/*
 * (C) Copyright IBM Corp. 1998-2004.  All Rights Reserved.
 *
 * The program is provided "as is" without any warranty express or
 * implied, including the warranty of non-infringement and the implied
 * warranties of merchantibility and fitness for a particular purpose.
 * IBM will not be liable for any damages suffered by you as a result
 * of using the Program. In no event will IBM be liable for any
 * special, indirect or consequential damages or lost profits even if
 * IBM has been advised of the possibility of their occurrence. IBM
 * will not be liable for any third party claims against you.
 */
/*
    7/1/97 - caret blinks

    7/3/97 - fAnchor is no longer restricted to the start or end of the selection. {jbr}
            Also, removed fVisible - it was identical to enabled().
*/

package com.ibm.richtext.textpanel;

import java.awt.Graphics;
import java.awt.Color;
import java.awt.Rectangle;

import java.text.BreakIterator;

import java.awt.event.MouseEvent;
import java.awt.event.KeyEvent;
import java.awt.event.FocusEvent;

import com.ibm.richtext.styledtext.MConstText;
import com.ibm.richtext.textformat.TextOffset;

import com.ibm.richtext.textformat.MFormatter;

class TextSelection extends Behavior implements Runnable {
    static final String COPYRIGHT =
                "(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
    static final Color          HIGHLIGHTCOLOR = Color.pink;

    private TextComponent       fTextComponent;
    private MConstText          fText;
    private TextOffset          fStart;
    private TextOffset          fLimit;
    private TextOffset          fAnchor;
    private TextOffset          fUpDownAnchor = null;
    private BreakIterator       fBoundaries = null;
    private Color               fHighlightColor = HIGHLIGHTCOLOR;
    private PanelEventBroadcaster   fListener;
    private RunStrategy         fRunStrategy;
    private boolean             fMouseDown = false;
    private boolean             fHandlingKeyOrCommand = false;
    
    private boolean fCaretShouldBlink;
    private boolean fCaretIsVisible;
    private int fCaretCount;

    // formerly in base class
    private boolean fEnabled;

    private MouseEvent fPendingMouseEvent = null;

    private static final int kCaretInterval = 500;

    public void run() {

        final Runnable blinkCaret = new Runnable() {
            public void run() {
                fCaretIsVisible = !fCaretIsVisible;
                Graphics g = fTextComponent.getGraphics();
                if (g != null) {
                    //System.out.println("caretIsVisible: " + fCaretIsVisible);
                    drawSelection(g, fCaretIsVisible);
                }
                else {
                    // Not sure what else to do:
                    fCaretShouldBlink = false;
                }
            }
        };
        
        // blink caret
        while (true) {

            synchronized(this) {

                while (!fCaretShouldBlink) {
                    try {
                        wait();
                    }
                    catch(InterruptedException e) {
                        System.out.println("Caught InterruptedException in caret thread.");
                    }
                }

                ++fCaretCount;

                if (fCaretCount % 2 == 0) {
                    fRunStrategy.doIt(blinkCaret);
                }
            }

            try {
                Thread.sleep(kCaretInterval);
            }
            catch(InterruptedException e) {
            }
        }
    }



    public TextSelection(TextComponent textComponent,
                         PanelEventBroadcaster listener,
                         RunStrategy runStrategy) {
                            
        fTextComponent = textComponent;
        fText = textComponent.getText();
        fListener = listener;
        fRunStrategy = runStrategy;
        
        fStart = new TextOffset();
        fLimit = new TextOffset();
        fAnchor = new TextOffset();
        fMouseDown = false;

        fCaretCount = 0;
        fCaretIsVisible = true;
        fCaretShouldBlink = false;
        setEnabled(false);

        Thread caretThread = new Thread(this);
        caretThread.setDaemon(true);
        caretThread.start();
    }

    boolean enabled() {

        return fEnabled;
    }

    private void setEnabled(boolean enabled) {

        fEnabled = enabled;
    }

    public boolean textControlEventOccurred(Behavior.EventType event, Object what) {

        boolean result;
        fHandlingKeyOrCommand = true;
        
        if (event == Behavior.SELECT) {
            select((TextRange) what);
            result = true;
        }
        else if (event == Behavior.COPY) {
            fTextComponent.getClipboard().setContents(fText.extract(fStart.fOffset, fLimit.fOffset));
            fListener.textStateChanged(TextPanelEvent.CLIPBOARD_CHANGED);
            result = true;
        }
        else {
            result = false;
        }
        
        fHandlingKeyOrCommand = false;
        return result;
    }

    protected void advanceToNextBoundary(TextOffset offset) {
    
        // If there's no boundaries object, or if position at the end of the
        // document, return the offset unchanged
        if (fBoundaries == null) {
            return;
        }
        
        int position = offset.fOffset;
        
        if (position >= fText.length()) {
            return;
        }

        // If position is at a boundary and offset is before position,
        // leave it unchanged.  Otherwise move to next boundary.
        int nextPos = fBoundaries.following(position);
        if (fBoundaries.previous() == position && 
                offset.fPlacement==TextOffset.BEFORE_OFFSET) {
            return;
        }
        
        offset.setOffset(nextPos, TextOffset.AFTER_OFFSET);
    }

    protected void advanceToPreviousBoundary(TextOffset offset) {
    
        advanceToPreviousBoundary(offset, false);
    }
    
    private void advanceToPreviousBoundary(TextOffset offset, boolean alwaysMove) {
        // if there's no boundaries object, or if we're sitting at the beginning
        // of the document, return the offset unchanged
        if (fBoundaries == null) {
            return;
        }
        
        int position = offset.fOffset;

        if (position == 0) {
            return;
        }
        
        // If position is at a boundary, leave it unchanged.  Otherwise
        // move to previous boundary.
        if (position == fText.length()) {
            fBoundaries.last();
        }
        else {
            fBoundaries.following(position);
        }
        
        int prevPos = fBoundaries.previous();
        
        if (prevPos == position) {
            if (!alwaysMove && offset.fPlacement==TextOffset.AFTER_OFFSET) {
                return;
            }

            prevPos = fBoundaries.previous();
        }
                
        // and finally update the real offset with this new position we've found
        offset.setOffset(prevPos, TextOffset.AFTER_OFFSET);
    }

    private void doArrowKey(KeyEvent e, int key) {

        // when there's a selection range, the left and up arrow keys place an
        // insertion point at the beginning of the range, and the right and down
        // keys place an insertion point at the end of the range (unless the shift
        // key is down, of course)

        if (!fStart.equals(fLimit) && !e.isShiftDown()) {
            if (key == KeyEvent.VK_LEFT || key == KeyEvent.VK_UP)
                setSelRangeAndDraw(fStart, fStart, fStart);
            else
                setSelRangeAndDraw(fLimit, fLimit, fLimit);
        }
        else {
            if (!fAnchor.equals(fStart))
                fAnchor.assign(fLimit);

            TextOffset  liveEnd = (fStart.equals(fAnchor)) ? fLimit : fStart;
            TextOffset  newPos = new TextOffset();

            // if the control key is down, the left and right arrow keys move by whole
            // word in the appropriate direction (we use a line break object so that we're
            // not treating spaces and punctuation as words)
            if (e.isControlDown() && (key == KeyEvent.VK_LEFT || key == KeyEvent.VK_RIGHT)) {
                fUpDownAnchor = null;
                fBoundaries = BreakIterator.getLineInstance();
                fBoundaries.setText(fText.createCharacterIterator());

                newPos.assign(liveEnd);
                if (key == KeyEvent.VK_RIGHT)
                    advanceToNextBoundary(newPos);
                else
                    advanceToPreviousBoundary(newPos, true);
            }

            // if we get down to here, this is a plain-vanilla insertion-point move,
            // or the shift key is down and we're extending or shortening the selection
            else {

                // fUpDownAnchor is used to keep track of the horizontal position
                // across a run of up or down arrow keys (this prevents accumulated
                // error from destroying our horizontal position)
                if (key == KeyEvent.VK_LEFT || key == KeyEvent.VK_RIGHT)
                    fUpDownAnchor = null;
                else {
                    if (fUpDownAnchor == null) {
                        fUpDownAnchor = new TextOffset(liveEnd);
                    }
                }

                short   direction = MFormatter.eRight;  // just to have a default...

                switch (key) {
                    case KeyEvent.VK_UP: direction = MFormatter.eUp; break;
                    case KeyEvent.VK_DOWN: direction = MFormatter.eDown; break;
                    case KeyEvent.VK_LEFT: direction = MFormatter.eLeft; break;
                    case KeyEvent.VK_RIGHT: direction = MFormatter.eRight; break;
                }

                // use the formatter to determine the actual effect of the arrow key
                fTextComponent.findNewInsertionOffset(newPos, fUpDownAnchor, liveEnd, direction);
            }

            // if the shift key is down, the selection range is from the anchor point
            // the site of the last insertion point or the beginning point of the last
            // selection drag operation) to the newly-calculated position; if the
            // shift key is down, the newly-calculated position is the insertion point position
            if (!e.isShiftDown())
                setSelRangeAndDraw(newPos, newPos, newPos);
            else {
                if (newPos.lessThan(fAnchor))
                    setSelRangeAndDraw(newPos, fAnchor, fAnchor);
                else
                    setSelRangeAndDraw(fAnchor, newPos, fAnchor);
            }
        }

        scrollToShowSelectionEnd();
        fBoundaries = null;
    }

    private void doEndKey(KeyEvent e) {
        // ctrl-end moves the insertsion point to the end of the document,
        // ctrl-shift-end extends the selection so that it ends at the end
        // of the document

        TextOffset activeEnd, anchor;

        if (fAnchor.equals(fStart)) {
            activeEnd = new TextOffset(fStart);
            anchor = new TextOffset(fLimit);
        }
        else {
            activeEnd = new TextOffset(fLimit);
            anchor = new TextOffset(fStart);
        }

        if (e.isControlDown()) {
            TextOffset end = new TextOffset(fText.length(), TextOffset.BEFORE_OFFSET);

            if (e.isShiftDown())
                setSelRangeAndDraw(anchor, end, anchor);
            else
                setSelRangeAndDraw(end, end, end);
        }

        // end moves the insertion point to the end of the line containing
        // the end of the current selection
        // shift-end extends the selection to the end of the line containing
        // the end of the current selection

        else {

            int oldOffset = activeEnd.fOffset;

            activeEnd.fOffset = fTextComponent.lineRangeLimit(fTextComponent.lineContaining(activeEnd));
            activeEnd.fPlacement = TextOffset.BEFORE_OFFSET;

            if (fText.paragraphLimit(oldOffset) == activeEnd.fOffset &&
                    activeEnd.fOffset != fText.length() && activeEnd.fOffset > oldOffset) {
                activeEnd.fOffset--;
                activeEnd.fPlacement = TextOffset.AFTER_OFFSET;
            }

            if (!e.isShiftDown())
                setSelRangeAndDraw(activeEnd, activeEnd, activeEnd);
            else {
                if (activeEnd.lessThan(anchor))
                    setSelRangeAndDraw(activeEnd, anchor, anchor);
                else
                    setSelRangeAndDraw(anchor, activeEnd, anchor);
            }
        }

        scrollToShowSelectionEnd();
        fBoundaries = null;
        fUpDownAnchor = null;
    }

    private void doHomeKey(KeyEvent e) {
        // ctrl-home moves the insertion point to the beginning of the document,
        // ctrl-shift-home extends the selection so that it begins at the beginning
        // of the document

        TextOffset activeEnd, anchor;

        if (fAnchor.equals(fStart)) {
            activeEnd = new TextOffset(fStart);
            anchor = new TextOffset(fLimit);
        }
        else {
            activeEnd = new TextOffset(fLimit);
            anchor = new TextOffset(fStart);
        }

        if (e.isControlDown()) {

            TextOffset start = new TextOffset(0, TextOffset.AFTER_OFFSET);
            if (e.isShiftDown())
                setSelRangeAndDraw(start, anchor, anchor);
            else
                setSelRangeAndDraw(start, start, start);
        }

        // home moves the insertion point to the beginning of the line containing
        // the beginning of the current selection
        // shift-home extends the selection to the beginning of the line containing
        // the beginning of the current selection

        else {

            activeEnd.fOffset = fTextComponent.lineRangeLow(fTextComponent.lineContaining(activeEnd));
            activeEnd.fPlacement = TextOffset.AFTER_OFFSET;

            if (!e.isShiftDown())
                setSelRangeAndDraw(activeEnd, activeEnd, activeEnd);
            else {
                if (activeEnd.lessThan(anchor))
                    setSelRangeAndDraw(activeEnd, anchor, anchor);
                else
                    setSelRangeAndDraw(anchor, activeEnd, anchor);
            }
        }

        scrollToShowSelectionEnd();
        fBoundaries = null;
        fUpDownAnchor = null;
    }

    /** draws or erases the current selection
    * Draws or erases the highlight region or insertion caret for the current selection
    * range.
    * @param g The graphics environment to draw into
    * @param visible If true, draw the selection; if false, erase it
    */
    protected void drawSelection(Graphics g, boolean visible) {
        drawSelectionRange(g, fStart, fLimit, visible);
    }

    /** draws or erases a selection highlight at the specfied positions
    * Draws or erases a selection highlight or insertion caret corresponding to
    * the specified selecion range
    * @param g The graphics environment to draw into.  If null, this method does nothing.
    * @param start The beginning of the range to highlight
    * @param limit The end of the range to highlight
    * @param vsible If true, draw; if false, erase
    */
    protected void drawSelectionRange(  Graphics    g,
                                        TextOffset  start,
                                        TextOffset  limit,
                                        boolean     visible) {
        if (g == null) {
            return;
        }
        Rectangle   selBounds = fTextComponent.getBoundingRect(start, limit);

        selBounds.width = Math.max(1, selBounds.width);
        selBounds.height = Math.max(1, selBounds.height);

        fTextComponent.drawText(g, selBounds, visible, start, limit, fHighlightColor);
    }

    protected TextOffset getAnchor() {
        return fAnchor;
    }

    public TextOffset getEnd() {
        return fLimit;
    }

    public Color getHighlightColor() {
        return fHighlightColor;
    }

    public TextOffset getStart() {
        return fStart;
    }

    public TextRange getSelectionRange() {

        return new TextRange(fStart.fOffset, fLimit.fOffset);
    }

    public boolean focusGained(FocusEvent e) {

        setEnabled(true);
        drawSelection(fTextComponent.getGraphics(), true);

        restartCaretBlinking(true);
        if (fPendingMouseEvent != null) {
            mousePressed(fPendingMouseEvent);
            fPendingMouseEvent = null;
        }
        fListener.textStateChanged(TextPanelEvent.CLIPBOARD_CHANGED);
 
        return true;
    }

    public boolean focusLost(FocusEvent e) {
        stopCaretBlinking();
        setEnabled(false);
        drawSelection(fTextComponent.getGraphics(), false);
        return true;
    }

    /**
     * Return true if the given key event can affect the selection
     * range.
     */
    public static boolean keyAffectsSelection(KeyEvent e) {

        if (e.getID() != KeyEvent.KEY_PRESSED) {
            return false;
        }

        int key = e.getKeyCode();

        switch (key) {
            case KeyEvent.VK_HOME:
            case KeyEvent.VK_END:
            case KeyEvent.VK_LEFT:
            case KeyEvent.VK_RIGHT:
            case KeyEvent.VK_UP:
            case KeyEvent.VK_DOWN:
                return true;

            default:
                return false;
        }
    }

    public boolean keyPressed(KeyEvent e) {

        fHandlingKeyOrCommand = true;
        int key = e.getKeyCode();
        boolean result = true;
        
        switch (key) {
            case KeyEvent.VK_HOME:
                doHomeKey(e);
                break;
                
            case KeyEvent.VK_END:
                doEndKey(e);
                break;

            case KeyEvent.VK_LEFT:
            case KeyEvent.VK_RIGHT:
            case KeyEvent.VK_UP:
            case KeyEvent.VK_DOWN:
                doArrowKey(e, key);
                break;
                
            default:
                fUpDownAnchor = null;
                result = false;
                break;
        }
        
        fHandlingKeyOrCommand = false;
        return result;
    }

    public boolean mousePressed(MouseEvent e) {

        if (!enabled()) {
            fPendingMouseEvent = e;
            fTextComponent.requestFocus();
            return false;
        }

        if (fMouseDown)
            throw new Error("fMouseDown is out of sync with mouse in TextSelection.");

        fMouseDown = true;
        stopCaretBlinking();

        int x = e.getX(), y = e.getY();
        boolean wasZeroLength = rangeIsZeroLength(fStart, fLimit, fAnchor);
        
        TextOffset current = fTextComponent.pointToTextOffset(null, x, y, null, true);
        TextOffset anchorStart = new TextOffset();
        TextOffset anchorEnd = new TextOffset();

        fUpDownAnchor = null;

        // if we're not extending the selection...
        if (!e.isShiftDown()) {

            // if there are multiple clicks, create the appopriate type of BreakIterator
            // object for finding text boundaries (single clicks don't use a BreakIterator
            // object)
            if (e.getClickCount() == 2)
                fBoundaries = BreakIterator.getWordInstance();
            else if (e.getClickCount() == 3)
                fBoundaries = BreakIterator.getSentenceInstance();
            else
                fBoundaries = null;

            // if we're using a BreakIterator object, use it to find the nearest boundaries
            // on either side of the mouse-click position and make them our anchor range
            if (fBoundaries != null)
                fBoundaries.setText(fText.createCharacterIterator());

            anchorStart.assign(current);
            advanceToPreviousBoundary(anchorStart);
            anchorEnd.assign(current);
            advanceToNextBoundary(anchorEnd);
        }

        // if we _are_ extending the selection, determine our anchor range as follows:
        // fAnchor is the start of the anchor range;
        // the next boundary (after fAnchor) is the limit of the anchor range.

        else {

            if (fBoundaries != null)
                fBoundaries.setText(fText.createCharacterIterator());

            anchorStart.assign(fAnchor);
            anchorEnd.assign(anchorStart);

            advanceToNextBoundary(anchorEnd);
        }

        SelectionDragInteractor interactor = new SelectionDragInteractor(this, 
                                                                         fTextComponent,
                                                                         fRunStrategy,
                                                                         anchorStart,
                                                                         anchorEnd,
                                                                         current,
                                                                         x,
                                                                         y,
                                                                         wasZeroLength);

        interactor.addToOwner(fTextComponent);

        return true;
    }

    public boolean mouseReleased(MouseEvent e) {

        fPendingMouseEvent = null;
        return false;
    }

    // drag interactor calls this
    void mouseReleased(boolean zeroLengthChange) {

        fMouseDown = false;

        if (zeroLengthChange) {
            fListener.textStateChanged(TextPanelEvent.SELECTION_EMPTY_CHANGED);
        }
        fListener.textStateChanged(TextPanelEvent.SELECTION_RANGE_CHANGED);
        fListener.textStateChanged(TextPanelEvent.SELECTION_STYLES_CHANGED);

        // if caret drawing during mouse drags is supressed, draw caret now.

        restartCaretBlinking(true);
    }


    /** draws the selection
    * Provided, of course, that the selection is visible, the adorner is enabled,
    * and we're calling it to adorn the view it actually belongs to
    * @param g The graphics environment to draw into
    * @return true if we actually drew
    */
    public boolean paint(Graphics g, Rectangle drawRect) {
        // don't draw anything unless we're enabled and the selection is visible
        if (!enabled())
            return false;

        fTextComponent.drawText(g, drawRect, true, fStart, fLimit, fHighlightColor);
        return true;
    }

    /** scrolls the view to reveal the live end of the selection
    * (i.e., the end that moves if you use the arrow keys with the shift key down)
    */
    public void scrollToShowSelection() {
        Rectangle   selRect = fTextComponent.getBoundingRect(fStart, fLimit);

        fTextComponent.scrollToShow(selRect);
    }

    /** scrolls the view to reveal the live end of the selection
    * (i.e., the end that moves if you use the arrow keys with the shift key down)
    */
    public void scrollToShowSelectionEnd() {
        TextOffset  liveEnd;
        // variable not used Point[]     points;
        Rectangle   caret;

        if (fAnchor.equals(fStart))
            liveEnd = fLimit;
        else
            liveEnd = fStart;

        //points = fTextComponent.textOffsetToPoint(liveEnd);
        //caret = new Rectangle(points[0]);
        //caret = caret.union(new Rectangle(points[1]));
        caret = fTextComponent.getCaretRect(liveEnd);
        fTextComponent.scrollToShow(caret);
    }

    private void select(TextRange range) {
        // variable not used int textLength = fTextComponent.getText().length();

        TextOffset start = new TextOffset(range.start);

        stopCaretBlinking();
        setSelRangeAndDraw(start, new TextOffset(range.limit), start);
        restartCaretBlinking(true);
    }

    public void setHighlightColor(Color newColor) {
        fHighlightColor = newColor;
        if (enabled())
            drawSelection(fTextComponent.getGraphics(), true);
    }
    
    static boolean rangeIsZeroLength(TextOffset start, TextOffset limit, TextOffset anchor) {
        
        return start.fOffset == limit.fOffset && anchor.fOffset == limit.fOffset;
    }

    // sigh... look out for aliasing
    public void setSelectionRange(TextOffset newStart, TextOffset newLimit, TextOffset newAnchor) {

        boolean zeroLengthChange = rangeIsZeroLength(newStart, newLimit, newAnchor) != 
                                    rangeIsZeroLength(fStart, fLimit, fAnchor);
        TextOffset tempNewAnchor;
        if (newAnchor == fStart || newAnchor == fLimit) {
            tempNewAnchor = new TextOffset(newAnchor); // clone in case of aliasing
        }
        else {
            tempNewAnchor = newAnchor;
        }

        // DEBUG {jbr}

        if (newStart.greaterThan(newLimit))
            throw new IllegalArgumentException("Selection limit is before selection start.");

        if (newLimit != fStart) {
            fStart.assign(newStart);
            fLimit.assign(newLimit);
        }
        else {
            fLimit.assign(newLimit);
            fStart.assign(newStart);
        }

        fAnchor.assign(tempNewAnchor);

        if (fStart.fOffset == fLimit.fOffset) {
            fStart.fPlacement = fAnchor.fPlacement;
            fLimit.fPlacement = fAnchor.fPlacement;
        }
        
        if (!fMouseDown) {
            if (zeroLengthChange) {
                fListener.textStateChanged(TextPanelEvent.SELECTION_EMPTY_CHANGED);
            }
            fListener.textStateChanged(TextPanelEvent.SELECTION_RANGE_CHANGED);
            if (fHandlingKeyOrCommand) {
                fListener.textStateChanged(TextPanelEvent.SELECTION_STYLES_CHANGED);
            }
        }
    }

    private void sortOffsets(TextOffset offsets[]) {

        int i, j;

        for (i=0; i < offsets.length-1; i++) {
            for (j=i+1; j < offsets.length; j++) {
                if (offsets[j].lessThan(offsets[i])) {
                    TextOffset temp = offsets[j];
                    offsets[j] = offsets[i];
                    offsets[i] = temp;
                }
            }
        }

        // DEBUG {jbr}
        for (i=0; i < offsets.length-1; i++)
            if (offsets[i].greaterThan(offsets[i+1]))
                throw new Error("sortOffsets failed!");
    }

    private Rectangle getSelectionChangeRect(
                                    TextOffset rangeStart, TextOffset rangeLimit,
                                    TextOffset oldStart, TextOffset oldLimit,
                                    TextOffset newStart, TextOffset newLimit,
                                    boolean drawIfInsPoint) {

        if (!rangeStart.equals(rangeLimit))
            return fTextComponent.getBoundingRect(rangeStart, rangeLimit);

        // here, rangeStart and rangeLimit are equal

        if (rangeStart.equals(oldLimit)) {

            // range start is OLD insertion point.  Redraw if caret is currently visible.

            if (fCaretIsVisible)
                return fTextComponent.getBoundingRect(rangeStart, rangeStart);
        }
        else if (rangeStart.equals(newLimit)) {

            // range start is NEW insertion point.

            if (drawIfInsPoint)
                return fTextComponent.getBoundingRect(rangeStart, rangeStart);
        }

        return null;
    }

    private static boolean rectanglesOverlapVertically(Rectangle r1, Rectangle r2) {
        
        if (r1 == null || r2 == null) {
            return false;
        }
        
        return r1.y <= r2.y + r2.height || r2.y <= r1.y + r1.height;
    }
    
    // Update to show new selection, redrawing as little as possible

    private void updateSelectionDisplay(
                            TextOffset oldStart, TextOffset oldLimit,
                            TextOffset newStart, TextOffset newLimit, boolean drawIfInsPoint) {

        //System.out.println("newStart:" + newStart + "; newLimit:" + newLimit);

        TextOffset off[] = new TextOffset[4];

        off[0] = oldStart;
        off[1] = oldLimit;
        off[2] = newStart;
        off[3] = newLimit;

        sortOffsets(off);

        Rectangle r1 = getSelectionChangeRect(off[0], off[1], oldStart, oldLimit, newStart, newLimit, drawIfInsPoint);
        Rectangle r2 = getSelectionChangeRect(off[2], off[3], oldStart, oldLimit, newStart, newLimit, drawIfInsPoint);

        boolean drawSelection = drawIfInsPoint || !newStart.equals(newLimit);

        if (rectanglesOverlapVertically(r1, r2)) {

            fTextComponent.drawText(fTextComponent.getGraphics(), r1.union(r2), drawSelection, newStart, newLimit, fHighlightColor);
        }
        else {
            if (r1 != null)
                fTextComponent.drawText(fTextComponent.getGraphics(), r1, drawSelection, newStart, newLimit, fHighlightColor);
            if (r2 != null)
                fTextComponent.drawText(fTextComponent.getGraphics(), r2, drawSelection, newStart, newLimit, fHighlightColor);
        }
    }

    public void setSelRangeAndDraw(TextOffset newStart, TextOffset newLimit, TextOffset newAnchor) {

        // if the old and new selection ranges are the same, don't do anything
        if (fStart.equals(newStart) && fLimit.equals(newLimit) && fAnchor.equals(newAnchor))
            return;

        if (enabled())
            stopCaretBlinking();

        // update the selection on screen if we're enabled and visible

        TextOffset oldStart = new TextOffset(fStart), oldLimit = new TextOffset(fLimit);

        setSelectionRange(newStart, newLimit, newAnchor);

        if (enabled()) {

                // To supress drawing a caret during a mouse drag, pass !fMouseDown instead of true:
                updateSelectionDisplay(oldStart, oldLimit, fStart, fLimit, true);
        }

        if (!fMouseDown && enabled())
            restartCaretBlinking(true);
    }

    public void stopCaretBlinking() {

        synchronized(this) {
            fCaretShouldBlink = false;
        }
    }

/**
* Resume blinking the caret, if the selection is an insertion point.
* @param caretIsVisible true if the caret is displayed when this is called.
* This method relies on the client to display (or not display) the caret.
*/
    public void restartCaretBlinking(boolean caretIsVisible) {

        synchronized(this) {
            fCaretShouldBlink = fStart.equals(fLimit);
            fCaretCount = 0;
            fCaretIsVisible = caretIsVisible;

            if (fCaretShouldBlink) {
                try {
                    notify();
                }
                catch (IllegalMonitorStateException e) {
                    System.out.println("Caught IllegalMonitorStateException: "+e);
                }
            }
        }
    }

    public void removeFromOwner() {

        stopCaretBlinking();
        super.removeFromOwner();
    }

}
