/*
 * @(#)$RCSfile: TextComponent.java,v $ $Revision: 1.5 $ $Date: 2002/02/16 03:06:47 $
 *
 * (C) Copyright IBM Corp. 1998-1999.  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.
 */
package com.ibm.richtext.textpanel;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;

import java.awt.event.ComponentAdapter;
import java.awt.event.FocusListener;
import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

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

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

import com.ibm.richtext.textformat.MFormatter;

import com.ibm.richtext.textlayout.attributes.AttributeMap;

class TextComponent extends FakeComponent
                    implements BehaviorOwner,
                    FocusListener,
                    KeyListener,
                    MouseListener,
                    MouseMotionListener,
                    Scroller.Client {

    static final String COPYRIGHT =
                "(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";

    public static final int WINDOW_WIDTH = -10;
    public static final int DEFAULT_INSET = 10;

    private static final Color STRONG_CARET_COLOR = Color.black;
    private static final Color WEAK_CARET_COLOR = Color.darkGray;

    private Behavior fBehavior;
    private MText fText;
    private StyledTextClipboard fClipboard;
    private boolean fScrolls;
    private Scroller fScroller;

    private DocumentView fDocumentView = null;

    // sigh - can't create DocumentView until addNotify() is called.
    // These values hold DocumentView ctor args
    private AttributeMap fDefaultValues;
    private boolean fViewWraps;
    private int fViewWrapWidth;
    private int fViewInsetAmount;
    
    private PanelEventBroadcaster fListener;

    /**
     * Create a new TextComponent.
     * @param text the text model.  This model will be used for
     * the life of the component, even if setText is called
     * @param wraps if true, the text is wrapped to the specified
     * wrapping width.  If false, the text wraps only at paragraph breaks.
     * @param wrapWidth ignored if wraps is false.  Text wraps to this width
     * unless the width is WINDOW_WIDTH, in which case text wraps to width
     * of this component. Should not be negative (unless it is WINDOW_WIDTH).
     * @param insetAmount the size of the margins around the text
     * @param clipboard the clipboard to use for cut/copy/paste operations.
     * If null, the component will use its own clipboard.
     */
    public TextComponent(MText text,
                         AttributeMap defaultValues,
                         boolean wraps,
                         int wrapWidth,
                         int insetAmount,
                         StyledTextClipboard clipboard,
                         boolean scrolls,
                         Scroller scroller,
                         PanelEventBroadcaster listener) {

        fBehavior = null;

        if (text == null) {
            throw new IllegalArgumentException("Text is null.");
        }

        fText = text;
        fDefaultValues = defaultValues;
        
        if (clipboard == null) {
            throw new IllegalArgumentException("Clipboard is null.");
        }
        fClipboard = clipboard;

        fScrolls = scrolls;

        fScroller = scroller;

        fDocumentView = null;

        fViewWrapWidth = wrapWidth;
        fViewWraps = wraps;
        fViewInsetAmount = insetAmount;
        fListener = listener;
    }
    
    AttributeMap getDefaultValues() {
    
        return fDefaultValues;
    }
    
    void setHost(Component component) {
        
        super.setHost(component);
        
        component.addFocusListener(this);
        component.addKeyListener(this);
        component.addMouseListener(this);
        component.addMouseMotionListener(this);
        
        component.addComponentListener(new ComponentAdapter() {        
            public void componentResized(ComponentEvent e) {
                if (fDocumentView != null) {
                    fDocumentView.hostSizeChanged();
                    scrollToShow(fDocumentView.getDocumentBounds());
                }
            }
        });
    }
    
    /**
     * ATextPanelImpl's use only!
     */
    Component getHost() {
    
        return fHost;
    }
    
    // Create document view here.  TextComponent isn't fully constructed
    // until this is called.
    // This must be called by host component!
    void addNotify() {

        Graphics g = getGraphics();
        if (g == null) {
            throw new Error("Graphics should be valid here but isn't.");
        }

        fDocumentView = new DocumentView(this,
                                         fText,
                                         fDefaultValues,
                                         fViewWraps,
                                         fViewWrapWidth,
                                         fViewInsetAmount,
                                         fListener);
        documentSizeChanged();
        fListener.textStateChanged(TextPanelEvent.FORMAT_WIDTH_CHANGED);
    }
    
    public Rectangle getBounds() {
        
        if (fHost != null) {
            return fHost.getBounds();
        }
        else {
            return new Rectangle(0, 0, 0, 0);
        }
    }
    
    Graphics getGraphics() {
        
        return (fHost==null)? null : fHost.getGraphics();
    }
    
    void requestFocus() {
        
        if (fHost != null) {
            fHost.requestFocus();
        }
    }

    // *** Behavior management ***
    public Behavior getBehavior() {
        return fBehavior;
    }

    public void setBehavior(Behavior b) {
        fBehavior = b;
    }


    // *** Events - just forward to behavior ***
    public void focusGained(FocusEvent event) {
        if (fBehavior != null)
            fBehavior.focusGained(event);
    }

    public void focusLost(FocusEvent event) {
        if (fBehavior != null)
            fBehavior.focusLost(event);
    }

    public void keyPressed(KeyEvent event) {
        if (fBehavior != null)
            fBehavior.keyPressed(event);
    }

    public void keyTyped(KeyEvent event) {

        if (fBehavior != null) {
            fBehavior.keyTyped(event);
        }
    }

    public void keyReleased(KeyEvent event) {
        if (fBehavior != null)
            fBehavior.keyReleased(event);
    }

    public void mouseClicked(MouseEvent event) {
        return;  // no behavior method for this
    }

    public void mouseDragged(MouseEvent event) {
        if (fBehavior != null)
            fBehavior.mouseDragged(event);
    }

    public void mouseEntered(MouseEvent event)  {
        if (fBehavior != null)
            fBehavior.mouseEntered(event);
    }

    public void mouseExited(MouseEvent event)  {
        if (fBehavior != null)
            fBehavior.mouseExited(event);
    }

    public void mouseMoved(MouseEvent event) {
        if (fBehavior != null)
            fBehavior.mouseMoved(event);
    }

    public void mousePressed(MouseEvent event) {
        if (fBehavior != null)
            fBehavior.mousePressed(event);
    }

    public void mouseReleased(MouseEvent event)  {
        if (fBehavior != null)
            fBehavior.mouseReleased(event);
    }

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

        boolean handled = false;

        if (fBehavior != null) {
            handled = fBehavior.textControlEventOccurred(event, what);
        }
        return handled;
    }


    // *** Scroll methods - called by Behaviors

    // viewStart, viewLimit is visible bounds of window
    // targetStart, targetLimit is the region to scroll into view
    private static int getScrollDifference(int viewStart,
                                           int viewLimit,
                                           int targetStart,
                                           int targetLimit) {

        if (viewStart <= targetStart) {
            if (viewLimit >= targetLimit) {
                return 0;
            }
            else {
                return Math.max(viewStart-targetStart, viewLimit-targetLimit);
            }
        }
        else if (viewLimit > targetLimit) {

            return viewLimit - targetLimit;
        }
        else {
            return 0;
        }
    }

    void scrollToShow(Rectangle showRect) {

        if (fDocumentView != null) {
            Rectangle bounds = getBounds();

            int dx = getScrollDifference(showRect.x, showRect.x + showRect.width,
                                         bounds.x, bounds.x + bounds.width);
            int dy = getScrollDifference(showRect.y, showRect.y + showRect.height,
                                         bounds.y, bounds.y + bounds.height);

            scrollSelf(dx, dy);
        }
    }

    void scrollToShow(int showX, int showY) {

        if (fDocumentView != null) {
            int dx = 0, dy = 0;

            Rectangle bounds = getBounds();
            if (showX < bounds.x) {
                dx = showX - bounds.x;
            }
            else if (showX > bounds.x + bounds.width) {
                dx = showX - (bounds.x + bounds.width);
            }

            if (showY < bounds.y) {
                dy = showY - bounds.y;
            }
            else if (showY > bounds.y + bounds.height) {
                dy = showY - (bounds.y + bounds.height);
            }

            scrollSelf(dx, dy);
        }
    }

    private int pinScrollOffset(int delta,
                                int contentStart,
                                int contentLength,
                                int viewStart,
                                int viewLength) {

        if (delta > 0) {
            int viewLimit = viewStart + viewLength;
            int contentLimit = contentStart + contentLength;

            if (viewLimit + delta > contentLimit) {
                delta = Math.max(0, contentLimit-viewLimit);
            }
        }
        else {
            if (viewStart + delta < contentStart) {
                delta = Math.min(0, contentStart-viewStart);
            }
        }

        return delta;
    }

    private void scrollSelf(int dx, int dy) {

        boolean scrolled = scrollBy(dx, dy);

        if (scrolled && fScroller != null) {
            Rectangle documentBounds = fDocumentView.getDocumentBounds();
            fScroller.setPosition(-documentBounds.x,
                                  -documentBounds.y);
        }
    }

    private synchronized boolean scrollBy(int dx, int dy) {

        boolean scrolled = false;

        if (fScrolls) {
            Rectangle documentBounds = fDocumentView.getDocumentBounds();
            Rectangle viewBounds = getBounds();
            
            // variable not used int oldDx = dx;
            dx = pinScrollOffset(dx, 
                                 documentBounds.x,
                                 documentBounds.width,
                                 viewBounds.x,
                                 viewBounds.width);
            dy = pinScrollOffset(dy, 
                                 documentBounds.y,
                                 documentBounds.height,
                                 viewBounds.y,
                                 viewBounds.height);

            if (dx != 0 || dy != 0) {
                scrolled = true;
                fDocumentView.moveBy(-dx, -dy);
            }
        }

        return scrolled;
    }

    // implementation of Scroller.Client - called by Scroller
    // they have to be public since they're in an interface
    // no one else should call these methods
    public Rectangle getScrollSize() {

        if (fDocumentView != null) {
            return fDocumentView.getScrollableArea();
        }
        else {
            return new Rectangle(0, 0, 0, 0);
        }
    }

    public void scrollTo(int x, int y) {

        if (fDocumentView != null) {
            scrollBy(x + fDocumentView.getDocX(), y + fDocumentView.getDocY());
        }
    }

    // *** Text access ***
    MConstText getText() {
        return fText;
    }

    MText getModifiableText() {
        return fText;
    }

    StyledTextClipboard getClipboard() {
        return fClipboard;
    }

    public synchronized void paint(Graphics g) {

        if (fDocumentView != null) {
            fDocumentView.paint(g);
        }
    }


    // *** Metric info - used by Behaviors
    Rectangle getCaretRect(TextOffset offset) {

        if (fDocumentView != null) {
            return fDocumentView.getCaretRect(offset);
        }
        else {
            return new Rectangle(0, 0);
        }
    }

    TextOffset pointToTextOffset(TextOffset result,
                                 int x,
                                 int y,
                                 TextOffset anchor,
                                 boolean infiniteMode) {

        if (fDocumentView != null) {
            return fDocumentView.pointToTextOffset(result, x, y, anchor, infiniteMode);
        }
        else {
            return new TextOffset();
        }
    }

    // *** Other stuff used by Behaviors - mostly formatter exports
    int lineContaining(TextOffset offset) {

        if (fDocumentView != null) {
            return fDocumentView.lineContaining(offset);
        }
        else {
            return 0;
        }
    }

    int lineRangeLow(int lineNumber) {

        if (fDocumentView != null) {
            return fDocumentView.lineRangeLow(lineNumber);
        }
        else {
            return 0;
        }
    }

    int lineRangeLimit(int lineNumber) {

        if (fDocumentView != null) {
            return fDocumentView.lineRangeLimit(lineNumber);
        }
        else {
            return 0;
        }
    }

    void stopBackgroundFormatting() {

        if (fDocumentView != null) {
            fDocumentView.stopBackgroundFormatting();
        }
    }

    Rectangle getBoundingRect(TextOffset offset1, TextOffset offset2) {

        if (fDocumentView != null) {
            return fDocumentView.getBoundingRect(offset1, offset2);
        }
        else {
            return new Rectangle(0, 0, 0, 0);
        }
    }

    synchronized void reformatAndDrawText(int reformatStart,
                             int reformatLength,
                             TextOffset selStart,
                             TextOffset selEnd,
                             Rectangle additionalUpdateRect,
                             Color hiliteColor) {

        if (fDocumentView != null) {
            fDocumentView.reformatAndDrawText(reformatStart,
                                              reformatLength,
                                              selStart,
                                              selEnd,
                                              additionalUpdateRect,
                                              hiliteColor);
        }
    }

    TextOffset findNewInsertionOffset(TextOffset result,
                                      TextOffset initialOffset,
                                      TextOffset previousOffset,
                                      short direction) {

        if (fDocumentView != null) {
            return fDocumentView.findNewInsertionOffset(result, initialOffset, previousOffset, direction);
        }
        else {
            return new TextOffset(initialOffset);
        }
    }

    synchronized void drawText(Graphics g,
                  Rectangle damagedRect,
                  boolean selectionVisible,
                  TextOffset selStart,
                  TextOffset selEnd,
                  Color hiliteColor) {

        if (fDocumentView != null) {
            fDocumentView.drawText(g, damagedRect, selectionVisible, selStart, selEnd, hiliteColor);
        }
    }

    private void documentSizeChanged() {

        if (fScroller != null) {
            fScroller.clientScrollSizeChanged();
        }
    }

    int getFormatWidth() {

        if (fDocumentView != null) {
            return fDocumentView.getFormatWidth();
        }
        else {
            return 0;
        }
    }

    /**
     * Return true if the paragraph at the given offset is left-to-right.
     * @param offset an offset in the text
     * @return true if the paragraph at the given offset is left-to-right
     */
    boolean paragraphIsLeftToRight(int offset) {
        
        if (fDocumentView != null) {
            return fDocumentView.paragraphIsLeftToRight(offset);
        }
        else {
            return true;
        }
    }
    
    private static final class DocumentView {

        private TextComponent fHost;
        private boolean fWraps;
        private boolean fWrapToWindowWidth;
        private int fInsetAmount;
        private PanelEventBroadcaster fListener;

        // fBounds is the total scrollable area of the document (including insets)
        private Rectangle fBounds = new Rectangle();
        
        private Point fOrigin;

        private MFormatter fFormatter;

        private OffscreenBufferCache fBufferCache;

        // Note, when this is true the caret won't blink in 1.1.  Looks like an AWT bug.
        private static boolean fNoOffscreenBuffer =
                            Boolean.getBoolean("TextComponent.NoOffscreenBuffer");

        // Amount by which to reduce the format width to allow for right-aligned carets.
        private final int CARET_SLOP = 1;

        DocumentView(TextComponent host,
                     MConstText text,
                     AttributeMap defaultValues,
                     boolean wraps,
                     int wrapWidth,
                     int insetAmount,
                     PanelEventBroadcaster listener) {

            fHost = host;
            fWrapToWindowWidth = wrapWidth == WINDOW_WIDTH;
            fInsetAmount = insetAmount;
            fListener = listener;

            initFormatterAndSize(text, defaultValues, wraps, wrapWidth);

            fBufferCache = new OffscreenBufferCache(host.fHost);
        }
        
        /**
         * Note: this computes the bounds rectangle relative to fOrigin
         */
        private void calcBoundsRect() {
        
            final int insetDim = 2 * fInsetAmount;

            final int minX = fFormatter.minX();
            final int minY = fFormatter.minY();

            fBounds.setBounds(fOrigin.x + minX - fInsetAmount,
                              fOrigin.y + minY - fInsetAmount,
                              fFormatter.maxX() - minX + insetDim, 
                              fFormatter.maxY() - minY + insetDim);
            //if (minX <= 0) {
            //    System.out.println("calcBoundsRect: minX="+minX+
            //                       "; bounds.x="+fBounds.x+"; width="+fBounds.width);
            //}
        }

        private void initFormatterAndSize(MConstText text, 
                                          AttributeMap defaultValues,
                                          boolean wraps,
                                          int wrapWidth) {

            Rectangle hostBounds = fHost.getBounds();
            int formatWidth;

            if (!wraps || fWrapToWindowWidth) {
                formatWidth = hostBounds.width - 2 * fInsetAmount;
                if (formatWidth <= CARET_SLOP) {
                    formatWidth = CARET_SLOP+1;
                }
            }
            else {
                formatWidth = wrapWidth;
            }

            fFormatter = MFormatter.createFormatter(text,
                                                    defaultValues,
                                                    formatWidth-CARET_SLOP,
                                                    wraps,
                                                    fHost.getGraphics());

            fFormatter.formatToHeight(hostBounds.height * 2);
            fOrigin = new Point(fInsetAmount, fInsetAmount);
            calcBoundsRect();
        }

        // notification method called by TextComponent
        void hostSizeChanged() {

            final boolean wrap = fFormatter.wrap();
            if (fWrapToWindowWidth || !wrap) {

                Rectangle hostBounds = fHost.getBounds();
                // variable not used final int insetDim = 2 * fInsetAmount;

                int formatWidth = hostBounds.width - 2*fInsetAmount;
                if (formatWidth <= CARET_SLOP) {
                    formatWidth = CARET_SLOP+1;
                }
                fFormatter.setLineBound(formatWidth-CARET_SLOP);

                fFormatter.formatToHeight(hostBounds.y + (hostBounds.height*2) - fOrigin.y);

                calcBoundsRect();
                
                //System.out.println("Window bounds="+hostBounds+"; document bounds="+fBounds);

                fHost.documentSizeChanged();
                fListener.textStateChanged(TextPanelEvent.FORMAT_WIDTH_CHANGED);
                //System.out.println("formatWidth="+formatWidth);
                //System.out.println("document bounds="+fBounds);
                //System.out.println();
            }
            //dumpWidthInfo();
        }

        int getFormatWidth() {

            return fFormatter.lineBound();
        }
        
        boolean paragraphIsLeftToRight(int offset) {
            
            int lineNumber = fFormatter.lineContaining(offset);
            return fFormatter.lineIsLeftToRight(lineNumber);
        }

        private void textSizeMightHaveChanged() {

            boolean changed = false;
            final int insetDim = 2 * fInsetAmount;
            
            int textHeight = fFormatter.maxY() - fFormatter.minY() + insetDim;
            if (textHeight != fBounds.height) {
                fBounds.height = textHeight;
                changed = true;
            }

            if (!fFormatter.wrap()) {
                int textWidth = fFormatter.maxX() - fFormatter.minX() + insetDim;
                if (textWidth != fBounds.width) {
                    fBounds.width = textWidth;
                    changed = true;
                }
            }

            if (changed) {
                //System.out.println("Text size changed.  fBounds: " + fBounds);
                calcBoundsRect();
                fHost.documentSizeChanged();
                fHost.scrollToShow(getDocumentBounds());
            }
        }

        private void doDrawText(Graphics g,
                                Rectangle drawRect,
                                boolean selectionVisible,
                                TextOffset selStart,
                                TextOffset selEnd,
                                Color hiliteColor) {

            Color oldColor = g.getColor();
            g.setColor(fHost.getHost().getBackground());
            g.fillRect(drawRect.x, drawRect.y, drawRect.width, drawRect.height);
            g.setColor(oldColor);

            //            g.clearRect(drawRect.x, drawRect.y, drawRect.width, drawRect.height);

            if (selectionVisible) {
                fFormatter.draw(g, drawRect, fOrigin, selStart, selEnd, hiliteColor);
            }
            else {
                fFormatter.draw(g, drawRect, fOrigin, null, null, null);
            }

            if (selStart != null && selStart.equals(selEnd) && selectionVisible) {

                fFormatter.drawCaret(g, selStart, fOrigin,
                                    STRONG_CARET_COLOR, WEAK_CARET_COLOR);
            }
        }

        void drawText(Graphics g,
                      Rectangle drawRect,
                      boolean selectionVisible,
                      TextOffset selStart,
                      TextOffset selEnd,
                      Color hiliteColor) {

            if (g != null) {
                drawRect = drawRect.intersection(fHost.getBounds());
                //System.out.println("drawText:drawRect: " + drawRect);
                g.clipRect(drawRect.x, drawRect.y, drawRect.width, drawRect.height);
                if (fNoOffscreenBuffer) {
                    doDrawText(g, drawRect, selectionVisible, selStart, selEnd, hiliteColor);
                }
                else {
                    Image offscreenBuffer = fBufferCache.getBuffer(drawRect.width, drawRect.height);
                    Graphics offscreenGraphics = offscreenBuffer.getGraphics();
                    offscreenGraphics.translate(-drawRect.x, -drawRect.y);
    
                    doDrawText(offscreenGraphics, drawRect, selectionVisible, selStart, selEnd, hiliteColor);
    
                    g.drawImage(offscreenBuffer, drawRect.x, drawRect.y, fHost.fHost);
                }
            }
            textSizeMightHaveChanged();
        }

        void reformatAndDrawText(int reformatStart,
                                 int reformatLength,
                                 TextOffset selStart,
                                 TextOffset selEnd,
                                 Rectangle additionalUpdateRect,
                                 Color hiliteColor) {

            Rectangle visibleBounds = fHost.getBounds();
            Rectangle redrawRect = fFormatter.updateFormat(reformatStart,
                                                           reformatLength,
                                                           visibleBounds,
                                                           fOrigin);
            //System.out.println("[1] redrawRect: " + redrawRect);

            if (additionalUpdateRect != null) {
                redrawRect.add(additionalUpdateRect);
                //System.out.println("[2] redrawRect: " + redrawRect);
            }

            boolean haveSelection;

            if (selStart != null && selEnd != null) {
                haveSelection = true;
                redrawRect.add(fFormatter.getBoundingRect(selStart, selEnd, fOrigin, fFormatter.LOOSE));
                //System.out.println("[3] redrawRect: " + redrawRect);
            }
            else {
                haveSelection = false;
            }

            drawText(fHost.getGraphics(), redrawRect, haveSelection, selStart, selEnd, hiliteColor);
        }

        private void letBehaviorDraw(Graphics g, Rectangle drawRect) {

            boolean result = false;

            if (fHost.fBehavior != null) {
                result = fHost.fBehavior.paint(g, drawRect);
            }

            if (!result) {
                drawText(g, drawRect, false, null, null, null);
            }
        }

        void moveBy(int dx, int dy) {

            Rectangle visibleBounds = fHost.getBounds();
            Graphics g = fHost.getGraphics();

            fBounds.x += dx;
            fBounds.y += dy;
            fOrigin.x += dx;
            fOrigin.y += dy;

            Rectangle refreshRect = new Rectangle(visibleBounds);

            if (dx == 0) {
                if (g != null) {
                    g.copyArea(visibleBounds.x, visibleBounds.y, visibleBounds.width, visibleBounds.height, dx, dy);
                }
                if (dy < 0) {
                    refreshRect.y = visibleBounds.y + visibleBounds.height + dy;
                }
                refreshRect.height = Math.abs(dy);
                //System.out.println("refreshRect=" + refreshRect);
            }

            letBehaviorDraw(g, refreshRect);
        }
        
        private Rectangle getInsetBounds() {
            
            int insetDim = 2 * fInsetAmount;
            return new Rectangle(fBounds.x-fInsetAmount,
                                 fBounds.y-fInsetAmount,
                                 fBounds.width+insetDim,
                                 fBounds.height+insetDim);
        }

        void paint(Graphics g) {

            Rectangle hostBounds = fHost.getBounds();
            Rectangle textRefreshRect = hostBounds.intersection(getInsetBounds());
            letBehaviorDraw(g, textRefreshRect);
        }

        Rectangle getCaretRect(TextOffset offset) {

            return fFormatter.getCaretRect(offset, fOrigin);
        }

        TextOffset pointToTextOffset(TextOffset result,
                                     int x,
                                     int y,
                                     TextOffset anchor,
                                     boolean infiniteMode) {

            return fFormatter.pointToTextOffset(result, x, y, fOrigin, anchor, infiniteMode);
        }

        Rectangle getScrollableArea() {

            Rectangle area = new Rectangle(fBounds);
            area.x += fInsetAmount - fOrigin.x;
            area.y += fInsetAmount - fOrigin.y;
            return area;
        }

        /**
         * Doesn't clone so TextComponent needs to be nice.  TextComponent
         * is the only class which can access this anyway.
         */
        Rectangle getDocumentBounds() {

            return fBounds;
        }
        
        int getDocX() {
        
            return fOrigin.x - fInsetAmount;
        }
        
        int getDocY() {
        
            return fOrigin.y - fInsetAmount;
        }

        int lineContaining(TextOffset offset) {

            return fFormatter.lineContaining(offset);
        }

        int lineRangeLow(int lineNumber) {

            return fFormatter.lineRangeLow(lineNumber);
        }

        int lineRangeLimit(int lineNumber) {

            return fFormatter.lineRangeLimit(lineNumber);
        }

        void stopBackgroundFormatting() {

            fFormatter.stopBackgroundFormatting();
        }

        Rectangle getBoundingRect(TextOffset offset1, TextOffset offset2) {

            Rectangle r = fFormatter.getBoundingRect(offset1, offset2, fOrigin, fFormatter.TIGHT);
            //r.width += CARET_SLOP;
            //System.out.println("offset1="+offset1+"; offset2="+offset2);
            //System.out.println("bounds width="+r.width+"; host width="+(fHost.getBounds().width));
            return r;
        }

        TextOffset findNewInsertionOffset(TextOffset result,
                                          TextOffset initialOffset,
                                          TextOffset previousOffset,
                                          short direction) {

            return fFormatter.findNewInsertionOffset(
                        result, initialOffset, previousOffset, direction);
        }
    }
}
