// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
 *******************************************************************************
 * Copyright (C) 1996-2010, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.dev.demo.impl;
import java.awt.AWTEventMulticaster;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.TextEvent;
import java.awt.event.TextListener;
import java.text.BreakIterator;

// LIU: Changed from final to non-final
public class DumbTextComponent extends Canvas
  implements KeyListener, MouseListener, MouseMotionListener, FocusListener
{
    
    /**
     * For serialization
     */
    private static final long serialVersionUID = 8265547730738652151L;

//    private transient static final String copyright =
//      "Copyright \u00A9 1998, Mark Davis. All Rights Reserved.";
    private transient static boolean DEBUG = false;

    private String contents = "";
    private Selection selection = new Selection();
    private int activeStart = -1;
    private boolean editable = true;

    private transient Selection tempSelection = new Selection();
    private transient boolean focus;
    private transient BreakIterator lineBreaker = BreakIterator.getLineInstance();
    private transient BreakIterator wordBreaker = BreakIterator.getWordInstance();
    private transient BreakIterator charBreaker = BreakIterator.getCharacterInstance();
    private transient int lineAscent;
    private transient int lineHeight;
    private transient int lineLeading;
    private transient int lastHeight = 10;
    private transient int lastWidth = 50;
    private static final int MAX_LINES = 200; // LIU: Use symbolic name
    private transient int[] lineStarts = new int[MAX_LINES]; // LIU
    private transient int lineCount = 1;

    private transient boolean valid = false;
    private transient FontMetrics fm;
    private transient boolean redoLines = true;
    private transient boolean doubleClick = false;
    private transient TextListener textListener;
    private transient ActionListener selectionListener;
    private transient Image cacheImage;
    private transient Dimension mySize;
    private transient int xInset = 5;
    private transient int yInset = 5;
    private transient Point startPoint = new Point();
    private transient Point endPoint = new Point();
    private transient Point caretPoint = new Point();
    private transient Point activePoint = new Point();
    
    //private transient static String clipBoard;

    private static final char CR = '\015'; // LIU

    // ============================================

    public DumbTextComponent() {
        addMouseListener(this);
        addMouseMotionListener(this);
        addKeyListener(this);
        addFocusListener(this);
        setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));

    }

// ================ Events ====================

    // public boolean isFocusTraversable() { return true; }

    public void addActionListener(ActionListener l) {
        selectionListener = AWTEventMulticaster.add(selectionListener, l);
    }

    public void removeActionListener(ActionListener l) {
        selectionListener = AWTEventMulticaster.remove(selectionListener, l);
    }

    public void addTextListener(TextListener l) {
        textListener = AWTEventMulticaster.add(textListener, l);
    }

    public void removeTextListener(TextListener l) {
        textListener = AWTEventMulticaster.remove(textListener, l);
    }

    private transient boolean pressed;

    public void mousePressed(MouseEvent e) {
        if (DEBUG) System.out.println("mousePressed");
        if (pressed) {
            select(e,false);
        } else {
            doubleClick = e.getClickCount() > 1;
            requestFocus();
            select(e, true);
            pressed = true;
        }
    }

    public void mouseDragged(MouseEvent e) {
        if (DEBUG) System.out.println("mouseDragged");
        select(e, false);
    }

    public void mouseReleased(MouseEvent e) {
        if (DEBUG) System.out.println("mouseReleased");
        pressed = false;
    }

    public void mouseEntered(MouseEvent e) {
        //if (pressed) select(e, false);
    }

    public void mouseExited(MouseEvent e){
        //if (pressed) select(e, false);
    }

    public void mouseClicked(MouseEvent e) {}
    public void mouseMoved(MouseEvent e) {}


    public void focusGained(FocusEvent e) {
        if (DEBUG) System.out.println("focusGained");
        focus = true;
        valid = false;
        repaint(16);
    }
    public void focusLost(FocusEvent e) {
        if (DEBUG) System.out.println("focusLost");
        focus = false;
        valid = false;
        repaint(16);
    }

    public void select(MouseEvent e, boolean first) {
        setKeyStart(-1);
        point2Offset(e.getPoint(), tempSelection);
        if (first) {
            if ((e.getModifiers() & InputEvent.SHIFT_MASK) == 0) {
                tempSelection.anchor = tempSelection.caret;
            }
        }
        // fix words
        if (doubleClick) {
            tempSelection.expand(wordBreaker);
        }
        select(tempSelection);
    }
    
    public void keyPressed(KeyEvent e) {
        int code = e.getKeyCode();
        if (DEBUG) System.out.println("keyPressed "
          + hex((char)code) + ", " + hex((char)e.getModifiers()));
        int start = selection.getStart();
        int end = selection.getEnd();
        boolean shift = (e.getModifiers() & InputEvent.SHIFT_MASK) != 0;
        boolean ctrl = (e.getModifiers() & InputEvent.CTRL_MASK) != 0;
                
        switch (code) {
        case KeyEvent.VK_Q:
            if (!ctrl || !editable) break;
            setKeyStart(-1);
            fixHex();
            break;
        case KeyEvent.VK_V:
            if (!ctrl) break;
            if (!editable) {
                this.getToolkit().beep();
            } else {
                paste();
            }
            break;
        case KeyEvent.VK_C:
            if (!ctrl) break;
            copy();
            break;
        case KeyEvent.VK_X:
            if (!ctrl) break;
            if (!editable) {
                this.getToolkit().beep();
            } else {
                copy();
                insertText("");
            }
            break;
        case KeyEvent.VK_A:
            if (!ctrl) break;
            setKeyStart(-1);
            select(Integer.MAX_VALUE, 0, false);
            break;
        case KeyEvent.VK_RIGHT:
            setKeyStart(-1);
            tempSelection.set(selection);
            tempSelection.nextBound(ctrl ? wordBreaker : charBreaker, +1, shift);
            select(tempSelection);
            break;
        case KeyEvent.VK_LEFT:
            setKeyStart(-1);
            tempSelection.set(selection);
            tempSelection.nextBound(ctrl ? wordBreaker : charBreaker, -1, shift);
            select(tempSelection);
            break;
        case KeyEvent.VK_UP: // LIU: Add support for up arrow
            setKeyStart(-1);
            tempSelection.set(selection);
            tempSelection.caret = lineDelta(tempSelection.caret, -1);
            if (!shift) {
                tempSelection.anchor = tempSelection.caret;
            }
            select(tempSelection);
            break;
        case KeyEvent.VK_DOWN: // LIU: Add support for down arrow
            setKeyStart(-1);
            tempSelection.set(selection);
            tempSelection.caret = lineDelta(tempSelection.caret, +1);
            if (!shift) {
                tempSelection.anchor = tempSelection.caret;
            }
            select(tempSelection);
            break;
        case KeyEvent.VK_DELETE: // LIU: Add delete key support
            if (!editable) break;
            setKeyStart(-1);
            if (contents.length() == 0) break;
            start = selection.getStart();
            end = selection.getEnd();
            if (start == end) {
                ++end;
                if (end > contents.length()) {
                    getToolkit().beep();
                    return;
                }
            }
            replaceRange("", start, end);
            break;            
        }
    }

    void copy() {
        Clipboard cb = this.getToolkit().getSystemClipboard();
        StringSelection ss = new StringSelection(
            contents.substring(selection.getStart(), selection.getEnd()));
        cb.setContents(ss, ss);
    }
    
    void paste () {
        Clipboard cb = this.getToolkit().getSystemClipboard();
        Transferable t = cb.getContents(this);
        if (t == null) {
            this.getToolkit().beep();
            return;
        }
        try {
            String temp = (String) t.getTransferData(DataFlavor.stringFlavor);
            insertText(temp);
        } catch (Exception e) {
            this.getToolkit().beep();
        }            
    }

    /**
     * LIU: Given an offset into contents, moves up or down by lines,
     * according to lineStarts[].
     * @param off the offset into contents
     * @param delta how many lines to move up (< 0) or down (> 0)
     * @return the new offset into contents
     */
    private int lineDelta(int off, int delta) {
        int line = findLine(off, false);
        int posInLine = off - lineStarts[line];
        // System.out.println("off=" + off + " at " + line + ":" + posInLine);
        line += delta;
        if (line < 0) {
            line = posInLine = 0;
        } else if (line >= lineCount) {
            return contents.length();
        }
        off = lineStarts[line] + posInLine;
        if (off >= lineStarts[line+1]) {
            off = lineStarts[line+1] - 1;
        }
        return off;
    }
      
    public void keyReleased(KeyEvent e) {
        int code = e.getKeyCode();
        if (DEBUG) System.out.println("keyReleased "
          + hex((char)code) + ", " + hex((char)e.getModifiers()));
    }

    public void keyTyped(KeyEvent e) {
        char ch = e.getKeyChar();
        if (DEBUG) System.out.println("keyTyped "
          + hex((char)ch) + ", " + hex((char)e.getModifiers()));
        if ((e.getModifiers() & InputEvent.CTRL_MASK) != 0) return;
        int start, end;
        switch (ch) {
        case KeyEvent.CHAR_UNDEFINED:
            break;
        case KeyEvent.VK_BACK_SPACE:
            //setKeyStart(-1);
            if (!editable) break;
            if (contents.length() == 0) break;
            start = selection.getStart();
            end = selection.getEnd();
            if (start == end) {
                --start;
                if (start < 0) {
                    getToolkit().beep(); // LIU: Add audio feedback of NOP
                    return;
                }
            }
            replaceRange("", start, end);
            break;        
        case KeyEvent.VK_DELETE:
            //setKeyStart(-1);
            if (!editable) break;
            if (contents.length() == 0) break;
            start = selection.getStart();
            end = selection.getEnd();
            if (start == end) {
                ++end;
                if (end > contents.length()) {
                    getToolkit().beep(); // LIU: Add audio feedback of NOP
                    return;
                }
            }
            replaceRange("", start, end);
            break;
        default:
            if (!editable) break;
            // LIU: Dispatch to subclass API
            handleKeyTyped(e);
            break;
        }
    }

    // LIU: Subclass API for handling of key typing
    protected void handleKeyTyped(KeyEvent e) {
        insertText(String.valueOf(e.getKeyChar()));
    }
    
    protected void setKeyStart(int keyStart) {
        if (activeStart != keyStart) {
            activeStart = keyStart;
            repaint(10);
        }
    }
    
    protected void validateKeyStart() {
        if (activeStart > selection.getStart()) {
            activeStart = selection.getStart();
            repaint(10);
        }
    }
    
    protected int getKeyStart() {
        return activeStart;
    }

// ===================== Control ======================

    public synchronized void setEditable(boolean b) {
        editable = b;
    }

    public boolean isEditable() {
        return editable;
    }

    public void select(Selection newSelection) {
        newSelection.pin(contents);
        if (!selection.equals(newSelection)) {
            selection.set(newSelection);
            if (selectionListener != null) {
                selectionListener.actionPerformed(
                  new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
                    "Selection Changed", 0));
            }
            repaint(10);
            valid = false;
        }
    }

    public void select(int start, int end) {
        select(start, end, false);
    }

    public void select(int start, int end, boolean clickAfter) {
        tempSelection.set(start, end, clickAfter);
        select(tempSelection);
    }

    public int getSelectionStart() {
        return selection.getStart();
    }

    public int getSelectionEnd() {
        return selection.getEnd();
    }

    public void setBounds(int x, int y, int w, int h) {
        super.setBounds(x,y,w,h);
        redoLines = true;
    }

    public Dimension getPreferredSize() {
        return new Dimension(lastWidth,lastHeight);
    }

    public Dimension getMaximumSize() {
        return new Dimension(lastWidth,lastHeight);
    }

    public Dimension getMinimumSize() {
        return new Dimension(lastHeight,lastHeight);
    }

    public void setText(String text) {
        setText2(text);
        select(tempSelection.set(selection).pin(contents));
    }

    public void setText2(String text) {
        contents = text;
        charBreaker.setText(text);
        wordBreaker.setText(text);
        lineBreaker.setText(text);
        redoLines = true;
        if (textListener != null)
            textListener.textValueChanged(
              new TextEvent(this, TextEvent.TEXT_VALUE_CHANGED));
        repaint(16);
    }

    public void insertText(String text) {
        if (activeStart == -1) activeStart = selection.getStart();
        replaceRange(text, selection.getStart(), selection.getEnd());
    }

    public void replaceRange(String s, int start, int end) {
        setText2(contents.substring(0,start) + s
          + contents.substring(end));
        select(tempSelection.set(selection).
          fixAfterReplace(start, end, s.length()));
        validateKeyStart();
    }

    public String getText() {
        return contents;
    }

    public void setFont(Font font) {
        super.setFont(font);
        redoLines = true;
        repaint(16);
    }

    // ================== Graphics ======================

    public void update(Graphics g) {
        if (DEBUG) System.out.println("update");
        paint(g);
    }

    public void paint(Graphics g) {
        mySize = getSize();
        if (cacheImage == null
          || cacheImage.getHeight(this) != mySize.height
          || cacheImage.getWidth(this) != mySize.width) {
            cacheImage = createImage(mySize.width, mySize.height);
            valid = false;
        }
        if (!valid || redoLines) {
            if (DEBUG) System.out.println("painting");
            paint2(cacheImage.getGraphics());
            valid = true;
        }
        //getToolkit().sync();
        if (DEBUG) System.out.println("copying");
        g.drawImage(cacheImage,
          0, 0, mySize.width, mySize.height,
          0, 0, mySize.width, mySize.height,
          this);
    }

    public void paint2(Graphics g) {
        g.clearRect(0, 0, mySize.width, mySize.height);
        if (DEBUG) System.out.println("print");
        if (focus) g.setColor(Color.black);
        else g.setColor(Color.gray);
        g.drawRect(0,0,mySize.width-1,mySize.height-1);
        g.setClip(1,1,
          mySize.width-2,mySize.height-2);
        g.setColor(Color.black);
        g.setFont(getFont());
        fm = g.getFontMetrics();
        lineAscent = fm.getAscent();
        lineLeading = fm.getLeading();
        lineHeight = lineAscent + fm.getDescent() + lineLeading;
        int y = yInset + lineAscent;
        String lastSubstring = "";
        if (redoLines) fixLineStarts(mySize.width-xInset-xInset);
        for (int i = 0; i < lineCount; y += lineHeight, ++i) {
            // LIU: Don't display terminating ^M characters
            int lim = lineStarts[i+1];
            if (lim > 0 && contents.length() > 0 &&
                contents.charAt(lim-1) == CR) --lim;
            lastSubstring = contents.substring(lineStarts[i],lim);
            g.drawString(lastSubstring, xInset, y);
        }
        drawSelection(g, lastSubstring);
        lastHeight = y + yInset - lineHeight + yInset;
        lastWidth = mySize.width-xInset-xInset;
    }

    void paintRect(Graphics g, int x, int y, int w, int h) {
        if (focus) {
            g.fillRect(x, y, w, h);
        } else {
            g.drawRect(x, y, w-1, h-1);
        }
    }

    public void drawSelection(Graphics g, String lastSubstring) {
        g.setXORMode(Color.black);
        if (activeStart != -1) {
            offset2Point(activeStart, false, activePoint);
            g.setColor(Color.magenta);
            int line = activePoint.x - 1;
            g.fillRect(line, activePoint.y, 1, lineHeight);
        }
        if (selection.isCaret()) {
            offset2Point(selection.caret, selection.clickAfter, caretPoint);
        } else {
            if (focus) g.setColor(Color.blue);
            else g.setColor(Color.yellow);
            offset2Point(selection.getStart(), true, startPoint);
            offset2Point(selection.getEnd(), false, endPoint);
            if (selection.getStart() == selection.caret)
                caretPoint.setLocation(startPoint);
            else caretPoint.setLocation(endPoint);
            if (startPoint.y == endPoint.y) {
                paintRect(g, startPoint.x, startPoint.y,
                  Math.max(1,endPoint.x-startPoint.x), lineHeight);
            } else {
                paintRect(g, startPoint.x, startPoint.y,
                  (mySize.width-xInset)-startPoint.x, lineHeight);
                if (startPoint.y + lineHeight < endPoint.y)
                  paintRect(g, xInset, startPoint.y + lineHeight,
                  (mySize.width-xInset)-xInset, endPoint.y - startPoint.y - lineHeight);
                paintRect(g, xInset, endPoint.y, endPoint.x-xInset, lineHeight);
            }
        }
        if (focus || selection.isCaret()) {
            if (focus) g.setColor(Color.green);
            else g.setColor(Color.red);
            int line = caretPoint.x - (selection.clickAfter ? 0 : 1);
            g.fillRect(line, caretPoint.y, 1, lineHeight);
            int w = lineHeight/12 + 1;
            int braces = line - (selection.clickAfter ? -1 : w);
            g.fillRect(braces, caretPoint.y, w, 1);
            g.fillRect(braces, caretPoint.y + lineHeight - 1, w, 1);
        }
    }

    public Point offset2Point(int off, boolean start, Point p) {
        int line = findLine(off, start);
        int width = 0;
        try {
            width = fm.stringWidth(
              contents.substring(lineStarts[line], off));
        } catch (Exception e) {
            System.out.println(e);
        }
        p.x = width + xInset;
        if (p.x > mySize.width - xInset)
            p.x = mySize.width - xInset;
        p.y = lineHeight * line + yInset;
        return p;
    }

    private int findLine(int off, boolean start) {
        // if it is start, then go to the next line!
        if (start) ++off;
        for (int i = 1; i < lineCount; ++i) {
            // LIU: This was <= ; changed to < to make caret after
            // final CR in line appear at START of next line.
            if (off < lineStarts[i]) return i-1;
        }
        // LIU: Check for special case; after CR at end of the last line
        if (off == lineStarts[lineCount] &&
            off > 0 && contents.length() > 0 && contents.charAt(off-1) == CR) {
            return lineCount;
        }
        return lineCount-1;
    }

    // offsets on any line will go from start,true to end,false
    // excluding start,false and end,true
    public Selection point2Offset(Point p, Selection o) {
        if (p.y < yInset) {
            o.caret = 0;
            o.clickAfter = true;
            return o;
        }
        int line = (p.y - yInset)/lineHeight;
        if (line >= lineCount) {
            o.caret = contents.length();
            o.clickAfter = false;
            return o;
        }
        int target = p.x - xInset;
        if (target <= 0) {
            o.caret = lineStarts[line];
            o.clickAfter = true;
            return o;
        }
        int lowGuess = lineStarts[line];
        int lowWidth = 0;
        int highGuess = lineStarts[line+1];
        int highWidth = fm.stringWidth(contents.substring(lineStarts[line],highGuess));
        if (target >= highWidth) {
            o.caret = lineStarts[line+1];
            o.clickAfter = false;
            return o;
        }
        while (lowGuess < highGuess - 1) {
            int guess = (lowGuess + highGuess)/2;
            int width = fm.stringWidth(contents.substring(lineStarts[line],guess));
            if (width <= target) {
                lowGuess = guess;
                lowWidth = width;
                if (width == target) break;
            } else {
                highGuess = guess;
                highWidth = width;
            }
        }
        // at end, either lowWidth < target < width(low+1), or lowWidth = target
        int highBound = charBreaker.following(lowGuess);
        int lowBound = charBreaker.previous();
        // we are now at character boundaries
        if (lowBound != lowGuess)
            lowWidth = fm.stringWidth(contents.substring(lineStarts[line],lowBound));
        if (highBound != highGuess)
            highWidth = fm.stringWidth(contents.substring(lineStarts[line],highBound));
        // we now have the right widths
        if (target - lowWidth < highWidth - target) {
            o.caret = lowBound;
            o.clickAfter = true;
        } else {
            o.caret = highBound;
            o.clickAfter = false;
        }
        // we now have the closest!
        return o;
    }

    private void fixLineStarts(int width) {
        lineCount = 1;
        lineStarts[0] = 0;
        if (contents.length() == 0) {
            lineStarts[1] = 0;
            return;
        }
        int end = 0;
        // LIU: Add check for MAX_LINES
        for (int start = 0; start < contents.length() && lineCount < MAX_LINES;
             start = end) {
            end = nextLine(fm, start, width);
            lineStarts[lineCount++] = end;
            if (end == start) { // LIU: Assertion
                throw new RuntimeException("nextLine broken");
            }
        }
        --lineCount;
        redoLines = false;
    }

    // LIU: Enhanced to wrap long lines.  Bug with return of start fixed.
    public int nextLine(FontMetrics fMtr, int start, int width) {
        int len = contents.length();
        for (int i = start; i < len; ++i) {
            // check for line separator
            char ch = (contents.charAt(i));
            if (ch >= 0x000A && ch <= 0x000D || ch == 0x2028 || ch == 0x2029) {
                len = i + 1;
                if (ch == 0x000D && i+1 < len && contents.charAt(i+1) == 0x000A) // crlf
                    ++len; // grab extra char
                break;
            }
        }
        String subject = contents.substring(start,len);
        if (visibleWidth(fMtr, subject) <= width)
          return len;

        // LIU: Remainder of this method rewritten to accommodate lines
        // longer than the component width by first trying to break
        // into lines; then words; finally chars.
        int n = findFittingBreak(fMtr, subject, width, lineBreaker);
        if (n == 0) {
            n = findFittingBreak(fMtr, subject, width, wordBreaker);
        }
        if (n == 0) {
            n = findFittingBreak(fMtr, subject, width, charBreaker);
        }
        return n > 0 ? start + n : len;
    }

    /**
     * LIU: Finds the longest substring that fits a given width
     * composed of subunits returned by a BreakIterator.  If the smallest
     * subunit is too long, returns 0.
     * @param fMtr metrics to use
     * @param line the string to be fix into width
     * @param width line.substring(0, result) must be <= width
     * @param breaker the BreakIterator that will be used to find subunits
     * @return maximum characters, at boundaries returned by breaker,
     * that fit into width, or zero on failure
     */
    private int findFittingBreak(FontMetrics fMtr, String line, int width,
                                 BreakIterator breaker) {
        breaker.setText(line);
        int last = breaker.first();
        int end = breaker.next();
        while (end != BreakIterator.DONE &&
               visibleWidth(fMtr, line.substring(0, end)) <= width) {
            last = end;
            end = breaker.next();
        }
        return last;
    }

    public int visibleWidth(FontMetrics fMtr, String s) {
        int i;
        for (i = s.length()-1; i >= 0; --i) {
            char ch = s.charAt(i);
            if (!(ch == ' ' || ch >= 0x000A && ch <= 0x000D || ch == 0x2028 || ch == 0x2029))
                return fMtr.stringWidth(s.substring(0,i+1));
        }
        return 0;
    }

// =============== Utility ====================

    private void fixHex() {
        if (selection.getEnd() == 0) return;
        int store = 0;
        int places = 1;
        int count = 0;
        int min = Math.min(8,selection.getEnd());
        for (int i = 0; i < min; ++i) {
            char ch = contents.charAt(selection.getEnd()-1-i);
            int value = Character.getNumericValue(ch);
            if (value < 0 || value > 15) break;
            store += places * value;
            ++count;
            places *= 16;
        }
        String add = "";
        int bottom = store & 0xFFFF;
        if (store >= 0xD8000000 && store < 0xDC000000
          && bottom >= 0xDC00 && bottom < 0xE000) { // surrogates
            add = "" + (char)(store >> 16) + (char)bottom;
        } else if (store > 0xFFFF && store <= 0x10FFFF) {
            store -= 0x10000;
            add = "" + (char)(((store >> 10) & 0x3FF) + 0xD800)
              + (char)((store & 0x3FF) + 0xDC00);
              
        } else if (count >= 4) {
            count = 4;
            add = ""+(char)(store & 0xFFFF);
        } else {
            count = 1;
            char ch = contents.charAt(selection.getEnd()-1);
            add = hex(ch);
            if (ch >= 0xDC00 && ch <= 0xDFFF && selection.getEnd() > 1) {
                ch = contents.charAt(selection.getEnd()-2);
                if (ch >= 0xD800 && ch <= 0xDBFF) {
                    count = 2;
                    add = hex(ch) + add;
                }
            }
        }
        replaceRange(add, selection.getEnd()-count, selection.getEnd());
    }

    public static String hex(char ch) {
        String result = Integer.toString(ch,16).toUpperCase();
        result = "0000".substring(result.length(),4) + result;
        return result;
    }
}
