/* DefaultStyledDocument.java --
   Copyright (C) 2004, 2005 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.Color;
import java.awt.Font;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Stack;
import java.util.Vector;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.UndoableEditEvent;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.UndoableEdit;

/**
 * The default implementation of {@link StyledDocument}. The document is
 * modeled as an {@link Element} tree, which has a {@link SectionElement} as
 * single root, which has one or more {@link AbstractDocument.BranchElement}s
 * as paragraph nodes and each paragraph node having one or more
 * {@link AbstractDocument.LeafElement}s as content nodes.
 * 
 * @author Michael Koch (konqueror@gmx.de)
 * @author Roman Kennke (roman@kennke.org)
 */
public class DefaultStyledDocument extends AbstractDocument implements
    StyledDocument
{

  /**
   * An {@link UndoableEdit} that can undo attribute changes to an element.
   * 
   * @author Roman Kennke (kennke@aicas.com)
   */
  public static class AttributeUndoableEdit extends AbstractUndoableEdit
  {
    /**
     * A copy of the old attributes.
     */
    protected AttributeSet copy;

    /**
     * The new attributes.
     */
    protected AttributeSet newAttributes;

    /**
     * If the new attributes replaced the old attributes or if they only were
     * added to them.
     */
    protected boolean isReplacing;

    /**
     * The element that has changed.
     */
    protected Element element;

    /**
     * Creates a new <code>AttributeUndoableEdit</code>.
     * 
     * @param el
     *          the element that changes attributes
     * @param newAtts
     *          the new attributes
     * @param replacing
     *          if the new attributes replace the old or only append to them
     */
    public AttributeUndoableEdit(Element el, AttributeSet newAtts,
                                 boolean replacing)
    {
      element = el;
      newAttributes = newAtts;
      isReplacing = replacing;
      copy = el.getAttributes().copyAttributes();
    }

    /**
     * Undos the attribute change. The <code>copy</code> field is set as
     * attributes on <code>element</code>.
     */
    public void undo()
    {
      super.undo();
      AttributeSet atts = element.getAttributes();
      if (atts instanceof MutableAttributeSet)
        {
          MutableAttributeSet mutable = (MutableAttributeSet) atts;
          mutable.removeAttributes(atts);
          mutable.addAttributes(copy);
        }
    }

    /**
     * Redos an attribute change. This adds <code>newAttributes</code> to the
     * <code>element</code>'s attribute set, possibly clearing all attributes
     * if <code>isReplacing</code> is true.
     */
    public void redo()
    {
      super.undo();
      AttributeSet atts = element.getAttributes();
      if (atts instanceof MutableAttributeSet)
        {
          MutableAttributeSet mutable = (MutableAttributeSet) atts;
          if (isReplacing)
            mutable.removeAttributes(atts);
          mutable.addAttributes(newAttributes);
        }
    }
  }

  /**
   * Carries specification information for new {@link Element}s that should be
   * created in {@link ElementBuffer}. This allows the parsing process to be
   * decoupled from the <code>Element</code> creation process.
   */
  public static class ElementSpec
  {
    /**
     * This indicates a start tag. This is a possible value for {@link #getType}.
     */
    public static final short StartTagType = 1;

    /**
     * This indicates an end tag. This is a possible value for {@link #getType}.
     */
    public static final short EndTagType = 2;

    /**
     * This indicates a content element. This is a possible value for
     * {@link #getType}.
     */
    public static final short ContentType = 3;

    /**
     * This indicates that the data associated with this spec should be joined
     * with what precedes it. This is a possible value for {@link #getDirection}.
     */
    public static final short JoinPreviousDirection = 4;

    /**
     * This indicates that the data associated with this spec should be joined
     * with what follows it. This is a possible value for {@link #getDirection}.
     */
    public static final short JoinNextDirection = 5;

    /**
     * This indicates that the data associated with this spec should be used to
     * create a new element. This is a possible value for {@link #getDirection}.
     */
    public static final short OriginateDirection = 6;

    /**
     * This indicates that the data associated with this spec should be joined
     * to the fractured element. This is a possible value for
     * {@link #getDirection}.
     */
    public static final short JoinFractureDirection = 7;

    /**
     * The type of the tag.
     */
    short type;

    /**
     * The direction of the tag.
     */
    short direction;

    /**
     * The offset of the content.
     */
    int offset;

    /**
     * The length of the content.
     */
    int length;

    /**
     * The actual content.
     */
    char[] content;

    /**
     * The attributes for the tag.
     */
    AttributeSet attributes;

    /**
     * Creates a new <code>ElementSpec</code> with no content, length or
     * offset. This is most useful for start and end tags.
     * 
     * @param a
     *          the attributes for the element to be created
     * @param type
     *          the type of the tag
     */
    public ElementSpec(AttributeSet a, short type)
    {
      this(a, type, 0);
    }

    /**
     * Creates a new <code>ElementSpec</code> that specifies the length but
     * not the offset of an element. Such <code>ElementSpec</code>s are
     * processed sequentially from a known starting point.
     * 
     * @param a
     *          the attributes for the element to be created
     * @param type
     *          the type of the tag
     * @param len
     *          the length of the element
     */
    public ElementSpec(AttributeSet a, short type, int len)
    {
      this(a, type, null, 0, len);
    }

    /**
     * Creates a new <code>ElementSpec</code> with document content.
     * 
     * @param a
     *          the attributes for the element to be created
     * @param type
     *          the type of the tag
     * @param txt
     *          the actual content
     * @param offs
     *          the offset into the <code>txt</code> array
     * @param len
     *          the length of the element
     */
    public ElementSpec(AttributeSet a, short type, char[] txt, int offs, int len)
    {
      attributes = a;
      this.type = type;
      offset = offs;
      length = len;
      content = txt;
      direction = OriginateDirection;
    }

    /**
     * Sets the type of the element.
     * 
     * @param type
     *          the type of the element to be set
     */
    public void setType(short type)
    {
      this.type = type;
    }

    /**
     * Returns the type of the element.
     * 
     * @return the type of the element
     */
    public short getType()
    {
      return type;
    }

    /**
     * Sets the direction of the element.
     * 
     * @param dir
     *          the direction of the element to be set
     */
    public void setDirection(short dir)
    {
      direction = dir;
    }

    /**
     * Returns the direction of the element.
     * 
     * @return the direction of the element
     */
    public short getDirection()
    {
      return direction;
    }

    /**
     * Returns the attributes of the element.
     * 
     * @return the attributes of the element
     */
    public AttributeSet getAttributes()
    {
      return attributes;
    }

    /**
     * Returns the actual content of the element.
     * 
     * @return the actual content of the element
     */
    public char[] getArray()
    {
      return content;
    }

    /**
     * Returns the offset of the content.
     * 
     * @return the offset of the content
     */
    public int getOffset()
    {
      return offset;
    }

    /**
     * Returns the length of the content.
     * 
     * @return the length of the content
     */
    public int getLength()
    {
      return length;
    }

    /**
     * Returns a String representation of this <code>ElementSpec</code>
     * describing the type, direction and length of this
     * <code>ElementSpec</code>.
     * 
     * @return a String representation of this <code>ElementSpec</code>
     */
    public String toString()
    {
      StringBuilder b = new StringBuilder();
      switch (type)
        {
        case StartTagType:
          b.append("StartTag");
          break;
        case EndTagType:
          b.append("EndTag");
          break;
        case ContentType:
          b.append("Content");
          break;
        default:
          b.append("??");
          break;
        }

      b.append(':');

      switch (direction)
        {
        case JoinPreviousDirection:
          b.append("JoinPrevious");
          break;
        case JoinNextDirection:
          b.append("JoinNext");
          break;
        case OriginateDirection:
          b.append("Originate");
          break;
        case JoinFractureDirection:
          b.append("Fracture");
          break;
        default:
          b.append("??");
          break;
        }

      b.append(':');
      b.append(length);

      return b.toString();
    }
  }

  /**
   * Performs all <em>structural</code> changes to the <code>Element</code>
   * hierarchy.  This class was implemented with much help from the document:
   * http://java.sun.com/products/jfc/tsc/articles/text/element_buffer/index.html.
   */
  public class ElementBuffer implements Serializable
  {
    /**
     * Instance of all editing information for an object in the Vector. This class
     * is used to add information to the DocumentEvent associated with an
     * insertion/removal/change as well as to store the changes that need to be
     * made so they can be made all at the same (appropriate) time.
     */
    class Edit
    {
      /** The element to edit . */
      Element e;

      /** The index of the change. */
      int index;

      /** The removed elements. */
      ArrayList removed = new ArrayList();

      /** The added elements. */
      ArrayList added = new ArrayList();

      /**
       * Indicates if this edit contains a fracture.
       */
      boolean isFracture;

      /**
       * Creates a new Edit for the specified element at index i.
       *
       * @param el the element
       * @param i the index
       */
      Edit(Element el, int i)
      {
        this(el, i, false);
      }

      /**
       * Creates a new Edit for the specified element at index i.
       *
       * @param el the element
       * @param i the index
       * @param frac if this is a fracture edit or not
       */
      Edit(Element el, int i, boolean frac)
      {
        e = el;
        index = i;
        isFracture = frac;
      }

    }

    /** The serialization UID (compatible with JDK1.5). */
    private static final long serialVersionUID = 1688745877691146623L;

    /** The root element of the hierarchy. */
    private Element root;

    /** Holds the offset for structural changes. */
    private int offset;

    /** Holds the end offset for structural changes. */
    private int endOffset;

    /** Holds the length of structural changes. */
    private int length;

    /** Holds the position of the change. */
    private int pos;

    /**
     * The parent of the fracture.
     */
    private Element fracturedParent;

    /**
     * The fractured child.
     */
    private Element fracturedChild;

    /**
     * Indicates if a fracture has been created.
     */
    private boolean createdFracture;

    /**
     * The current position in the element tree. This is used for bulk inserts
     * using ElementSpecs.
     */
    private Stack elementStack;

    private Edit[] insertPath;

    private boolean recreateLeafs;

    /**
     * Vector that contains all the edits. Maybe replace by a HashMap.
     */
    private ArrayList edits;

    private boolean offsetLastIndex;
    private boolean offsetLastIndexReplace;

    /**
     * Creates a new <code>ElementBuffer</code> for the specified
     * <code>root</code> element.
     * 
     * @param root
     *          the root element for this <code>ElementBuffer</code>
     */
    public ElementBuffer(Element root)
    {
      this.root = root;
    }

    /**
     * Returns the root element of this <code>ElementBuffer</code>.
     * 
     * @return the root element of this <code>ElementBuffer</code>
     */
    public Element getRootElement()
    {
      return root;
    }

    /**
     * Removes the content. This method sets some internal parameters and
     * delegates the work to {@link #removeUpdate}.
     * 
     * @param offs
     *          the offset from which content is remove
     * @param len
     *          the length of the removed content
     * @param ev
     *          the document event that records the changes
     */
    public void remove(int offs, int len, DefaultDocumentEvent ev)
    {
      prepareEdit(offs, len);
      removeUpdate();
      finishEdit(ev);
    }

    /**
     * Updates the element structure of the document in response to removal of
     * content. It removes the affected {@link Element}s from the document
     * structure.
     */
    protected void removeUpdate()
    {
      removeElements(root, offset, endOffset);
    }

    private boolean removeElements(Element elem, int rmOffs0, int rmOffs1)
    {
      boolean ret = false; 
      if (! elem.isLeaf())
        {
          // Update stack for changes.
          int index0 = elem.getElementIndex(rmOffs0);
          int index1 = elem.getElementIndex(rmOffs1);
          elementStack.push(new Edit(elem, index0));
          Edit ec = (Edit) elementStack.peek();

          // If the range is contained by one element,
          // we just forward the request
          if (index0 == index1)
            {
              Element child0 = elem.getElement(index0);
              if(rmOffs0 <= child0.getStartOffset()
                  && rmOffs1 >= child0.getEndOffset())
                {
                  // Element totally removed.
                  ec.removed.add(child0);
                }
              else if (removeElements(child0, rmOffs0, rmOffs1))
                {
                  ec.removed.add(child0);
                }
            }
          else
            {
              // The removal range spans elements.  If we can join
              // the two endpoints, do it.  Otherwise we remove the
              // interior and forward to the endpoints.
              Element child0 = elem.getElement(index0);
              Element child1 = elem.getElement(index1);
              boolean containsOffs1 = (rmOffs1 < elem.getEndOffset());
          if (containsOffs1 && canJoin(child0, child1))
            {
              // Remove and join.
              for (int i = index0; i <= index1; i++)
                {
                  ec.removed.add(elem.getElement(i));
                }
              Element e = join(elem, child0, child1, rmOffs0, rmOffs1);
              ec.added.add(e);
            }
          else
            {
              // Remove interior and forward.
              int rmIndex0 = index0 + 1;
              int rmIndex1 = index1 - 1;
              if (child0.getStartOffset() == rmOffs0
                  || (index0 == 0 && child0.getStartOffset() > rmOffs0
                      && child0.getEndOffset() <= rmOffs1))
                {
                  // Start element completely consumed.
                  child0 = null;
                  rmIndex0 = index0;
                }
              if (! containsOffs1)
                {
                  child1 = null;
                  rmIndex1++;
              }
              else if (child1.getStartOffset() == rmOffs1)
                {
                  // End element not touched.
                  child1 = null;
                }
              if (rmIndex0 <= rmIndex1)
                {
                  ec.index = rmIndex0;
                }
              for (int i = rmIndex0; i <= rmIndex1; i++)
                {
                  ec.removed.add(elem.getElement(i));
                }
              if (child0 != null)
                {
                  if(removeElements(child0, rmOffs0, rmOffs1))
                    {
                      ec.removed.add(0, child0);
                      ec.index = index0;
                    }
                }
              if (child1 != null)
                {
                  if(removeElements(child1, rmOffs0, rmOffs1))
                    {
                      ec.removed.add(child1);
                    }
                }
            }
            }

          // Perform changes.
          pop();

          // Return true if we no longer have any children.
          if(elem.getElementCount() == (ec.removed.size() - ec.added.size()))
            ret = true;
        }
      return ret;
    }

    /**
     * Creates a document in response to a call to
     * {@link DefaultStyledDocument#create(ElementSpec[])}.
     *
     * @param len the length of the inserted text
     * @param data the specs for the elements
     * @param ev the document event
     */
    void create(int len, ElementSpec[] data, DefaultDocumentEvent ev)
    {
      prepareEdit(offset, len);
      Element el = root;
      int index = el.getElementIndex(0);
      while (! el.isLeaf())
        {
          Element child = el.getElement(index);
          Edit edit = new Edit(el, index, false);
          elementStack.push(edit);
          el = child;
          index = el.getElementIndex(0);
        }
      Edit ed = (Edit) elementStack.peek();
      Element child = ed.e.getElement(ed.index);
      ed.added.add(createLeafElement(ed.e, child.getAttributes(), getLength(),
                                     child.getEndOffset()));
      ed.removed.add(child);
      while (elementStack.size() > 1)
        pop();
      int n = data.length;

      // Reset root element's attributes.
      AttributeSet newAtts = null;
      if (n > 0 && data[0].getType() == ElementSpec.StartTagType)
        newAtts = data[0].getAttributes();
      if (newAtts == null)
        newAtts = SimpleAttributeSet.EMPTY;
      MutableAttributeSet mAtts = (MutableAttributeSet) root.getAttributes();
      ev.addEdit(new AttributeUndoableEdit(root, newAtts, true));
      mAtts.removeAttributes(mAtts);
      mAtts.addAttributes(newAtts);

      // Insert the specified elements.
      for (int i = 1; i < n; i++)
        insertElement(data[i]);

      // Pop remaining stack.
      while (elementStack.size() > 0)
        pop();

      finishEdit(ev);
    }

    private boolean canJoin(Element e0, Element e1)
    {
      boolean ret = false;
      if ((e0 != null) && (e1 != null))
        {
          // Don't join a leaf to a branch.
          boolean isLeaf0 = e0.isLeaf();
          boolean isLeaf1 = e1.isLeaf();
          if(isLeaf0 == isLeaf1)
            {
              if (isLeaf0)
                {
                  // Only join leaves if the attributes match, otherwise
                  // style information will be lost.
                  ret = e0.getAttributes().isEqual(e1.getAttributes());
                }
              else
                {
                  // Only join non-leafs if the names are equal. This may result
                  // in loss of style information, but this is typically
                  // acceptable for non-leafs.
                  String name0 = e0.getName();
                  String name1 = e1.getName();
                  if (name0 != null)
                    ret = name0.equals(name1);
                  else if (name1 != null)
                    ret = name1.equals(name0);
                  else // Both names null.
                    ret = true;
                }
            }
        }
      return ret;
    }

    private Element join(Element p, Element left, Element right, int rmOffs0,
                         int rmOffs1)
    {
      Element joined = null;
      if (left.isLeaf() && right.isLeaf())
        {
          joined = createLeafElement(p, left.getAttributes(),
                                     left.getStartOffset(),
                                     right.getEndOffset());
        }
      else if ((! left.isLeaf()) && (! right.isLeaf()))
        {
          // Join two branch elements.  This copies the children before
          // the removal range on the left element, and after the removal
          // range on the right element.  The two elements on the edge
          // are joined if possible and needed.
          joined = createBranchElement(p, left.getAttributes());
          int ljIndex = left.getElementIndex(rmOffs0);
          int rjIndex = right.getElementIndex(rmOffs1);
          Element lj = left.getElement(ljIndex);
          if (lj.getStartOffset() >= rmOffs0)
            {
              lj = null;
            }
          Element rj = right.getElement(rjIndex);
          if (rj.getStartOffset() == rmOffs1)
            {
              rj = null;
            }
          ArrayList children = new ArrayList();
          // Transfer the left.
          for (int i = 0; i < ljIndex; i++)
            {
              children.add(clone(joined, left.getElement(i)));
            }

          // Transfer the join/middle.
          if (canJoin(lj, rj))
            {
              Element e = join(joined, lj, rj, rmOffs0, rmOffs1);
              children.add(e);
            }
          else
            {
              if (lj != null)
                {
                  children.add(cloneAsNecessary(joined, lj, rmOffs0, rmOffs1));
                }
              if (rj != null)
                {
                  children.add(cloneAsNecessary(joined, rj, rmOffs0, rmOffs1));
                }
            }

          // Transfer the right.
          int n = right.getElementCount();
          for (int i = (rj == null) ? rjIndex : rjIndex + 1; i < n; i++)
            {
              children.add(clone(joined, right.getElement(i)));
            }

          // Install the children.
          Element[] c = new Element[children.size()];
          c = (Element[]) children.toArray(c);
          ((BranchElement) joined).replace(0, 0, c);
        }
      else
        {
          assert false : "Must not happen";
        }
      return joined;
    }

    /**
     * Performs the actual work for {@link #change}. The elements at the
     * interval boundaries are split up (if necessary) so that the interval
     * boundaries are located at element boundaries.
     */
    protected void changeUpdate()
    {
      boolean didEnd = split(offset, length);
      if (! didEnd)
        {
          // need to do the other end
          while (elementStack.size() != 0)
            {
              pop();
            }
          split(offset + length, 0);
        }
      while (elementStack.size() != 0)
        {
          pop();
        }
    }

    /**
     * Modifies the element structure so that the specified interval starts and
     * ends at an element boundary. Content and paragraph elements are split and
     * created as necessary. This also updates the
     * <code>DefaultDocumentEvent</code> to reflect the structural changes.
     * The bulk work is delegated to {@link #changeUpdate()}.
     * 
     * @param offset
     *          the start index of the interval to be changed
     * @param length
     *          the length of the interval to be changed
     * @param ev
     *          the <code>DefaultDocumentEvent</code> describing the change
     */
    public void change(int offset, int length, DefaultDocumentEvent ev)
    {
      prepareEdit(offset, length);
      changeUpdate();
      finishEdit(ev);
    }

    /**
     * Creates and returns a deep clone of the specified <code>clonee</code>
     * with the specified parent as new parent.
     *
     * This method can only clone direct instances of {@link BranchElement}
     * or {@link LeafElement}.
     *
     * @param parent the new parent
     * @param clonee the element to be cloned
     *
     * @return the cloned element with the new parent
     */
    public Element clone(Element parent, Element clonee)
    {
      Element clone = clonee;
      // We can only handle AbstractElements here.
      if (clonee instanceof BranchElement)
        {
          BranchElement branchEl = (BranchElement) clonee;
          BranchElement branchClone =
            new BranchElement(parent, branchEl.getAttributes());
          // Also clone all of the children.
          int numChildren = branchClone.getElementCount();
          Element[] cloneChildren = new Element[numChildren];
          for (int i = 0; i < numChildren; ++i)
            {
              cloneChildren[i] = clone(branchClone,
                                       branchClone.getElement(i));
            }
          branchClone.replace(0, 0, cloneChildren);
          clone = branchClone;
        }
      else if (clonee instanceof LeafElement)
        {
          clone = new LeafElement(parent, clonee.getAttributes(),
                                  clonee.getStartOffset(),
                                  clonee.getEndOffset());
        }
      return clone;
    }

    private Element cloneAsNecessary(Element parent, Element clonee,
                                     int rmOffs0, int rmOffs1)
    {
      Element cloned;
      if (clonee.isLeaf())
        {
          cloned = createLeafElement(parent, clonee.getAttributes(),
                                     clonee.getStartOffset(),
                                     clonee.getEndOffset());
        }
      else
        {
          Element e = createBranchElement(parent, clonee.getAttributes());
          int n = clonee.getElementCount();
          ArrayList childrenList = new ArrayList(n);
          for (int i = 0; i < n; i++)
            {
              Element elem = clonee.getElement(i);
              if (elem.getStartOffset() < rmOffs0
                  || elem.getEndOffset() > rmOffs1)
                {
                  childrenList.add(cloneAsNecessary(e, elem, rmOffs0,
                                                    rmOffs1));
                }
            }
          Element[] children = new Element[childrenList.size()];
          children = (Element[]) childrenList.toArray(children);
          ((BranchElement) e).replace(0, 0, children);
          cloned = e;
        }
      return cloned;
    }

    /**
     * Inserts new <code>Element</code> in the document at the specified
     * position. Most of the work is done by {@link #insertUpdate}, after some
     * fields have been prepared for it.
     * 
     * @param offset
     *          the location in the document at which the content is inserted
     * @param length
     *          the length of the inserted content
     * @param data
     *          the element specifications for the content to be inserted
     * @param ev
     *          the document event that is updated to reflect the structural
     *          changes
     */
    public void insert(int offset, int length, ElementSpec[] data,
                       DefaultDocumentEvent ev)
    {
      if (length > 0)
	{
	  prepareEdit(offset, length);
	  insertUpdate(data);
	  finishEdit(ev);
	}
    }

    /**
     * Prepares the state of this object for performing an insert.
     *
     * @param offset the offset at which is inserted
     * @param length the length of the inserted region
     */
    private void prepareEdit(int offset, int length)
    {
      this.offset = offset;
      this.pos = offset;
      this.endOffset = offset + length;
      this.length = length;

      if (edits == null)
	edits = new ArrayList();
      else
	edits.clear();

      if (elementStack == null)
	elementStack = new Stack();
      else
	elementStack.clear();

      fracturedParent = null;
      fracturedChild = null;
      offsetLastIndex = false;
      offsetLastIndexReplace = false;
    }

    /**
     * Finishes an insert. This applies all changes and updates
     * the DocumentEvent.
     *
     * @param ev the document event
     */
    private void finishEdit(DefaultDocumentEvent ev)
    {
      // This for loop applies all the changes that were made and updates the
      // DocumentEvent.
      for (Iterator i = edits.iterator(); i.hasNext();)
	{
          Edit edits = (Edit) i.next();
          Element[] removed = new Element[edits.removed.size()];
          removed = (Element[]) edits.removed.toArray(removed);
          Element[] added = new Element[edits.added.size()];
          added = (Element[]) edits.added.toArray(added);
          int index = edits.index;
          BranchElement parent = (BranchElement) edits.e;
          parent.replace(index, removed.length, added);
          ElementEdit ee = new ElementEdit(parent, index, removed, added);
          ev.addEdit(ee);
	}
      edits.clear();
      elementStack.clear();
    }

    /**
     * Inserts new content.
     * 
     * @param data the element specifications for the elements to be inserted
     */
    protected void insertUpdate(ElementSpec[] data)
    {
      // Push the current path to the stack.
      Element current = root;
      int index = current.getElementIndex(offset);
      while (! current.isLeaf())
        {
          Element child = current.getElement(index);
          int editIndex = child.isLeaf() ? index : index + 1;
          Edit edit = new Edit(current, editIndex);
          elementStack.push(edit);
          current = child;
          index = current.getElementIndex(offset);
        }

      // Create a copy of the original path.
      insertPath = new Edit[elementStack.size()];
      insertPath = (Edit[]) elementStack.toArray(insertPath);

      // No fracture yet.
      createdFracture = false;

      // Insert first content tag.
      int i = 0;
      recreateLeafs = false;
      int type = data[0].getType();
      if (type == ElementSpec.ContentType)
        {
          // If the first tag is content we must treat it separately to allow
          // for joining properly to previous Elements and to ensure that
          // no extra LeafElements are erroneously inserted.
          insertFirstContentTag(data);
          pos += data[0].length;
          i = 1;
        }
      else
        {
          createFracture(data);
          i = 0;
        }

      // Handle each ElementSpec individually.
      for (; i < data.length; i++)
        {
          insertElement(data[i]);
        }

      // Fracture if we haven't done yet.
      if (! createdFracture)
        fracture(-1);

      // Pop the remaining stack.
      while (elementStack.size() != 0)
        pop();

      // Offset last index if necessary.
      if (offsetLastIndex && offsetLastIndexReplace)
        insertPath[insertPath.length - 1].index++;

      // Make sure we havea an Edit for each path item that has a change.
      for (int p = insertPath.length - 1; p >= 0; p--)
        {
          Edit edit = insertPath[p];
          if (edit.e == fracturedParent)
            edit.added.add(fracturedChild);
          if ((edit.added.size() > 0 || edit.removed.size() > 0)
              && ! edits.contains(edit))
            edits.add(edit);
        }

      // Remove element that would be created by an insert at 0 with
      // an initial end tag.
      if (offset == 0 && fracturedParent != null
          && data[0].getType() == ElementSpec.EndTagType)
        {
          int p;
          for (p = 0;
               p < data.length && data[p].getType() == ElementSpec.EndTagType;
               p++)
            ;
          
          Edit edit = insertPath[insertPath.length - p - 1];
          edit.index--;
          edit.removed.add(0, edit.e.getElement(edit.index));
        }
    }

    private void pop()
    {
      Edit edit = (Edit) elementStack.peek();
      elementStack.pop();
      if ((edit.added.size() > 0) || (edit.removed.size() > 0))
        {
          edits.add(edit);
        }
      else if (! elementStack.isEmpty())
        {
          Element e = edit.e;
          if (e.getElementCount() == 0)
            {
              // If we pushed a branch element that didn't get
              // used, make sure its not marked as having been added.
              edit = (Edit) elementStack.peek();
              edit.added.remove(e);
          }
      }
    }

    private void insertElement(ElementSpec spec)
    {
      Edit edit = (Edit) elementStack.peek();
      switch (spec.getType())
        {
        case ElementSpec.StartTagType:
          switch (spec.getDirection())
            {
            case ElementSpec.JoinFractureDirection:
              // Fracture the tree and ensure the appropriate element
              // is on top of the stack.
              if (! createdFracture)
                {
                  fracture(elementStack.size() - 1);
                }
              if (! edit.isFracture)
                {
                  // If the parent isn't a fracture, then the fracture is
                  // in fracturedChild.
                  Edit newEdit = new Edit(fracturedChild, 0, true);
                  elementStack.push(newEdit);
                }
              else
                {
                  // Otherwise use the parent's first child.
                  Element el = edit.e.getElement(0);
                  Edit newEdit = new Edit(el, 0, true);
                  elementStack.push(newEdit);
                }
              break;
            case ElementSpec.JoinNextDirection:
              // Push the next paragraph element onto the stack so
              // future insertions are added to it.
              Element parent = edit.e.getElement(edit.index);
              if (parent.isLeaf())
                {
                  if (edit.index + 1 < edit.e.getElementCount())
                    parent = edit.e.getElement(edit.index + 1);
                  else
                    assert false; // Must not happen.
                }
              elementStack.push(new Edit(parent, 0, true));
              break;
            default:
              Element branch = createBranchElement(edit.e,
                                                   spec.getAttributes());
              edit.added.add(branch);
              elementStack.push(new Edit(branch, 0));
              break;
            }
          break;
        case ElementSpec.EndTagType:
          pop();
          break;
        case ElementSpec.ContentType:
          insertContentTag(spec, edit);
          break;
        }
    }

    /**
     * Inserts the first tag into the document.
     * 
     * @param data -
     *          the data to be inserted.
     */
    private void insertFirstContentTag(ElementSpec[] data)
    {
      ElementSpec first = data[0];
      Edit edit = (Edit) elementStack.peek();
      Element current = edit.e.getElement(edit.index);
      int firstEndOffset = offset + first.length;
      boolean onlyContent = data.length == 1;
      switch (first.getDirection())
        {
        case ElementSpec.JoinPreviousDirection:
          if (current.getEndOffset() != firstEndOffset && ! onlyContent)
            {
              Element newEl1 = createLeafElement(edit.e,
                                                 current.getAttributes(),
                                                 current.getStartOffset(),
                                                 firstEndOffset);
              edit.added.add(newEl1);
              edit.removed.add(current);
              if (current.getEndOffset() != endOffset)
                recreateLeafs = true;
              else
                offsetLastIndex = true;
            }
          else
            {
              offsetLastIndex = true;
              offsetLastIndexReplace = true;
            }
          break;
        case ElementSpec.JoinNextDirection:
          if (offset != 0)
            {
              Element newEl1 = createLeafElement(edit.e,
                                                 current.getAttributes(),
                                                 current.getStartOffset(),
                                                 offset);
              edit.added.add(newEl1);
              Element next = edit.e.getElement(edit.index + 1);
              if (onlyContent)
                newEl1 = createLeafElement(edit.e, next.getAttributes(),
                                           offset, next.getEndOffset());
              else
                {
                  newEl1 = createLeafElement(edit.e, next.getAttributes(),
                                             offset, firstEndOffset);
                }
              edit.added.add(newEl1);
              edit.removed.add(current);
              edit.removed.add(next);
            }
          break;
        default: // OriginateDirection.
          if (current.getStartOffset() != offset)
            {
              Element newEl = createLeafElement(edit.e,
                                                current.getAttributes(),
                                                current.getStartOffset(),
                                                offset);
              edit.added.add(newEl);
            }
          edit.removed.add(current);
          Element newEl1 = createLeafElement(edit.e, first.getAttributes(),
                                             offset, firstEndOffset);
          edit.added.add(newEl1);
          if (current.getEndOffset() != endOffset)
            recreateLeafs = true;
          else
            offsetLastIndex = true;
          break;
        }
    }

    /**
     * Inserts a content element into the document structure.
     * 
     * @param tag -
     *          the element spec
     */
    private void insertContentTag(ElementSpec tag, Edit edit)
    {
      int len = tag.getLength();
      int dir = tag.getDirection();
      if (dir == ElementSpec.JoinNextDirection)
        {
          if (! edit.isFracture)
            {
              Element first = null;
              if (insertPath != null)
                {
                  for (int p = insertPath.length - 1; p >= 0; p--)
                    {
                      if (insertPath[p] == edit)
                        {
                          if (p != insertPath.length - 1)
                            first = edit.e.getElement(edit.index);
                          break;
                        }
                    }
                }
              if (first == null)
                first = edit.e.getElement(edit.index + 1);
              Element leaf = createLeafElement(edit.e, first.getAttributes(),
                                               pos, first.getEndOffset());
              edit.added.add(leaf);
              edit.removed.add(first);
            }
          else
            {
              Element first = edit.e.getElement(0);
              Element leaf = createLeafElement(edit.e, first.getAttributes(),
                                               pos, first.getEndOffset());
              edit.added.add(leaf);
              edit.removed.add(first);
            }
        }
      else 
        {
          Element leaf = createLeafElement(edit.e, tag.getAttributes(), pos,
                                           pos + len);
          edit.added.add(leaf);
        }

      pos += len;
      
    }

    /**
     * This method fractures bottomost leaf in the elementStack. This
     * happens when the first inserted tag is not content.
     * 
     * @param data
     *          the ElementSpecs used for the entire insertion
     */
    private void createFracture(ElementSpec[] data)
    {
      Edit edit = (Edit) elementStack.peek();
      Element child = edit.e.getElement(edit.index);
      if (offset != 0)
        {
          Element newChild = createLeafElement(edit.e, child.getAttributes(),
                                               child.getStartOffset(), offset);
          edit.added.add(newChild);
        }
      edit.removed.add(child);
      if (child.getEndOffset() != endOffset)
        recreateLeafs = true;
      else
        offsetLastIndex = true;
    }

    private void fracture(int depth)
    {
      int len = insertPath.length;
      int lastIndex = -1;
      boolean recreate = recreateLeafs;
      Edit lastEdit = insertPath[len - 1];
      boolean childChanged = lastEdit.index + 1 < lastEdit.e.getElementCount();
      int deepestChangedIndex = recreate ? len : - 1;
      int lastChangedIndex = len - 1;
      createdFracture = true;
      for (int i = len - 2; i >= 0; i--)
        {
          Edit edit = insertPath[i];
          if (edit.added.size() > 0 || i == depth)
            {
              lastIndex = i;
              if (! recreate && childChanged)
                {
                  recreate = true;
                  if (deepestChangedIndex == -1)
                    deepestChangedIndex = lastChangedIndex + 1;
                }
            }
          if (! childChanged && edit.index < edit.e.getElementCount())
            {
              childChanged = true;
              lastChangedIndex = i;
            }
        }
      if (recreate)
        {
          if (lastIndex == -1)
            lastIndex = len - 1;
          recreate(lastIndex, deepestChangedIndex);
        }
    }

    private void recreate(int startIndex, int endIndex)
    {
      // Recreate the element representing the inserted index.
      Edit edit = insertPath[startIndex];
      Element child;
      Element newChild;
      int changeLength = insertPath.length;

      if (startIndex + 1 == changeLength)
        child = edit.e.getElement(edit.index);
      else
        child = edit.e.getElement(edit.index - 1);

      if(child.isLeaf())
        {
          newChild = createLeafElement(edit.e, child.getAttributes(),
                                   Math.max(endOffset, child.getStartOffset()),
                                   child.getEndOffset());
        }
      else
        {
          newChild = createBranchElement(edit.e, child.getAttributes());
        }
      fracturedParent = edit.e;
      fracturedChild = newChild;

      // Recreate all the elements to the right of the insertion point.
      Element parent = newChild;
      while (++startIndex < endIndex)
        {
          boolean isEnd = (startIndex + 1) == endIndex;
          boolean isEndLeaf = (startIndex + 1) == changeLength;

          // Create the newChild, a duplicate of the elment at
          // index. This isn't done if isEnd and offsetLastIndex are true
          // indicating a join previous was done.
          edit = insertPath[startIndex];

          // Determine the child to duplicate, won't have to duplicate
          // if at end of fracture, or offseting index.
          if(isEnd)
            {
              if(offsetLastIndex || ! isEndLeaf)
                child = null;
              else
                child = edit.e.getElement(edit.index);
            }
          else
            {
              child = edit.e.getElement(edit.index - 1);
            }

          // Duplicate it.
          if(child != null)
            {
              if(child.isLeaf())
                {
                  newChild = createLeafElement(parent, child.getAttributes(),
                                   Math.max(endOffset, child.getStartOffset()),
                                   child.getEndOffset());
                }
              else
                {
                  newChild = createBranchElement(parent,
                                                 child.getAttributes());
                }
            }
          else
            newChild = null;

        // Recreate the remaining children (there may be none).
        int childrenToMove = edit.e.getElementCount() - edit.index;
        Element[] children;
        int moveStartIndex;
        int childStartIndex = 1;

        if (newChild == null)
          {
            // Last part of fracture.
            if (isEndLeaf)
              {
                childrenToMove--;
                moveStartIndex = edit.index + 1;
              }
            else
              {
                moveStartIndex = edit.index;
              }
            childStartIndex = 0;
            children = new Element[childrenToMove];
          }
        else
          {
            if (! isEnd)
              {
                // Branch.
                childrenToMove++;
                moveStartIndex = edit.index;
            }
            else
              {
                // Last leaf, need to recreate part of it.
                moveStartIndex = edit.index + 1;
              }
            children = new Element[childrenToMove];
            children[0] = newChild;
        }

        for (int c = childStartIndex; c < childrenToMove; c++)
          {
            Element toMove = edit.e.getElement(moveStartIndex++);
            children[c] = recreateFracturedElement(parent, toMove);
            edit.removed.add(toMove);
          }
        ((BranchElement) parent).replace(0, 0, children);
        parent = newChild;
      }

    }

    private Element recreateFracturedElement(Element parent, Element toCopy)
    {
      Element recreated;
      if(toCopy.isLeaf())
        {
          recreated = createLeafElement(parent, toCopy.getAttributes(),
                                  Math.max(toCopy.getStartOffset(), endOffset),
                                  toCopy.getEndOffset());
        }
      else
        {
          Element newParent = createBranchElement(parent,
                                                  toCopy.getAttributes());
          int childCount = toCopy.getElementCount();
          Element[] newChildren = new Element[childCount];
          for (int i = 0; i < childCount; i++)
            {
              newChildren[i] = recreateFracturedElement(newParent,
                                                        toCopy.getElement(i));
            }
          ((BranchElement) newParent).replace(0, 0, newChildren);
          recreated = newParent;
        }
      return recreated;
    }

    private boolean split(int offs, int len)
    {
      boolean splitEnd = false;
      // Push the path to the stack.
      Element e = root;
      int index = e.getElementIndex(offs);
      while (! e.isLeaf())
        {
          elementStack.push(new Edit(e, index));
          e = e.getElement(index);
          index = e.getElementIndex(offs);
        }

      Edit ec = (Edit) elementStack.peek();
      Element child = ec.e.getElement(ec.index);
      // Make sure there is something to do. If the
      // offset is already at a boundary then there is
      // nothing to do.
      if (child.getStartOffset() < offs && offs < child.getEndOffset())
        {
          // We need to split, now see if the other end is within
          // the same parent.
          int index0 = ec.index;
          int index1 = index0;
          if (((offs + len) < ec.e.getEndOffset()) && (len != 0))
            {
              // It's a range split in the same parent.
              index1 = ec.e.getElementIndex(offs+len);
              if (index1 == index0)
                {
                  // It's a three-way split.
                  ec.removed.add(child);
                  e = createLeafElement(ec.e, child.getAttributes(),
                                        child.getStartOffset(), offs);
                  ec.added.add(e);
                  e = createLeafElement(ec.e, child.getAttributes(),
                                        offs, offs + len);
                  ec.added.add(e);
                  e = createLeafElement(ec.e, child.getAttributes(),
                                        offs + len, child.getEndOffset());
                  ec.added.add(e);
                  return true;
                }
              else
                {
                  child = ec.e.getElement(index1);
                  if ((offs + len) == child.getStartOffset())
                    {
                      // End is already on a boundary.
                      index1 = index0;
                    }
                }
              splitEnd = true;
            }

          // Split the first location.
          pos = offs;
          child = ec.e.getElement(index0);
          ec.removed.add(child);
          e = createLeafElement(ec.e, child.getAttributes(),
                                child.getStartOffset(), pos);
          ec.added.add(e);
          e = createLeafElement(ec.e, child.getAttributes(),
                                pos, child.getEndOffset());
          ec.added.add(e);

          // Pick up things in the middle.
          for (int i = index0 + 1; i < index1; i++)
            {
              child = ec.e.getElement(i);
              ec.removed.add(child);
              ec.added.add(child);
            }

          if (index1 != index0)
            {
              child = ec.e.getElement(index1);
              pos = offs + len;
              ec.removed.add(child);
              e = createLeafElement(ec.e, child.getAttributes(),
                                    child.getStartOffset(), pos);
              ec.added.add(e);
              e = createLeafElement(ec.e, child.getAttributes(),
                                    pos, child.getEndOffset());
              
              ec.added.add(e);
            }
        }
      return splitEnd;
      
    }

  }


  /**
   * An element type for sections. This is a simple BranchElement with a unique
   * name.
   */
  protected class SectionElement extends BranchElement
  {
    /**
     * Creates a new SectionElement.
     */
    public SectionElement()
    {
      super(null, null);
    }

    /**
     * Returns the name of the element. This method always returns
     * &quot;section&quot;.
     * 
     * @return the name of the element
     */
    public String getName()
    {
      return SectionElementName;
    }
  }

  /**
   * Receives notification when any of the document's style changes and calls
   * {@link DefaultStyledDocument#styleChanged(Style)}.
   * 
   * @author Roman Kennke (kennke@aicas.com)
   */
  private class StyleChangeListener implements ChangeListener
  {

    /**
     * Receives notification when any of the document's style changes and calls
     * {@link DefaultStyledDocument#styleChanged(Style)}.
     * 
     * @param event
     *          the change event
     */
    public void stateChanged(ChangeEvent event)
    {
      Style style = (Style) event.getSource();
      styleChanged(style);
    }
  }

  /** The serialization UID (compatible with JDK1.5). */
  private static final long serialVersionUID = 940485415728614849L;

  /**
   * The default size to use for new content buffers.
   */
  public static final int BUFFER_SIZE_DEFAULT = 4096;

  /**
   * The <code>EditorBuffer</code> that is used to manage to
   * <code>Element</code> hierarchy.
   */
  protected DefaultStyledDocument.ElementBuffer buffer;

  /**
   * Listens for changes on this document's styles and notifies styleChanged().
   */
  private StyleChangeListener styleChangeListener;

  /**
   * Creates a new <code>DefaultStyledDocument</code>.
   */
  public DefaultStyledDocument()
  {
    this(new GapContent(BUFFER_SIZE_DEFAULT), new StyleContext());
  }

  /**
   * Creates a new <code>DefaultStyledDocument</code> that uses the specified
   * {@link StyleContext}.
   * 
   * @param context
   *          the <code>StyleContext</code> to use
   */
  public DefaultStyledDocument(StyleContext context)
  {
    this(new GapContent(BUFFER_SIZE_DEFAULT), context);
  }

  /**
   * Creates a new <code>DefaultStyledDocument</code> that uses the specified
   * {@link StyleContext} and {@link Content} buffer.
   * 
   * @param content
   *          the <code>Content</code> buffer to use
   * @param context
   *          the <code>StyleContext</code> to use
   */
  public DefaultStyledDocument(AbstractDocument.Content content,
                               StyleContext context)
  {
    super(content, context);
    buffer = new ElementBuffer(createDefaultRoot());
    setLogicalStyle(0, context.getStyle(StyleContext.DEFAULT_STYLE));
  }

  /**
   * Adds a style into the style hierarchy. Unspecified style attributes can be
   * resolved in the <code>parent</code> style, if one is specified. While it
   * is legal to add nameless styles (<code>nm == null</code),
   * you must be aware that the client application is then responsible
   * for managing the style hierarchy, since unnamed styles cannot be
   * looked up by their name.
   *
   * @param nm the name of the style or <code>null</code> if the style should
   *           be unnamed
   * @param parent the parent in which unspecified style attributes are
   *           resolved, or <code>null</code> if that is not necessary
   *
   * @return the newly created <code>Style</code>
   */
  public Style addStyle(String nm, Style parent)
  {
    StyleContext context = (StyleContext) getAttributeContext();
    Style newStyle = context.addStyle(nm, parent);

    // Register change listener.
    if (styleChangeListener == null)
      styleChangeListener = new StyleChangeListener();
    newStyle.addChangeListener(styleChangeListener);

    return newStyle;
  }

  /**
   * Create the default root element for this kind of <code>Document</code>.
   * 
   * @return the default root element for this kind of <code>Document</code>
   */
  protected AbstractDocument.AbstractElement createDefaultRoot()
  {
    Element[] tmp;
    SectionElement section = new SectionElement();

    BranchElement paragraph = new BranchElement(section, null);
    tmp = new Element[1];
    tmp[0] = paragraph;
    section.replace(0, 0, tmp);

    Element leaf = new LeafElement(paragraph, null, 0, 1);
    tmp = new Element[1];
    tmp[0] = leaf;
    paragraph.replace(0, 0, tmp);

    return section;
  }

  /**
   * Returns the <code>Element</code> that corresponds to the character at the
   * specified position.
   * 
   * @param position
   *          the position of which we query the corresponding
   *          <code>Element</code>
   * @return the <code>Element</code> that corresponds to the character at the
   *         specified position
   */
  public Element getCharacterElement(int position)
  {
    Element element = getDefaultRootElement();

    while (!element.isLeaf())
      {
        int index = element.getElementIndex(position);
        element = element.getElement(index);
      }

    return element;
  }

  /**
   * Extracts a background color from a set of attributes.
   * 
   * @param attributes
   *          the attributes from which to get a background color
   * @return the background color that correspond to the attributes
   */
  public Color getBackground(AttributeSet attributes)
  {
    StyleContext context = (StyleContext) getAttributeContext();
    return context.getBackground(attributes);
  }

  /**
   * Returns the default root element.
   * 
   * @return the default root element
   */
  public Element getDefaultRootElement()
  {
    return buffer.getRootElement();
  }

  /**
   * Extracts a font from a set of attributes.
   * 
   * @param attributes
   *          the attributes from which to get a font
   * @return the font that correspond to the attributes
   */
  public Font getFont(AttributeSet attributes)
  {
    StyleContext context = (StyleContext) getAttributeContext();
    return context.getFont(attributes);
  }

  /**
   * Extracts a foreground color from a set of attributes.
   * 
   * @param attributes
   *          the attributes from which to get a foreground color
   * @return the foreground color that correspond to the attributes
   */
  public Color getForeground(AttributeSet attributes)
  {
    StyleContext context = (StyleContext) getAttributeContext();
    return context.getForeground(attributes);
  }

  /**
   * Returns the logical <code>Style</code> for the specified position.
   * 
   * @param position
   *          the position from which to query to logical style
   * @return the logical <code>Style</code> for the specified position
   */
  public Style getLogicalStyle(int position)
  {
    Element paragraph = getParagraphElement(position);
    AttributeSet attributes = paragraph.getAttributes();
    AttributeSet a = attributes.getResolveParent();
    // If the resolve parent is not of type Style, we return null.
    if (a instanceof Style)
      return (Style) a;
    return null;
  }

  /**
   * Returns the paragraph element for the specified position. If the position
   * is outside the bounds of the document's root element, then the closest
   * element is returned. That is the last paragraph if
   * <code>position >= endIndex</code> or the first paragraph if
   * <code>position < startIndex</code>.
   * 
   * @param position
   *          the position for which to query the paragraph element
   * @return the paragraph element for the specified position
   */
  public Element getParagraphElement(int position)
  {
    Element e = getDefaultRootElement();
    while (!e.isLeaf())
      e = e.getElement(e.getElementIndex(position));

    if (e != null)
      return e.getParentElement();
    return e;
  }

  /**
   * Looks up and returns a named <code>Style</code>.
   * 
   * @param nm
   *          the name of the <code>Style</code>
   * @return the found <code>Style</code> of <code>null</code> if no such
   *         <code>Style</code> exists
   */
  public Style getStyle(String nm)
  {
    StyleContext context = (StyleContext) getAttributeContext();
    return context.getStyle(nm);
  }

  /**
   * Removes a named <code>Style</code> from the style hierarchy.
   * 
   * @param nm
   *          the name of the <code>Style</code> to be removed
   */
  public void removeStyle(String nm)
  {
    StyleContext context = (StyleContext) getAttributeContext();
    context.removeStyle(nm);
  }

  /**
   * Sets text attributes for the fragment specified by <code>offset</code>
   * and <code>length</code>.
   * 
   * @param offset
   *          the start offset of the fragment
   * @param length
   *          the length of the fragment
   * @param attributes
   *          the text attributes to set
   * @param replace
   *          if <code>true</code>, the attributes of the current selection
   *          are overridden, otherwise they are merged
   */
  public void setCharacterAttributes(int offset, int length,
                                     AttributeSet attributes, boolean replace)
  {
    // Exit early if length is 0, so no DocumentEvent is created or fired.
    if (length == 0)
      return;
    try
      {
        // Must obtain a write lock for this method. writeLock() and
        // writeUnlock() should always be in try/finally block to make
        // sure that locking happens in a balanced manner.
        writeLock();
        DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
                                                           length,
                                                           DocumentEvent.EventType.CHANGE);

        // Modify the element structure so that the interval begins at an
        // element
        // start and ends at an element end.
        buffer.change(offset, length, ev);

        // Visit all paragraph elements within the specified interval
        int end = offset + length;
        Element curr;
        for (int pos = offset; pos < end;)
          {
            // Get the CharacterElement at offset pos.
            curr = getCharacterElement(pos);
            if (pos == curr.getEndOffset())
              break;

            MutableAttributeSet a = (MutableAttributeSet) curr.getAttributes();
            ev.addEdit(new AttributeUndoableEdit(curr, attributes, replace));
            // If replace is true, remove all the old attributes.
            if (replace)
              a.removeAttributes(a);
            // Add all the new attributes.
            a.addAttributes(attributes);
            // Increment pos so we can check the next CharacterElement.
            pos = curr.getEndOffset();
          }
        fireChangedUpdate(ev);
        fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
      }
    finally
      {
        writeUnlock();
      }
  }

  /**
   * Sets the logical style for the paragraph at the specified position.
   * 
   * @param position
   *          the position at which the logical style is added
   * @param style
   *          the style to set for the current paragraph
   */
  public void setLogicalStyle(int position, Style style)
  {
    Element el = getParagraphElement(position);
    // getParagraphElement doesn't return null but subclasses might so
    // we check for null here.
    if (el == null)
      return;
    try
      {
        writeLock();
        if (el instanceof AbstractElement)
          {
            AbstractElement ael = (AbstractElement) el;
            ael.setResolveParent(style);
            int start = el.getStartOffset();
            int end = el.getEndOffset();
            DefaultDocumentEvent ev = new DefaultDocumentEvent(start,
                                                               end - start,
                                                               DocumentEvent.EventType.CHANGE);
            fireChangedUpdate(ev);
            fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
          }
        else
          throw new AssertionError(
                                   "paragraph elements are expected to be"
                                       + "instances of AbstractDocument.AbstractElement");
      }
    finally
      {
        writeUnlock();
      }
  }

  /**
   * Sets text attributes for the paragraph at the specified fragment.
   * 
   * @param offset
   *          the beginning of the fragment
   * @param length
   *          the length of the fragment
   * @param attributes
   *          the text attributes to set
   * @param replace
   *          if <code>true</code>, the attributes of the current selection
   *          are overridden, otherwise they are merged
   */
  public void setParagraphAttributes(int offset, int length,
                                     AttributeSet attributes, boolean replace)
  {
    try
      {
        // Must obtain a write lock for this method. writeLock() and
        // writeUnlock() should always be in try/finally blocks to make
        // sure that locking occurs in a balanced manner.
        writeLock();

        // Create a DocumentEvent to use for changedUpdate().
        DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
                                                           length,
                                                           DocumentEvent.EventType.CHANGE);

        // Have to iterate through all the _paragraph_ elements that are
        // contained or partially contained in the interval
        // (offset, offset + length).
        Element rootElement = getDefaultRootElement();
        int startElement = rootElement.getElementIndex(offset);
        int endElement = rootElement.getElementIndex(offset + length - 1);
        if (endElement < startElement)
          endElement = startElement;

        for (int i = startElement; i <= endElement; i++)
          {
            Element par = rootElement.getElement(i);
            MutableAttributeSet a = (MutableAttributeSet) par.getAttributes();
            // Add the change to the DocumentEvent.
            ev.addEdit(new AttributeUndoableEdit(par, attributes, replace));
            // If replace is true remove the old attributes.
            if (replace)
              a.removeAttributes(a);
            // Add the new attributes.
            a.addAttributes(attributes);
          }
        fireChangedUpdate(ev);
        fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
      }
    finally
      {
        writeUnlock();
      }
  }

  /**
   * Called in response to content insert actions. This is used to update the
   * element structure.
   * 
   * @param ev
   *          the <code>DocumentEvent</code> describing the change
   * @param attr
   *          the attributes for the change
   */
  protected void insertUpdate(DefaultDocumentEvent ev, AttributeSet attr)
  {
    int offs = ev.getOffset();
    int len = ev.getLength();
    int endOffs = offs + len;
    if (attr == null)
      attr = SimpleAttributeSet.EMPTY;

    // Paragraph attributes are fetched from the point _after_ the insertion.
    Element paragraph = getParagraphElement(endOffs);
    AttributeSet pAttr = paragraph.getAttributes();
    // Character attributes are fetched from the actual insertion point.
    Element paragraph2 = getParagraphElement(offs);
    int contIndex = paragraph2.getElementIndex(offs);
    Element content = paragraph2.getElement(contIndex);
    AttributeSet cAttr = content.getAttributes();

    boolean insertAtBoundary = content.getEndOffset() == endOffs;
    try
      {
        Segment s = new Segment();
        ArrayList buf = new ArrayList();
        ElementSpec lastStartTag = null;
        boolean insertAfterNewline = false;
        short lastStartDir = ElementSpec.OriginateDirection;

        // Special handle if we are inserting after a newline.
        if (offs > 0)
          {
            getText(offs - 1, 1, s);
            if (s.array[s.offset] == '\n')
              {
                insertAfterNewline = true;
                lastStartDir = insertAfterNewline(paragraph, paragraph2,
                                                  pAttr, buf, offs,
                                                  endOffs);
                // Search last start tag.
                for (int i = buf.size() - 1; i >= 0 && lastStartTag == null;
                     i--)
                  {
                    ElementSpec tag = (ElementSpec) buf.get(i);
                    if (tag.getType() == ElementSpec.StartTagType)
                      {
                        lastStartTag = tag;
                      }
                  }
              }

          }

        // If we are not inserting after a newline, the paragraph attributes
        // come from the paragraph under the insertion point.
        if (! insertAfterNewline)
          pAttr = paragraph2.getAttributes();

        // Scan text and build up the specs.
        getText(offs, len, s);
        int end = s.offset + s.count;
        int last = s.offset;
        for (int i = s.offset; i < end; i++)
          {
            if (s.array[i] == '\n')
              {
                int breakOffs = i + 1;
                buf.add(new ElementSpec(attr, ElementSpec.ContentType,
                                        breakOffs - last));
                buf.add(new ElementSpec(null, ElementSpec.EndTagType));
                lastStartTag = new ElementSpec(pAttr,
                                               ElementSpec.StartTagType);
                buf.add(lastStartTag);
                last = breakOffs;
              }
          }

        // Need to add a tailing content tag if we didn't finish at a boundary.
        if (last < end)
          {
            buf.add(new ElementSpec(attr, ElementSpec.ContentType,
                                    end - last));
          }

        // Now we need to fix up the directions of the specs.
        ElementSpec first = (ElementSpec) buf.get(0);
        int doclen = getLength();

        // Maybe join-previous the first tag if it is content and has
        // the same attributes as the previous character run.
        if (first.getType() == ElementSpec.ContentType && cAttr.isEqual(attr))
          first.setDirection(ElementSpec.JoinPreviousDirection);

        // Join-fracture or join-next the last start tag if necessary.
        if (lastStartTag != null)
          {
            if (insertAfterNewline)
              lastStartTag.setDirection(lastStartDir);
            else if (paragraph2.getEndOffset() != endOffs)
              lastStartTag.setDirection(ElementSpec.JoinFractureDirection);
            else
              {
                Element par = paragraph2.getParentElement();
                int par2Index = par.getElementIndex(offs);
                if (par2Index + 1 < par.getElementCount()
                    && ! par.getElement(par2Index + 1).isLeaf())
                  lastStartTag.setDirection(ElementSpec.JoinNextDirection);
              }
          }

        // Join-next last tag if possible.
        if (insertAtBoundary && endOffs < doclen)
          {
            ElementSpec lastTag = (ElementSpec) buf.get(buf.size() - 1);
            if (lastTag.getType() == ElementSpec.ContentType
                && ((lastStartTag == null
                     && (paragraph == paragraph2 || insertAfterNewline))
                    || (lastStartTag != null
             && lastStartTag.getDirection() != ElementSpec.OriginateDirection)))
              {
                int nextIndex = paragraph.getElementIndex(endOffs);
                Element nextRun = paragraph.getElement(nextIndex);
                if (nextRun.isLeaf() && attr.isEqual(nextRun.getAttributes()))
                  lastTag.setDirection(ElementSpec.JoinNextDirection);
              }
          }

        else if (! insertAtBoundary && lastStartTag != null
           && lastStartTag.getDirection() == ElementSpec.JoinFractureDirection)
          {
            ElementSpec lastTag = (ElementSpec) buf.get(buf.size() - 1);
            if (lastTag.getType() == ElementSpec.ContentType
                && lastTag.getDirection() != ElementSpec.JoinPreviousDirection
                && attr.isEqual(cAttr))
              {
                lastTag.setDirection(ElementSpec.JoinNextDirection);
              }
          }

        ElementSpec[] specs = new ElementSpec[buf.size()];
        specs = (ElementSpec[]) buf.toArray(specs);
        buffer.insert(offs, len, specs, ev);
      }
    catch (BadLocationException ex)
      {
        // Ignore this. Comment out for debugging.
        ex.printStackTrace();
      }
    super.insertUpdate(ev, attr);
  }

  private short insertAfterNewline(Element par1, Element par2,
                                   AttributeSet attr, ArrayList buf,
                                   int offs, int endOffs)
  {
    short dir = 0;
    if (par1.getParentElement() == par2.getParentElement())
      {
        ElementSpec tag = new ElementSpec(attr, ElementSpec.EndTagType);
        buf.add(tag);
        tag = new ElementSpec(attr, ElementSpec.StartTagType);
        buf.add(tag);
        if (par2.getEndOffset() != endOffs)
          dir = ElementSpec.JoinFractureDirection;
        else
          {
            Element par = par2.getParentElement();
            if (par.getElementIndex(offs) + 1 < par.getElementCount())
              dir = ElementSpec.JoinNextDirection;
          }
      }
    else
      {
        // For text with more than 2 levels, find the common parent of
        // par1 and par2.
        ArrayList parentsLeft = new ArrayList();
        ArrayList parentsRight = new ArrayList();
        Element e = par2;
        while (e != null)
          {
            parentsLeft.add(e);
            e = e.getParentElement();
          }
        e = par1;
        int leftIndex = -1;
        while (e != null && (leftIndex = parentsLeft.indexOf(e)) == 1)
          {
            parentsRight.add(e);
            e = e.getParentElement();
          }

        if (e != null)
       
          {
            // e is now the common parent.
            // Insert the end tags.
            for (int c = 0; c < leftIndex; c++)
              {
                buf.add(new ElementSpec(null, ElementSpec.EndTagType));
              }
            // Insert the start tags.
            for (int c = parentsRight.size() - 1; c >= 0; c--)
              {
                Element el = (Element) parentsRight.get(c);
                ElementSpec tag = new ElementSpec(el.getAttributes(),
                                                  ElementSpec.StartTagType);
                if (c > 0)
                  tag.setDirection(ElementSpec.JoinNextDirection);
                buf.add(tag);
              }
            if (parentsRight.size() > 0)
              dir = ElementSpec.JoinNextDirection;
            else
              dir = ElementSpec.JoinFractureDirection;
          }
        else
          assert false;
      }
    return dir;
  }

  /**
   * A helper method to set up the ElementSpec buffer for the special case of an
   * insertion occurring immediately after a newline.
   * 
   * @param specs
   *          the ElementSpec buffer to initialize.
   */
  short handleInsertAfterNewline(Vector specs, int offset, int endOffset,
                                 Element prevParagraph, Element paragraph,
                                 AttributeSet a)
  {
    if (prevParagraph.getParentElement() == paragraph.getParentElement())
      {
        specs.add(new ElementSpec(a, ElementSpec.EndTagType));
        specs.add(new ElementSpec(a, ElementSpec.StartTagType));
        if (paragraph.getStartOffset() != endOffset)
          return ElementSpec.JoinFractureDirection;
        // If there is an Element after this one, use JoinNextDirection.
        Element parent = paragraph.getParentElement();
        if (parent.getElementCount() > (parent.getElementIndex(offset) + 1))
          return ElementSpec.JoinNextDirection;
      }
    return ElementSpec.OriginateDirection;
  }

  /**
   * Updates the document structure in response to text removal. This is
   * forwarded to the {@link ElementBuffer} of this document. Any changes to the
   * document structure are added to the specified document event and sent to
   * registered listeners.
   * 
   * @param ev
   *          the document event that records the changes to the document
   */
  protected void removeUpdate(DefaultDocumentEvent ev)
  {
    super.removeUpdate(ev);
    buffer.remove(ev.getOffset(), ev.getLength(), ev);
  }

  /**
   * Returns an enumeration of all style names.
   * 
   * @return an enumeration of all style names
   */
  public Enumeration<?> getStyleNames()
  {
    StyleContext context = (StyleContext) getAttributeContext();
    return context.getStyleNames();
  }

  /**
   * Called when any of this document's styles changes.
   * 
   * @param style
   *          the style that changed
   */
  protected void styleChanged(Style style)
  {
    // Nothing to do here. This is intended to be overridden by subclasses.
  }

  /**
   * Inserts a bulk of structured content at once.
   * 
   * @param offset
   *          the offset at which the content should be inserted
   * @param data
   *          the actual content spec to be inserted
   */
  protected void insert(int offset, ElementSpec[] data)
      throws BadLocationException
  {
    if (data == null || data.length == 0)
      return;
    try
      {
        // writeLock() and writeUnlock() should always be in a try/finally
        // block so that locking balance is guaranteed even if some
        // exception is thrown.
        writeLock();

        // First we collect the content to be inserted.
        StringBuffer contentBuffer = new StringBuffer();
        for (int i = 0; i < data.length; i++)
          {
            // Collect all inserts into one so we can get the correct
            // ElementEdit
            ElementSpec spec = data[i];
            if (spec.getArray() != null && spec.getLength() > 0)
              contentBuffer.append(spec.getArray(), spec.getOffset(),
                                   spec.getLength());
          }

        int length = contentBuffer.length();

        // If there was no content inserted then exit early.
        if (length == 0)
          return;

        Content c = getContent();
        UndoableEdit edit = c.insertString(offset,
                                           contentBuffer.toString());

        // Create the DocumentEvent with the ElementEdit added
        DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
                                                           length,
                                                           DocumentEvent.EventType.INSERT);

        ev.addEdit(edit);

        // Finally we must update the document structure and fire the insert
        // update event.
        buffer.insert(offset, length, data, ev);

        super.insertUpdate(ev, null);

        ev.end();
        fireInsertUpdate(ev);
        fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
      }
    finally
      {
        writeUnlock();
      }
  }

  /**
   * Initializes the <code>DefaultStyledDocument</code> with the specified
   * data.
   * 
   * @param data
   *          the specification of the content with which the document is
   *          initialized
   */
  protected void create(ElementSpec[] data)
  {
    try
      {

        // Clear content if there is some.
        int len = getLength();
        if (len > 0)
          remove(0, len);

        writeLock();

        // Now we insert the content.
        StringBuilder b = new StringBuilder();
        for (int i = 0; i < data.length; ++i)
          {
            ElementSpec el = data[i];
            if (el.getArray() != null && el.getLength() > 0)
              b.append(el.getArray(), el.getOffset(), el.getLength());
          }
        Content content = getContent();
        UndoableEdit cEdit = content.insertString(0, b.toString());

        len = b.length();
        DefaultDocumentEvent ev =
          new DefaultDocumentEvent(0, b.length(),
                                   DocumentEvent.EventType.INSERT);
        ev.addEdit(cEdit);

        buffer.create(len, data, ev);

        // For the bidi update.
        super.insertUpdate(ev, null);

        ev.end();
        fireInsertUpdate(ev);
        fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
      }
    catch (BadLocationException ex)
      {
        AssertionError err = new AssertionError("Unexpected bad location");
        err.initCause(ex);
        throw err;
      }
    finally
      {
        writeUnlock();
      }
  }
}
