/* Utilities.java --
   Copyright (C) 2004, 2005, 2006  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.swing.text;

import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
import java.text.BreakIterator;

import javax.swing.text.Position.Bias;

/**
 * A set of utilities to deal with text. This is used by several other classes
 * inside this package.
 *
 * @author Roman Kennke (roman@ontographics.com)
 * @author Robert Schuster (robertschuster@fsfe.org)
 */
public class Utilities
{

  /**
   * Creates a new <code>Utilities</code> object.
   */
  public Utilities()
  {
    // Nothing to be done here.
  }

  /**
   * Draws the given text segment. Contained tabs and newline characters
   * are taken into account. Tabs are expanded using the
   * specified {@link TabExpander}.
   *
   *
   * The X and Y coordinates denote the start of the <em>baseline</em> where
   * the text should be drawn.
   *
   * @param s the text fragment to be drawn.
   * @param x the x position for drawing.
   * @param y the y position for drawing.
   * @param g the {@link Graphics} context for drawing.
   * @param e the {@link TabExpander} which specifies the Tab-expanding
   *     technique.
   * @param startOffset starting offset in the text.
   * @return the x coordinate at the end of the drawn text.
   */
  public static final int drawTabbedText(Segment s, int x, int y, Graphics g,
                                         TabExpander e, int startOffset)
  {
    // This buffers the chars to be drawn.
    char[] buffer = s.array;

    // The font metrics of the current selected font.
    FontMetrics metrics = g.getFontMetrics();

    int ascent = metrics.getAscent();

    // The current x and y pixel coordinates.
    int pixelX = x;

    int pos = s.offset;
    int len = 0;

    int end = s.offset + s.count;

    for (int offset = s.offset; offset < end; ++offset)
      {
        char c = buffer[offset];
        switch (c)
          {
          case '\t':
            if (len > 0) {
              g.drawChars(buffer, pos, len, pixelX, y);
              pixelX += metrics.charsWidth(buffer, pos, len);
              len = 0;
            }
            pos = offset+1;
            if (e != null)
              pixelX = (int) e.nextTabStop((float) pixelX, startOffset + offset
                                           - s.offset);
            else
              pixelX += metrics.charWidth(' ');
            x = pixelX;
            break;
          case '\n':
          case '\r':
            if (len > 0) {
              g.drawChars(buffer, pos, len, pixelX, y);
              pixelX += metrics.charsWidth(buffer, pos, len);
              len = 0;
            }
            x = pixelX;
            break;
          default:
            len += 1;
          }
      }

    if (len > 0)
      {
        g.drawChars(buffer, pos, len, pixelX, y);
        pixelX += metrics.charsWidth(buffer, pos, len);
      }

    return pixelX;
  }

  /**
   * Determines the width, that the given text <code>s</code> would take
   * if it was printed with the given {@link java.awt.FontMetrics} on the
   * specified screen position.
   * @param s the text fragment
   * @param metrics the font metrics of the font to be used
   * @param x the x coordinate of the point at which drawing should be done
   * @param e the {@link TabExpander} to be used
   * @param startOffset the index in <code>s</code> where to start
   * @returns the width of the given text s. This takes tabs and newlines
   * into account.
   */
  public static final int getTabbedTextWidth(Segment s, FontMetrics metrics,
                                             int x, TabExpander e,
                                             int startOffset)
  {
    // This buffers the chars to be drawn.
    char[] buffer = s.array;

    // The current x coordinate.
    int pixelX = x;

    // The current maximum width.
    int maxWidth = 0;

    int end = s.offset + s.count;
    int count = 0;
    for (int offset = s.offset; offset < end; offset++)
      {
        switch (buffer[offset])
          {
          case '\t':
            // In case we have a tab, we just 'jump' over the tab.
            // When we have no tab expander we just use the width of 'm'.
            if (e != null)
              pixelX = (int) e.nextTabStop(pixelX,
                                           startOffset + offset - s.offset);
            else
              pixelX += metrics.charWidth(' ');
            break;
          case '\n':
            // In case we have a newline, we must 'draw'
            // the buffer and jump on the next line.
            pixelX += metrics.charsWidth(buffer, offset - count, count);
            count = 0;
            break;
          default:
            count++;
          }
      }

    // Take the last line into account.
    pixelX += metrics.charsWidth(buffer, end - count, count);

    return pixelX - x;
  }

  /**
   * Provides a facility to map screen coordinates into a model location. For a
   * given text fragment and start location within this fragment, this method
   * determines the model location so that the resulting fragment fits best
   * into the span <code>[x0, x]</code>.
   *
   * The parameter <code>round</code> controls which model location is returned
   * if the view coordinates are on a character: If <code>round</code> is
   * <code>true</code>, then the result is rounded up to the next character, so
   * that the resulting fragment is the smallest fragment that is larger than
   * the specified span. If <code>round</code> is <code>false</code>, then the
   * resulting fragment is the largest fragment that is smaller than the
   * specified span.
   *
   * @param s the text segment
   * @param fm the font metrics to use
   * @param x0 the starting screen location
   * @param x the target screen location at which the requested fragment should
   *        end
   * @param te the tab expander to use; if this is <code>null</code>, TABs are
   *        expanded to one space character
   * @param p0 the starting model location
   * @param round if <code>true</code> round up to the next location, otherwise
   *        round down to the current location
   *
   * @return the model location, so that the resulting fragment fits within the
   *         specified span
   */
  public static final int getTabbedTextOffset(Segment s, FontMetrics fm, int x0,
                                              int x, TabExpander te, int p0,
                                              boolean round)
  {
    int found = s.count;
    int currentX = x0;
    int nextX = currentX;

    int end = s.offset + s.count;
    for (int pos = s.offset; pos < end && found == s.count; pos++)
      {
        char nextChar = s.array[pos];

        if (nextChar != '\t')
          nextX += fm.charWidth(nextChar);
        else
          {
            if (te == null)
              nextX += fm.charWidth(' ');
            else
              nextX += ((int) te.nextTabStop(nextX, p0 + pos - s.offset));
          }

        if (x >= currentX && x < nextX)
          {
            // Found position.
            if ((! round) || ((x - currentX) < (nextX - x)))
              {
                found = pos - s.offset;
              }
            else
              {
                found = pos + 1 - s.offset;
              }
          }
        currentX = nextX;
      }

    return found;
  }

  /**
   * Provides a facility to map screen coordinates into a model location. For a
   * given text fragment and start location within this fragment, this method
   * determines the model location so that the resulting fragment fits best
   * into the span <code>[x0, x]</code>.
   *
   * This method rounds up to the next location, so that the resulting fragment
   * will be the smallest fragment of the text, that is greater than the
   * specified span.
   *
   * @param s the text segment
   * @param fm the font metrics to use
   * @param x0 the starting screen location
   * @param x the target screen location at which the requested fragment should
   *        end
   * @param te the tab expander to use; if this is <code>null</code>, TABs are
   *        expanded to one space character
   * @param p0 the starting model location
   *
   * @return the model location, so that the resulting fragment fits within the
   *         specified span
   */
  public static final int getTabbedTextOffset(Segment s, FontMetrics fm, int x0,
                                              int x, TabExpander te, int p0)
  {
    return getTabbedTextOffset(s, fm, x0, x, te, p0, true);
  }

  /**
   * Finds the start of the next word for the given offset.
   *
   * @param c
   *          the text component
   * @param offs
   *          the offset in the document
   * @return the location in the model of the start of the next word.
   * @throws BadLocationException
   *           if the offset is invalid.
   */
  public static final int getNextWord(JTextComponent c, int offs)
      throws BadLocationException
  {
    if (offs < 0 || offs > (c.getText().length() - 1))
      throw new BadLocationException("invalid offset specified", offs);
    String text = c.getText();
    BreakIterator wb = BreakIterator.getWordInstance();
    wb.setText(text);

    int last = wb.following(offs);
    int current = wb.next();
    int cp;

    while (current != BreakIterator.DONE)
      {
        for (int i = last; i < current; i++)
          {
            cp = text.codePointAt(i);

            // Return the last found bound if there is a letter at the current
            // location or is not whitespace (meaning it is a number or
            // punctuation). The first case means that 'last' denotes the
            // beginning of a word while the second case means it is the start
            // of something else.
            if (Character.isLetter(cp)
                || !Character.isWhitespace(cp))
              return last;
          }
        last = current;
        current = wb.next();
      }

    throw new BadLocationException("no more words", offs);
  }

  /**
   * Finds the start of the previous word for the given offset.
   *
   * @param c
   *          the text component
   * @param offs
   *          the offset in the document
   * @return the location in the model of the start of the previous word.
   * @throws BadLocationException
   *           if the offset is invalid.
   */
  public static final int getPreviousWord(JTextComponent c, int offs)
      throws BadLocationException
  {
    String text = c.getText();

    if (offs <= 0 || offs > text.length())
      throw new BadLocationException("invalid offset specified", offs);

    BreakIterator wb = BreakIterator.getWordInstance();
    wb.setText(text);
    int last = wb.preceding(offs);
    int current = wb.previous();
    int cp;

    while (current != BreakIterator.DONE)
      {
        for (int i = last; i < offs; i++)
          {
            cp = text.codePointAt(i);

            // Return the last found bound if there is a letter at the current
            // location or is not whitespace (meaning it is a number or
            // punctuation). The first case means that 'last' denotes the
            // beginning of a word while the second case means it is the start
            // of some else.
            if (Character.isLetter(cp)
                || !Character.isWhitespace(cp))
              return last;
          }
        last = current;
        current = wb.previous();
      }

    return 0;
  }

  /**
   * Finds the start of a word for the given location.
   * @param c the text component
   * @param offs the offset location
   * @return the location of the word beginning
   * @throws BadLocationException if the offset location is invalid
   */
  public static final int getWordStart(JTextComponent c, int offs)
      throws BadLocationException
  {
    String text = c.getText();

    if (offs < 0 || offs > text.length())
      throw new BadLocationException("invalid offset specified", offs);

    BreakIterator wb = BreakIterator.getWordInstance();
    wb.setText(text);

    if (wb.isBoundary(offs))
      return offs;

    return wb.preceding(offs);
  }

  /**
   * Finds the end of a word for the given location.
   * @param c the text component
   * @param offs the offset location
   * @return the location of the word end
   * @throws BadLocationException if the offset location is invalid
   */
  public static final int getWordEnd(JTextComponent c, int offs)
      throws BadLocationException
  {
    if (offs < 0 || offs >= c.getText().length())
      throw new BadLocationException("invalid offset specified", offs);

    String text = c.getText();
    BreakIterator wb = BreakIterator.getWordInstance();
    wb.setText(text);
    return wb.following(offs);
  }

  /**
   * Get the model position of the end of the row that contains the
   * specified model position.  Return null if the given JTextComponent
   * does not have a size.
   * @param c the JTextComponent
   * @param offs the model position
   * @return the model position of the end of the row containing the given
   * offset
   * @throws BadLocationException if the offset is invalid
   */
  public static final int getRowEnd(JTextComponent c, int offs)
      throws BadLocationException
  {
    String text = c.getText();
    if (text == null)
      return -1;

    // Do a binary search for the smallest position X > offs
    // such that that character at positino X is not on the same
    // line as the character at position offs
    int high = offs + ((text.length() - 1 - offs) / 2);
    int low = offs;
    int oldHigh = text.length() + 1;
    while (true)
      {
        if (c.modelToView(high).y != c.modelToView(offs).y)
          {
            oldHigh = high;
            high = low + ((high + 1 - low) / 2);
            if (oldHigh == high)
              return high - 1;
          }
        else
          {
            low = high;
            high += ((oldHigh - high) / 2);
            if (low == high)
              return low;
          }
      }
  }

  /**
   * Get the model position of the start of the row that contains the specified
   * model position. Return null if the given JTextComponent does not have a
   * size.
   *
   * @param c the JTextComponent
   * @param offs the model position
   * @return the model position of the start of the row containing the given
   *         offset
   * @throws BadLocationException if the offset is invalid
   */
  public static final int getRowStart(JTextComponent c, int offs)
      throws BadLocationException
  {
    String text = c.getText();
    if (text == null)
      return -1;

    // Do a binary search for the greatest position X < offs
    // such that the character at position X is not on the same
    // row as the character at position offs
    int high = offs;
    int low = 0;
    int oldLow = 0;
    while (true)
      {
        if (c.modelToView(low).y != c.modelToView(offs).y)
          {
            oldLow = low;
            low = high - ((high + 1 - low) / 2);
            if (oldLow == low)
              return low + 1;
          }
        else
          {
            high = low;
            low -= ((low - oldLow) / 2);
            if (low == high)
              return low;
          }
      }
  }

  /**
   * Determine where to break the text in the given Segment, attempting to find
   * a word boundary.
   * @param s the Segment that holds the text
   * @param metrics the font metrics used for calculating the break point
   * @param x0 starting view location representing the start of the text
   * @param x the target view location
   * @param e the TabExpander used for expanding tabs (if this is null tabs
   * are expanded to 1 space)
   * @param startOffset the offset in the Document of the start of the text
   * @return the offset at which we should break the text
   */
  public static final int getBreakLocation(Segment s, FontMetrics metrics,
                                           int x0, int x, TabExpander e,
                                           int startOffset)
  {
    int mark = Utilities.getTabbedTextOffset(s, metrics, x0, x, e, startOffset,
                                             false);
    int breakLoc = mark;
    // If mark is equal to the end of the string, just use that position.
    if (mark < s.count - 1)
      {
        for (int i = s.offset + mark; i >= s.offset; i--)
          {
            char ch = s.array[i];
            if (ch < 256)
              {
                // For ASCII simply scan backwards for whitespace.
                if (Character.isWhitespace(ch))
                  {
                    breakLoc = i - s.offset + 1;
                    break;
                  }
              }
            else
              {
                // Only query BreakIterator for complex chars.
                BreakIterator bi = BreakIterator.getLineInstance();
                bi.setText(s);
                int pos = bi.preceding(i + 1);
                if (pos > s.offset)
                  {
                    breakLoc = breakLoc - s.offset;
                  }
                break;
              }
          }
      }
    return breakLoc;
  }

  /**
   * Returns the paragraph element in the text component <code>c</code> at
   * the specified location <code>offset</code>.
   *
   * @param c the text component
   * @param offset the offset of the paragraph element to return
   *
   * @return the paragraph element at <code>offset</code>
   */
  public static final Element getParagraphElement(JTextComponent c, int offset)
  {
    Document doc = c.getDocument();
    Element par = null;
    if (doc instanceof StyledDocument)
      {
        StyledDocument styledDoc = (StyledDocument) doc;
        par = styledDoc.getParagraphElement(offset);
      }
    else
      {
        Element root = c.getDocument().getDefaultRootElement();
        int parIndex = root.getElementIndex(offset);
        par = root.getElement(parIndex);
      }
    return par;
  }

  /**
   * Returns the document position that is closest above to the specified x
   * coordinate in the row containing <code>offset</code>.
   *
   * @param c the text component
   * @param offset the offset
   * @param x the x coordinate
   *
   * @return  the document position that is closest above to the specified x
   *          coordinate in the row containing <code>offset</code>
   *
   * @throws BadLocationException if <code>offset</code> is not a valid offset
   */
  public static final int getPositionAbove(JTextComponent c, int offset, int x)
    throws BadLocationException
  {
    int offs = getRowStart(c, offset);

    if(offs == -1)
      return -1;

    // Effectively calculates the y value of the previous line.
    Point pt = c.modelToView(offs-1).getLocation();

    pt.x = x;

    // Calculate a simple fitting offset.
    offs = c.viewToModel(pt);

    // Find out the real x positions of the calculated character and its
    // neighbour.
    int offsX = c.modelToView(offs).getLocation().x;
    int offsXNext = c.modelToView(offs+1).getLocation().x;

    // Chose the one which is nearer to us and return its offset.
    if (Math.abs(offsX-x) <= Math.abs(offsXNext-x))
      return offs;
    else
      return offs+1;
  }

  /**
   * Returns the document position that is closest below to the specified x
   * coordinate in the row containing <code>offset</code>.
   *
   * @param c the text component
   * @param offset the offset
   * @param x the x coordinate
   *
   * @return  the document position that is closest above to the specified x
   *          coordinate in the row containing <code>offset</code>
   *
   * @throws BadLocationException if <code>offset</code> is not a valid offset
   */
  public static final int getPositionBelow(JTextComponent c, int offset, int x)
    throws BadLocationException
  {
    int offs = getRowEnd(c, offset);

    if(offs == -1)
      return -1;

    Point pt = null;

    // Note: Some views represent the position after the last
    // typed character others do not. Converting offset 3 in "a\nb"
    // in a PlainView will return a valid rectangle while in a
    // WrappedPlainView this will throw a BadLocationException.
    // This behavior has been observed in the RI.
    try
      {
        // Effectively calculates the y value of the next line.
        pt = c.modelToView(offs+1).getLocation();
      }
    catch(BadLocationException ble)
      {
        return offset;
      }

    pt.x = x;

    // Calculate a simple fitting offset.
    offs = c.viewToModel(pt);

    if (offs == c.getDocument().getLength())
      return offs;

    // Find out the real x positions of the calculated character and its
    // neighbour.
    int offsX = c.modelToView(offs).getLocation().x;
    int offsXNext = c.modelToView(offs+1).getLocation().x;

    // Chose the one which is nearer to us and return its offset.
    if (Math.abs(offsX-x) <= Math.abs(offsXNext-x))
      return offs;
    else
      return offs+1;
    }

  /** This is an internal helper method which is used by the
   * <code>javax.swing.text</code> package. It simply delegates the
   * call to a method with the same name on the <code>NavigationFilter</code>
   * of the provided <code>JTextComponent</code> (if it has one) or its UI.
   *
   * If the underlying method throws a <code>BadLocationException</code> it
   * will be swallowed and the initial offset is returned.
   */
  static int getNextVisualPositionFrom(JTextComponent t, int offset, int direction)
  {
    NavigationFilter nf = t.getNavigationFilter();

    try
      {
        return (nf != null)
          ? nf.getNextVisualPositionFrom(t,
                                         offset,
                                         Bias.Forward,
                                         direction,
                                         new Position.Bias[1])
          : t.getUI().getNextVisualPositionFrom(t,
                                                offset,
                                                Bias.Forward,
                                                direction,
                                                new Position.Bias[1]);
      }
    catch (BadLocationException ble)
    {
      return offset;
    }

  }

}
