/* 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.SwingConstants;
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
{
  /**
   * The length of the char buffer that holds the characters to be drawn.
   */
  private static final int BUF_LENGTH = 64;

  /**
   * 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 pixelY = y - ascent;

    int pixelWidth = 0;
    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];
        if (c == '\t' || c == '\n')
          {
            if (len > 0) {
              g.drawChars(buffer, pos, len, pixelX, pixelY + ascent);            
              pixelX += pixelWidth;
              pixelWidth = 0;
            }
            pos = offset+1;
            len = 0;
          }
        
	switch (c)
	  {
	  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 ' '.
	    if (e != null)
	      pixelX = (int) e.nextTabStop((float) pixelX,
					   startOffset + offset - s.offset);
	    else
	      pixelX += metrics.charWidth(' ');
	    break;
	  case '\n':
	    // In case we have a newline, we must jump to the next line.
	    pixelY += metrics.getHeight();
	    pixelX = x;
	    break;
	  default:
            ++len;
	    pixelWidth += metrics.charWidth(buffer[offset]);
	    break;
	  }
      }

    if (len > 0)
      g.drawChars(buffer, pos, len, pixelX, pixelY + ascent);            
    
    return pixelX + pixelWidth;
  }

  /**
   * 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;

    for (int offset = s.offset; offset < (s.offset + s.count); ++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((float) 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.charWidth(buffer[offset]);
	    maxWidth = Math.max(maxWidth, pixelX - x);
	    pixelX = x;
	    break;
	  default:
	    // Here we draw the char.
	    pixelX += metrics.charWidth(buffer[offset]);
	    break;
	  }
      }

    // Take the last line into account.
    maxWidth = Math.max(maxWidth, pixelX - x);

    return maxWidth;
  }

  /**
   * 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)
  {
    // At the end of the for loop, this holds the requested model location
    int pos;
    int currentX = x0;
    int width = 0;
    
    for (pos = 0; pos < s.count; pos++)
      {
        char nextChar = s.array[s.offset+pos];
        
        if (nextChar == 0)
            break;
        
        if (nextChar != '\t')
          width = fm.charWidth(nextChar);
        else
          {
            if (te == null)
              width = fm.charWidth(' ');
            else
              width = ((int) te.nextTabStop(currentX, pos)) - currentX;
          }
        
        if (round)
          {
            if (currentX + (width>>1) > x)
              break;
          }
        else
          {
            if (currentX + width > x)
              break;
          }
        
        currentX += width;
      }

    return pos + p0;
  }

  /**
   * 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);
    BreakIterator breaker = BreakIterator.getWordInstance();
    breaker.setText(s);

    // If startOffset and s.offset differ then we need to use
    // that difference two convert the offset between the two metrics. 
    int shift = startOffset - s.offset;
    
    // If mark is equal to the end of the string, just use that position.
    if (mark >= shift + s.count)
      return mark;
    
    // Try to find a word boundary previous to the mark at which we 
    // can break the text.
    int preceding = breaker.preceding(mark + 1 - shift);
    
    if (preceding != 0)
      return preceding + shift;
    
    // If preceding is 0 we couldn't find a suitable word-boundary so
    // just break it on the character boundary
    return mark;
  }

  /**
   * 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,
                                         null)
          : t.getUI().getNextVisualPositionFrom(t,
                                                offset,
                                                Bias.Forward,
                                                direction,
                                                null);
      }
    catch (BadLocationException ble)
    {
      return offset;
    }
    
  }
  
}
