/* StringContent.java --
   Copyright (C) 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.io.Serializable;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoableEdit;

/**
 * An implementation of the <code>AbstractDocument.Content</code>
 * interface useful for small documents or debugging. The character
 * content is a simple character array. It's not really efficient.
 * 
 * <p>Do not use this class for large size.</p>
 */
public final class StringContent 
  implements AbstractDocument.Content, Serializable
{
  /** The serialization UID (compatible with JDK1.5). */
  private static final long serialVersionUID = 4755994433709540381L;

  // This is package-private to avoid an accessor method.
  char[] content;

  private int count;

  private Vector positions = new Vector();

  private class InsertUndo extends AbstractUndoableEdit
  {
    private int start;
    
    private int length;

    private String redoContent;

    public InsertUndo(int start, int length)
    {
      super();
      this.start = start;
      this.length = length;
    }

    public void undo()
    {
      super.undo();
      try
        {
          StringContent.this.checkLocation(this.start, this.length);
          this.redoContent = new String(StringContent.this.content, this.start,
              this.length);
          StringContent.this.remove(this.start, this.length);
        }
      catch (BadLocationException b)
        {
          throw new CannotUndoException();
        }
    }
    
    public void redo()
    {
      super.redo();
      try
        {
          StringContent.this.insertString(this.start, this.redoContent);
        }
      catch (BadLocationException b)
        {
          throw new CannotRedoException();
        }
    }
  }

  private class RemoveUndo extends AbstractUndoableEdit
  {
    private int start;

    private String undoString;

    public RemoveUndo(int start, String str)
    {
      super();
      this.start = start;
      this.undoString = str;
    }

    public void undo()
    {
      super.undo();
      try
        {
          StringContent.this.insertString(this.start, this.undoString);
        }
      catch (BadLocationException bad)
        {
          throw new CannotUndoException();
        }
    }

    public void redo()
    {
      super.redo();
      try
        {
          int end = this.undoString.length();
          StringContent.this.remove(this.start, end);
        }
      catch (BadLocationException bad)
        {
          throw new CannotRedoException();
        }
    }
  }

  private class StickyPosition implements Position
  {
    private int offset = -1;

    public StickyPosition(int offset)
    {
      this.offset = offset;
    }

    // This is package-private to avoid an accessor method.
    void setOffset(int offset)
    {
      this.offset = this.offset >= 0 ? offset : -1;
    }

    /**
     * Should be >=0.
     */
    public int getOffset()
    {
      return offset < 0 ? 0 : offset;
    }
  }

  /**
   * Creates a new instance containing the string "\n".  This is equivalent
   * to calling {@link #StringContent(int)} with an <code>initialLength</code>
   * of 10.
   */
  public StringContent()
  {
    this(10);
  }

  /**
   * Creates a new instance containing the string "\n".
   * 
   * @param initialLength  the initial length of the underlying character 
   *                       array used to store the content.
   */
  public StringContent(int initialLength)
  {
    super();
    if (initialLength < 1)
      initialLength = 1;
    this.content = new char[initialLength];
    this.content[0] = '\n';
    this.count = 1;
  }

  protected Vector getPositionsInRange(Vector v,
                                       int offset,
                                       int length)
  {
    Vector refPos = new Vector();
    Iterator iter = this.positions.iterator();
    while(iter.hasNext())
      {
        Position p = (Position) iter.next();
        if ((offset <= p.getOffset())
            && (p.getOffset() <= (offset + length)))
          refPos.add(p);
      }
    return refPos;
  }

  /**
   * Creates a position reference for the character at the given offset.  The
   * position offset will be automatically updated when new characters are
   * inserted into or removed from the content.
   * 
   * @param offset  the character offset.
   * 
   * @throws BadLocationException if offset is outside the bounds of the 
   *         content.
   */
  public Position createPosition(int offset) throws BadLocationException
  {
    if (offset < this.count || offset > this.count)
      checkLocation(offset, 0);
    StickyPosition sp = new StickyPosition(offset);
    this.positions.add(sp);
    return sp;
  }
  
  /**
   * Returns the length of the string content, including the '\n' character at
   * the end.
   * 
   * @return The length of the string content.
   */
  public int length()
  {
    return this.count;
  }
  
  /**
   * Inserts <code>str</code> at the given position and returns an 
   * {@link UndoableEdit} that enables undo/redo support.
   * 
   * @param where  the insertion point (must be less than 
   *               <code>length()</code>).
   * @param str  the string to insert (<code>null</code> not permitted).
   * 
   * @return An object that can undo the insertion.
   */
  public UndoableEdit insertString(int where, String str)
    throws BadLocationException
  {
    checkLocation(where, 0);
    if (where == this.count)
      throw new BadLocationException("Invalid location", 1);
    if (str == null)
      throw new NullPointerException();
    char[] insert = str.toCharArray();
    char[] temp = new char[this.content.length + insert.length];
    this.count += insert.length;
    // Copy array and insert the string.
    if (where > 0)
      System.arraycopy(this.content, 0, temp, 0, where);
    System.arraycopy(insert, 0, temp, where, insert.length);
    System.arraycopy(this.content, where, temp, (where + insert.length), 
        (temp.length - where - insert.length));
    if (this.content.length < temp.length)
      this.content = new char[temp.length];
    // Copy the result in the original char array.
    System.arraycopy(temp, 0, this.content, 0, temp.length);
    // Move all the positions.
    Vector refPos = getPositionsInRange(this.positions, where, 
                                        temp.length - where);
    Iterator iter = refPos.iterator();
    while (iter.hasNext())
      {
        StickyPosition p = (StickyPosition)iter.next();
        p.setOffset(p.getOffset() + str.length());
      }
    InsertUndo iundo = new InsertUndo(where, insert.length);
    return iundo;
  }
  
  /**
   * Removes the specified range of characters and returns an 
   * {@link UndoableEdit} that enables undo/redo support.
   * 
   * @param where  the starting index.
   * @param nitems  the number of characters.
   * 
   * @return An object that can undo the removal.
   * 
   * @throws BadLocationException if the character range extends outside the
   *         bounds of the content OR includes the last character.
   */
  public UndoableEdit remove(int where, int nitems) throws BadLocationException
  {
    checkLocation(where, nitems + 1);
    char[] temp = new char[(this.content.length - nitems)];
    this.count = this.count - nitems;
    RemoveUndo rundo = new RemoveUndo(where, new String(this.content, where, 
        nitems));
    // Copy array.
    System.arraycopy(this.content, 0, temp, 0, where);
    System.arraycopy(this.content, where + nitems, temp, where, 
        this.content.length - where - nitems);
    this.content = new char[temp.length];
    // Then copy the result in the original char array.
    System.arraycopy(temp, 0, this.content, 0, this.content.length);
    // Move all the positions.
    Vector refPos = getPositionsInRange(this.positions, where, 
        this.content.length + nitems - where);
    Iterator iter = refPos.iterator();
    while (iter.hasNext())
      {
        StickyPosition p = (StickyPosition)iter.next();
        int result = p.getOffset() - nitems;
        p.setOffset(result);
        if (result < 0)
          this.positions.remove(p);
      }
    return rundo;
  }
  
  /**
   * Returns a new <code>String</code> containing the characters in the 
   * specified range.
   * 
   * @param where  the start index.
   * @param len  the number of characters.
   * 
   * @return A string.
   * 
   * @throws BadLocationException if the requested range of characters extends 
   *         outside the bounds of the content.
   */
  public String getString(int where, int len) throws BadLocationException
  {
    checkLocation(where, len);
    return new String(this.content, where, len);
  }
  
  /**
   * Updates <code>txt</code> to contain a direct reference to the underlying 
   * character array.
   * 
   * @param where  the index of the first character.
   * @param len  the number of characters.
   * @param txt  a carrier for the return result (<code>null</code> not 
   *             permitted).
   *             
   * @throws BadLocationException if the requested character range is not 
   *                              within the bounds of the content.
   * @throws NullPointerException if <code>txt</code> is <code>null</code>.
   */
  public void getChars(int where, int len, Segment txt) 
    throws BadLocationException
  {
    checkLocation(where, len);
    txt.array = this.content;
    txt.offset = where;
    txt.count = len;
  }


  /**
   * @specnote This method is not very well specified and the positions vector
   *           is implementation specific. The undo positions are managed
   *           differently in this implementation, this method is only here
   *           for binary compatibility.
   */
  protected void updateUndoPositions(Vector positions)
  {
    // We do nothing here.
  }

  /** 
   * A utility method that checks the validity of the specified character
   * range.
   * 
   * @param where  the first character in the range.
   * @param len  the number of characters in the range.
   * 
   * @throws BadLocationException if the specified range is not within the
   *         bounds of the content.
   */
  void checkLocation(int where, int len) throws BadLocationException
  {
    if (where < 0)
      throw new BadLocationException("Invalid location", 1);
    else if (where > this.count)
      throw new BadLocationException("Invalid location", this.count);
    else if ((where + len) > this.count)
      throw new BadLocationException("Invalid range", this.count);
  }
  
}

