/*
 * (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.
 */
package com.ibm.richtext.textpanel;

import java.awt.Color;
import java.awt.Component;
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 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, MFormatter.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, MFormatter.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);
        }
    }
}
