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

This file is part of GNU Classpath.

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

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

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

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

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


package javax.swing.text;

import gnu.java.lang.CPStringBuilder;

import java.awt.font.TextAttribute;
import java.io.PrintStream;
import java.io.Serializable;
import java.text.Bidi;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Vector;

import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.EventListenerList;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.DocumentFilter;
import javax.swing.tree.TreeNode;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CompoundEdit;
import javax.swing.undo.UndoableEdit;

/**
 * An abstract base implementation for the {@link Document} interface.
 * This class provides some common functionality for all <code>Element</code>s,
 * most notably it implements a locking mechanism to make document modification
 * thread-safe.
 *
 * @author original author unknown
 * @author Roman Kennke (roman@kennke.org)
 */
public abstract class AbstractDocument implements Document, Serializable
{
  /** The serialization UID (compatible with JDK1.5). */
  private static final long serialVersionUID = 6842927725919637215L;

  /**
   * Standard error message to indicate a bad location.
   */
  protected static final String BAD_LOCATION = "document location failure";

  /**
   * Standard name for unidirectional <code>Element</code>s.
   */
  public static final String BidiElementName = "bidi level";

  /**
   * Standard name for content <code>Element</code>s. These are usually
   * {@link LeafElement}s.
   */
  public static final String ContentElementName = "content";

  /**
   * Standard name for paragraph <code>Element</code>s. These are usually
   * {@link BranchElement}s.
   */
  public static final String ParagraphElementName = "paragraph";

  /**
   * Standard name for section <code>Element</code>s. These are usually
   * {@link DefaultStyledDocument.SectionElement}s.
   */
  public static final String SectionElementName = "section";

  /**
   * Attribute key for storing the element name.
   */
  public static final String ElementNameAttribute = "$ename";

  /**
   * Standard name for the bidi root element.
   */
  private static final String BidiRootName = "bidi root";

  /**
   * Key for storing the asynchronous load priority.
   */
  private static final String AsyncLoadPriority = "load priority";

  /**
   * Key for storing the I18N state.
   */
  private static final String I18N = "i18n";

  /**
   * The actual content model of this <code>Document</code>.
   */
  Content content;

  /**
   * The AttributeContext for this <code>Document</code>.
   */
  AttributeContext context;

  /**
   * The currently installed <code>DocumentFilter</code>.
   */
  DocumentFilter documentFilter;

  /**
   * The documents properties.
   */
  Dictionary properties;

  /**
   * Manages event listeners for this <code>Document</code>.
   */
  protected EventListenerList listenerList = new EventListenerList();

  /**
   * Stores the current writer thread.  Used for locking.
   */
  private Thread currentWriter = null;

  /**
   * The number of readers.  Used for locking.
   */
  private int numReaders = 0;

  /**
   * The number of current writers. If this is > 1 then the same thread entered
   * the write lock more than once.
   */
  private int numWriters = 0;

  /** An instance of a DocumentFilter.FilterBypass which allows calling
   * the insert, remove and replace method without checking for an installed
   * document filter.
   */
  private DocumentFilter.FilterBypass bypass;

  /**
   * The bidi root element.
   */
  private BidiRootElement bidiRoot;

  /**
   * True when we are currently notifying any listeners. This is used
   * to detect illegal situations in writeLock().
   */
  private transient boolean notifyListeners;

  /**
   * Creates a new <code>AbstractDocument</code> with the specified
   * {@link Content} model.
   *
   * @param doc the <code>Content</code> model to be used in this
   *        <code>Document<code>
   *
   * @see GapContent
   * @see StringContent
   */
  protected AbstractDocument(Content doc)
  {
    this(doc, StyleContext.getDefaultStyleContext());
  }

  /**
   * Creates a new <code>AbstractDocument</code> with the specified
   * {@link Content} model and {@link AttributeContext}.
   *
   * @param doc the <code>Content</code> model to be used in this
   *        <code>Document<code>
   * @param ctx the <code>AttributeContext</code> to use
   *
   * @see GapContent
   * @see StringContent
   */
  protected AbstractDocument(Content doc, AttributeContext ctx)
  {
    content = doc;
    context = ctx;

    // FIXME: Fully implement bidi.
    bidiRoot = new BidiRootElement();

    // FIXME: This is determined using a Mauve test. Make the document
    // actually use this.
    putProperty(I18N, Boolean.FALSE);

    // Add one child to the bidi root.
    writeLock();
    try
      {
        Element[] children = new Element[1];
        children[0] = new BidiElement(bidiRoot, 0, 1, 0);
        bidiRoot.replace(0, 0, children);
      }
    finally
      {
        writeUnlock();
      }
  }

  /** Returns the DocumentFilter.FilterBypass instance for this
   * document and create it if it does not exist yet.
   *
   * @return This document's DocumentFilter.FilterBypass instance.
   */
  private DocumentFilter.FilterBypass getBypass()
  {
    if (bypass == null)
      bypass = new Bypass();

    return bypass;
  }

  /**
   * Returns the paragraph {@link Element} that holds the specified position.
   *
   * @param pos the position for which to get the paragraph element
   *
   * @return the paragraph {@link Element} that holds the specified position
   */
  public abstract Element getParagraphElement(int pos);

  /**
   * Returns the default root {@link Element} of this <code>Document</code>.
   * Usual <code>Document</code>s only have one root element and return this.
   * However, there may be <code>Document</code> implementations that
   * support multiple root elements, they have to return a default root element
   * here.
   *
   * @return the default root {@link Element} of this <code>Document</code>
   */
  public abstract Element getDefaultRootElement();

  /**
   * Creates and returns a branch element with the specified
   * <code>parent</code> and <code>attributes</code>. Note that the new
   * <code>Element</code> is linked to the parent <code>Element</code>
   * through {@link Element#getParentElement}, but it is not yet added
   * to the parent <code>Element</code> as child.
   *
   * @param parent the parent <code>Element</code> for the new branch element
   * @param attributes the text attributes to be installed in the new element
   *
   * @return the new branch <code>Element</code>
   *
   * @see BranchElement
   */
  protected Element createBranchElement(Element parent,
                                        AttributeSet attributes)
  {
    return new BranchElement(parent, attributes);
  }

  /**
   * Creates and returns a leaf element with the specified
   * <code>parent</code> and <code>attributes</code>. Note that the new
   * <code>Element</code> is linked to the parent <code>Element</code>
   * through {@link Element#getParentElement}, but it is not yet added
   * to the parent <code>Element</code> as child.
   *
   * @param parent the parent <code>Element</code> for the new branch element
   * @param attributes the text attributes to be installed in the new element
   *
   * @return the new branch <code>Element</code>
   *
   * @see LeafElement
   */
  protected Element createLeafElement(Element parent, AttributeSet attributes,
                                      int start, int end)
  {
    return new LeafElement(parent, attributes, start, end);
  }

  /**
   * Creates a {@link Position} that keeps track of the location at the
   * specified <code>offset</code>.
   *
   * @param offset the location in the document to keep track by the new
   *        <code>Position</code>
   *
   * @return the newly created <code>Position</code>
   *
   * @throws BadLocationException if <code>offset</code> is not a valid
   *         location in the documents content model
   */
  public synchronized Position createPosition(final int offset)
    throws BadLocationException
  {
    return content.createPosition(offset);
  }

  /**
   * Notifies all registered listeners when the document model changes.
   *
   * @param event the <code>DocumentEvent</code> to be fired
   */
  protected void fireChangedUpdate(DocumentEvent event)
  {
    notifyListeners = true;
    try
      {
        DocumentListener[] listeners = getDocumentListeners();
        for (int index = 0; index < listeners.length; ++index)
          listeners[index].changedUpdate(event);
      }
    finally
      {
        notifyListeners = false;
      }
  }

  /**
   * Notifies all registered listeners when content is inserted in the document
   * model.
   *
   * @param event the <code>DocumentEvent</code> to be fired
   */
  protected void fireInsertUpdate(DocumentEvent event)
  {
    notifyListeners = true;
    try
      {
        DocumentListener[] listeners = getDocumentListeners();
        for (int index = 0; index < listeners.length; ++index)
          listeners[index].insertUpdate(event);
      }
    finally
      {
        notifyListeners = false;
      }
  }

  /**
   * Notifies all registered listeners when content is removed from the
   * document model.
   *
   * @param event the <code>DocumentEvent</code> to be fired
   */
  protected void fireRemoveUpdate(DocumentEvent event)
  {
    notifyListeners = true;
    try
      {
        DocumentListener[] listeners = getDocumentListeners();
        for (int index = 0; index < listeners.length; ++index)
          listeners[index].removeUpdate(event);
      }
    finally
      {
        notifyListeners = false;
      }
  }

  /**
   * Notifies all registered listeners when an <code>UndoableEdit</code> has
   * been performed on this <code>Document</code>.
   *
   * @param event the <code>UndoableEditEvent</code> to be fired
   */
  protected void fireUndoableEditUpdate(UndoableEditEvent event)
  {
    UndoableEditListener[] listeners = getUndoableEditListeners();

    for (int index = 0; index < listeners.length; ++index)
      listeners[index].undoableEditHappened(event);
  }

  /**
   * Returns the asynchronous loading priority. Returns <code>-1</code> if this
   * document should not be loaded asynchronously.
   *
   * @return the asynchronous loading priority
   */
  public int getAsynchronousLoadPriority()
  {
    Object val = getProperty(AsyncLoadPriority);
    int prio = -1;
    if (val != null)
      prio = ((Integer) val).intValue();
    return prio;
  }

  /**
   * Returns the {@link AttributeContext} used in this <code>Document</code>.
   *
   * @return the {@link AttributeContext} used in this <code>Document</code>
   */
  protected final AttributeContext getAttributeContext()
  {
    return context;
  }

  /**
   * Returns the root element for bidirectional content.
   *
   * @return the root element for bidirectional content
   */
  public Element getBidiRootElement()
  {
    return bidiRoot;
  }

  /**
   * Returns the {@link Content} model for this <code>Document</code>
   *
   * @return the {@link Content} model for this <code>Document</code>
   *
   * @see GapContent
   * @see StringContent
   */
  protected final Content getContent()
  {
    return content;
  }

  /**
   * Returns the thread that currently modifies this <code>Document</code>
   * if there is one, otherwise <code>null</code>. This can be used to
   * distinguish between a method call that is part of an ongoing modification
   * or if it is a separate modification for which a new lock must be aquired.
   *
   * @return the thread that currently modifies this <code>Document</code>
   *         if there is one, otherwise <code>null</code>
   */
  protected final synchronized Thread getCurrentWriter()
  {
    return currentWriter;
  }

  /**
   * Returns the properties of this <code>Document</code>.
   *
   * @return the properties of this <code>Document</code>
   */
  public Dictionary<Object, Object> getDocumentProperties()
  {
    // FIXME: make me thread-safe
    if (properties == null)
      properties = new Hashtable();

    return properties;
  }

  /**
   * Returns a {@link Position} which will always mark the end of the
   * <code>Document</code>.
   *
   * @return a {@link Position} which will always mark the end of the
   *         <code>Document</code>
   */
  public final Position getEndPosition()
  {
    Position p;
    try
      {
        p = createPosition(content.length());
      }
    catch (BadLocationException ex)
      {
        // Shouldn't really happen.
        p = null;
      }
    return p;
  }

  /**
   * Returns the length of this <code>Document</code>'s content.
   *
   * @return the length of this <code>Document</code>'s content
   */
  public int getLength()
  {
    // We return Content.getLength() -1 here because there is always an
    // implicit \n at the end of the Content which does count in Content
    // but not in Document.
    return content.length() - 1;
  }

  /**
   * Returns all registered listeners of a given listener type.
   *
   * @param listenerType the type of the listeners to be queried
   *
   * @return all registered listeners of the specified type
   */
  public <T extends EventListener> T[] getListeners(Class<T> listenerType)
  {
    return listenerList.getListeners(listenerType);
  }

  /**
   * Returns a property from this <code>Document</code>'s property list.
   *
   * @param key the key of the property to be fetched
   *
   * @return the property for <code>key</code> or <code>null</code> if there
   *         is no such property stored
   */
  public final Object getProperty(Object key)
  {
    // FIXME: make me thread-safe
    Object value = null;
    if (properties != null)
      value = properties.get(key);

    return value;
  }

  /**
   * Returns all root elements of this <code>Document</code>. By default
   * this just returns the single root element returned by
   * {@link #getDefaultRootElement()}. <code>Document</code> implementations
   * that support multiple roots must override this method and return all roots
   * here.
   *
   * @return all root elements of this <code>Document</code>
   */
  public Element[] getRootElements()
  {
    Element[] elements = new Element[2];
    elements[0] = getDefaultRootElement();
    elements[1] = getBidiRootElement();
    return elements;
  }

  /**
   * Returns a {@link Position} which will always mark the beginning of the
   * <code>Document</code>.
   *
   * @return a {@link Position} which will always mark the beginning of the
   *         <code>Document</code>
   */
  public final Position getStartPosition()
  {
    Position p;
    try
      {
        p = createPosition(0);
      }
    catch (BadLocationException ex)
      {
        // Shouldn't really happen.
        p = null;
      }
    return p;
  }

  /**
   * Returns a piece of this <code>Document</code>'s content.
   *
   * @param offset the start offset of the content
   * @param length the length of the content
   *
   * @return the piece of content specified by <code>offset</code> and
   *         <code>length</code>
   *
   * @throws BadLocationException if <code>offset</code> or <code>offset +
   *         length</code> are invalid locations with this
   *         <code>Document</code>
   */
  public String getText(int offset, int length) throws BadLocationException
  {
    return content.getString(offset, length);
  }

  /**
   * Fetches a piece of this <code>Document</code>'s content and stores
   * it in the given {@link Segment}.
   *
   * @param offset the start offset of the content
   * @param length the length of the content
   * @param segment the <code>Segment</code> to store the content in
   *
   * @throws BadLocationException if <code>offset</code> or <code>offset +
   *         length</code> are invalid locations with this
   *         <code>Document</code>
   */
  public void getText(int offset, int length, Segment segment)
    throws BadLocationException
  {
    content.getChars(offset, length, segment);
  }

  /**
   * Inserts a String into this <code>Document</code> at the specified
   * position and assigning the specified attributes to it.
   *
   * <p>If a {@link DocumentFilter} is installed in this document, the
   * corresponding method of the filter object is called.</p>
   *
   * <p>The method has no effect when <code>text</code> is <code>null</code>
   * or has a length of zero.</p>
   *
   *
   * @param offset the location at which the string should be inserted
   * @param text the content to be inserted
   * @param attributes the text attributes to be assigned to that string
   *
   * @throws BadLocationException if <code>offset</code> is not a valid
   *         location in this <code>Document</code>
   */
  public void insertString(int offset, String text, AttributeSet attributes)
    throws BadLocationException
  {
    // Bail out if we have a bogus insertion (Behavior observed in RI).
    if (text == null || text.length() == 0)
      return;

    writeLock();
    try
      {
        if (documentFilter == null)
          insertStringImpl(offset, text, attributes);
        else
          documentFilter.insertString(getBypass(), offset, text, attributes);
      }
    finally
      {
        writeUnlock();
      }
  }

  void insertStringImpl(int offset, String text, AttributeSet attributes)
    throws BadLocationException
  {
    // Just return when no text to insert was given.
    if (text == null || text.length() == 0)
      return;
    DefaultDocumentEvent event =
      new DefaultDocumentEvent(offset, text.length(),
                               DocumentEvent.EventType.INSERT);

    UndoableEdit undo = content.insertString(offset, text);
    if (undo != null)
      event.addEdit(undo);

    // Check if we need bidi layout.
    if (getProperty(I18N).equals(Boolean.FALSE))
      {
        Object dir = getProperty(TextAttribute.RUN_DIRECTION);
        if (TextAttribute.RUN_DIRECTION_RTL.equals(dir))
          putProperty(I18N, Boolean.TRUE);
        else
          {
            char[] chars = text.toCharArray();
            if (Bidi.requiresBidi(chars, 0, chars.length))
              putProperty(I18N, Boolean.TRUE);
          }
      }

    insertUpdate(event, attributes);

    fireInsertUpdate(event);

    if (undo != null)
      fireUndoableEditUpdate(new UndoableEditEvent(this, undo));
  }

  /**
   * Called to indicate that text has been inserted into this
   * <code>Document</code>. The default implementation does nothing.
   * This method is executed within a write lock.
   *
   * @param chng the <code>DefaultDocumentEvent</code> describing the change
   * @param attr the attributes of the changed content
   */
  protected void insertUpdate(DefaultDocumentEvent chng, AttributeSet attr)
  {
    if (Boolean.TRUE.equals(getProperty(I18N)))
      updateBidi(chng);
  }

  /**
   * Called after some content has been removed from this
   * <code>Document</code>. The default implementation does nothing.
   * This method is executed within a write lock.
   *
   * @param chng the <code>DefaultDocumentEvent</code> describing the change
   */
  protected void postRemoveUpdate(DefaultDocumentEvent chng)
  {
    if (Boolean.TRUE.equals(getProperty(I18N)))
      updateBidi(chng);
  }

  /**
   * Stores a property in this <code>Document</code>'s property list.
   *
   * @param key the key of the property to be stored
   * @param value the value of the property to be stored
   */
  public final void putProperty(Object key, Object value)
  {
    // FIXME: make me thread-safe
    if (properties == null)
      properties = new Hashtable();

    if (value == null)
      properties.remove(key);
    else
      properties.put(key, value);

    // Update bidi structure if the RUN_DIRECTION is set.
    if (TextAttribute.RUN_DIRECTION.equals(key))
      {
        if (TextAttribute.RUN_DIRECTION_RTL.equals(value)
            && Boolean.FALSE.equals(getProperty(I18N)))
          putProperty(I18N, Boolean.TRUE);

        if (Boolean.TRUE.equals(getProperty(I18N)))
          {
            writeLock();
            try
              {
                DefaultDocumentEvent ev =
                  new DefaultDocumentEvent(0, getLength(),
                                           DocumentEvent.EventType.INSERT);
                updateBidi(ev);
              }
            finally
              {
                writeUnlock();
              }
          }
      }
  }

  /**
   * Updates the bidi element structure.
   *
   * @param ev the document event for the change
   */
  private void updateBidi(DefaultDocumentEvent ev)
  {
    // Determine start and end offset of the paragraphs to be scanned.
    int start = 0;
    int end = 0;
    DocumentEvent.EventType type = ev.getType();
    if (type == DocumentEvent.EventType.INSERT
        || type == DocumentEvent.EventType.CHANGE)
      {
        int offs = ev.getOffset();
        int endOffs = offs + ev.getLength();
        start = getParagraphElement(offs).getStartOffset();
        end = getParagraphElement(endOffs).getEndOffset();
      }
    else if (type == DocumentEvent.EventType.REMOVE)
      {
        Element par = getParagraphElement(ev.getOffset());
        start = par.getStartOffset();
        end = par.getEndOffset();
      }
    else
      assert false : "Unknown event type";

    // Determine the bidi levels for the affected range.
    Bidi[] bidis = getBidis(start, end);

    int removeFrom = 0;
    int removeTo = 0;

    int offs = 0;
    int lastRunStart = 0;
    int lastRunEnd = 0;
    int lastRunLevel = 0;
    ArrayList newEls = new ArrayList();
    for (int i = 0; i < bidis.length; i++)
      {
        Bidi bidi = bidis[i];
        int numRuns = bidi.getRunCount();
        for (int r = 0; r < numRuns; r++)
          {
            if (r == 0 && i == 0)
              {
                if (start > 0)
                  {
                    // Try to merge with the previous element if it has the
                    // same bidi level as the first run.
                    int prevElIndex = bidiRoot.getElementIndex(start - 1);
                    removeFrom = prevElIndex;
                    Element prevEl = bidiRoot.getElement(prevElIndex);
                    AttributeSet atts = prevEl.getAttributes();
                    int prevElLevel = StyleConstants.getBidiLevel(atts);
                    if (prevElLevel == bidi.getRunLevel(r))
                      {
                        // Merge previous element with current run.
                        lastRunStart = prevEl.getStartOffset() - start;
                        lastRunEnd = bidi.getRunLimit(r);
                        lastRunLevel  = bidi.getRunLevel(r);
                      }
                    else if (prevEl.getEndOffset() > start)
                      {
                        // Split previous element and replace by 2 new elements.
                        lastRunStart = 0;
                        lastRunEnd = bidi.getRunLimit(r);
                        lastRunLevel = bidi.getRunLevel(r);
                        newEls.add(new BidiElement(bidiRoot,
                                                   prevEl.getStartOffset(),
                                                   start, prevElLevel));
                      }
                    else
                      {
                        // Simply start new run at start location.
                        lastRunStart = 0;
                        lastRunEnd = bidi.getRunLimit(r);
                        lastRunLevel = bidi.getRunLevel(r);
                        removeFrom++;
                      }
                  }
                else
                  {
                    // Simply start new run at start location.
                    lastRunStart = 0;
                    lastRunEnd = bidi.getRunLimit(r);
                    lastRunLevel = bidi.getRunLevel(r);
                    removeFrom = 0;
                  }
              }
            if (i == bidis.length - 1 && r == numRuns - 1)
              {
                if (end <= getLength())
                  {
                    // Try to merge last element with next element.
                    int nextIndex = bidiRoot.getElementIndex(end);
                    Element nextEl = bidiRoot.getElement(nextIndex);
                    AttributeSet atts = nextEl.getAttributes();
                    int nextLevel = StyleConstants.getBidiLevel(atts);
                    int level = bidi.getRunLevel(r);
                    if (lastRunLevel == level && level == nextLevel)
                      {
                        // Merge runs together.
                        if (lastRunStart + start == nextEl.getStartOffset())
                          removeTo = nextIndex - 1;
                        else
                          {
                            newEls.add(new BidiElement(bidiRoot, start + lastRunStart,
                                                       nextEl.getEndOffset(), level));
                            removeTo = nextIndex;
                          }
                      }
                    else if (lastRunLevel == level)
                      {
                        // Merge current and last run.
                        int endOffs = offs + bidi.getRunLimit(r);
                        newEls.add(new BidiElement(bidiRoot, start + lastRunStart,
                                                   start + endOffs, level));
                        if (start + endOffs == nextEl.getStartOffset())
                          removeTo = nextIndex - 1;
                        else
                          {
                            newEls.add(new BidiElement(bidiRoot, start + endOffs,
                                                       nextEl.getEndOffset(),
                                                       nextLevel));
                            removeTo = nextIndex;
                          }
                      }
                    else if (level == nextLevel)
                      {
                        // Merge current and next run.
                        newEls.add(new BidiElement(bidiRoot, start + lastRunStart,
                                                   start + lastRunEnd,
                                                   lastRunLevel));
                        newEls.add(new BidiElement(bidiRoot, start + lastRunEnd,
                                                   nextEl.getEndOffset(), level));
                        removeTo = nextIndex;
                      }
                    else
                      {
                        // Split next element.
                        int endOffs = offs + bidi.getRunLimit(r);
                        newEls.add(new BidiElement(bidiRoot, start + lastRunStart,
                                                   start + lastRunEnd,
                                                   lastRunLevel));
                        newEls.add(new BidiElement(bidiRoot, start + lastRunEnd,
                                                   start + endOffs, level));
                        newEls.add(new BidiElement(bidiRoot, start + endOffs,
                                                   nextEl.getEndOffset(),
                                                   nextLevel));
                        removeTo = nextIndex;
                      }
                  }
                else
                  {
                    removeTo = bidiRoot.getElementIndex(end);
                    int level = bidi.getRunLevel(r);
                    int runEnd = offs + bidi.getRunLimit(r);

                    if (level == lastRunLevel)
                      {
                        // Merge with previous.
                        lastRunEnd = offs + runEnd;
                        newEls.add(new BidiElement(bidiRoot,
                                                  start + lastRunStart,
                                                  start + runEnd, level));
                      }
                    else
                      {
                        // Create element for last run and current run.
                        newEls.add(new BidiElement(bidiRoot, start + lastRunStart,
                                                   start + lastRunEnd,
                                                   lastRunLevel));
                        newEls.add(new BidiElement(bidiRoot,
                                                   start + lastRunEnd,
                                                   start + runEnd,
                                                   level));
                       }
                  }
              }
            else
              {
                int level = bidi.getRunLevel(r);
                int runEnd = bidi.getRunLimit(r);

                if (level == lastRunLevel)
                  {
                    // Merge with previous.
                    lastRunEnd = offs + runEnd;
                  }
                else
                  {
                    // Create element for last run and update values for
                    // current run.
                    newEls.add(new BidiElement(bidiRoot, start + lastRunStart,
                                               start + lastRunEnd,
                                               lastRunLevel));
                    lastRunStart = lastRunEnd;
                    lastRunEnd = offs + runEnd;
                    lastRunLevel = level;
                  }
              }
          }
        offs += bidi.getLength();
      }

    // Determine the bidi elements which are to be removed.
    int numRemoved = 0;
    if (bidiRoot.getElementCount() > 0)
      numRemoved = removeTo - removeFrom + 1;
    Element[] removed = new Element[numRemoved];
    for (int i = 0; i < numRemoved; i++)
      removed[i] = bidiRoot.getElement(removeFrom + i);

    Element[] added = new Element[newEls.size()];
    added = (Element[]) newEls.toArray(added);

    // Update the event.
    ElementEdit edit = new ElementEdit(bidiRoot, removeFrom, removed, added);
    ev.addEdit(edit);

    // Update the structure.
    bidiRoot.replace(removeFrom, numRemoved, added);
  }

  /**
   * Determines the Bidi objects for the paragraphs in the specified range.
   *
   * @param start the start of the range
   * @param end the end of the range
   *
   * @return the Bidi analysers for the paragraphs in the range
   */
  private Bidi[] getBidis(int start, int end)
  {
    // Determine the default run direction from the document property.
    Boolean defaultDir = null;
    Object o = getProperty(TextAttribute.RUN_DIRECTION);
    if (o instanceof Boolean)
      defaultDir = (Boolean) o;

    // Scan paragraphs and add their level arrays to the overall levels array.
    ArrayList bidis = new ArrayList();
    Segment s = new Segment();
    for (int i = start; i < end;)
      {
        Element par = getParagraphElement(i);
        int pStart = par.getStartOffset();
        int pEnd = par.getEndOffset();

        // Determine the default run direction of the paragraph.
        Boolean dir = defaultDir;
        o = par.getAttributes().getAttribute(TextAttribute.RUN_DIRECTION);
        if (o instanceof Boolean)
          dir = (Boolean) o;

        // Bidi over the paragraph.
        try
          {
            getText(pStart, pEnd - pStart, s);
          }
        catch (BadLocationException ex)
          {
            assert false : "Must not happen";
          }
        int flag = Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT;
        if (dir != null)
          {
            if (TextAttribute.RUN_DIRECTION_LTR.equals(dir))
              flag = Bidi.DIRECTION_LEFT_TO_RIGHT;
            else
              flag = Bidi.DIRECTION_RIGHT_TO_LEFT;
          }
        Bidi bidi = new Bidi(s.array, s.offset, null, 0, s.count, flag);
        bidis.add(bidi);
        i = pEnd;
      }
    Bidi[] ret = new Bidi[bidis.size()];
    ret = (Bidi[]) bidis.toArray(ret);
    return ret;
  }

  /**
   * Blocks until a read lock can be obtained.  Must block if there is
   * currently a writer modifying the <code>Document</code>.
   */
  public final synchronized void readLock()
  {
    try
      {
        while (currentWriter != null)
          {
            if (currentWriter == Thread.currentThread())
              return;
            wait();
          }
        numReaders++;
      }
    catch (InterruptedException ex)
      {
        throw new Error("Interrupted during grab read lock");
      }
  }

  /**
   * Releases the read lock. If this was the only reader on this
   * <code>Document</code>, writing may begin now.
   */
  public final synchronized void readUnlock()
  {
    // Note we could have a problem here if readUnlock was called without a
    // prior call to readLock but the specs simply warn users to ensure that
    // balance by using a finally block:
    // readLock()
    // try
    // {
    //   doSomethingHere
    // }
    // finally
    // {
    //   readUnlock();
    // }

    // All that the JDK seems to check for is that you don't call unlock
    // more times than you've previously called lock, but it doesn't make
    // sure that the threads calling unlock were the same ones that called lock

    // If the current thread holds the write lock, and attempted to also obtain
    // a readLock, then numReaders hasn't been incremented and we don't need
    // to unlock it here.
    if (currentWriter == Thread.currentThread())
      return;

    // FIXME: the reference implementation throws a
    // javax.swing.text.StateInvariantError here
    if (numReaders <= 0)
      throw new IllegalStateException("document lock failure");

    // If currentWriter is not null, the application code probably had a
    // writeLock and then tried to obtain a readLock, in which case
    // numReaders wasn't incremented
    numReaders--;
    notify();
  }

  /**
   * Removes a piece of content from this <code>Document</code>.
   *
   * <p>If a {@link DocumentFilter} is installed in this document, the
   * corresponding method of the filter object is called. The
   * <code>DocumentFilter</code> is called even if <code>length</code>
   * is zero. This is different from {@link #replace}.</p>
   *
   * <p>Note: When <code>length</code> is zero or below the call is not
   * forwarded to the underlying {@link AbstractDocument.Content} instance
   * of this document and no exception is thrown.</p>
   *
   * @param offset the start offset of the fragment to be removed
   * @param length the length of the fragment to be removed
   *
   * @throws BadLocationException if <code>offset</code> or
   *         <code>offset + length</code> or invalid locations within this
   *         document
   */
  public void remove(int offset, int length) throws BadLocationException
  {
    writeLock();
    try
      {
        DocumentFilter f = getDocumentFilter();
        if (f == null)
          removeImpl(offset, length);
        else
          f.remove(getBypass(), offset, length);
      }
    finally
      {
        writeUnlock();
      }
  }

  void removeImpl(int offset, int length) throws BadLocationException
  {
    // The RI silently ignores all requests that have a negative length.
    // Don't ask my why, but that's how it is.
    if (length > 0)
      {
        if (offset < 0 || offset > getLength())
          throw new BadLocationException("Invalid remove position", offset);

        if (offset + length > getLength())
          throw new BadLocationException("Invalid remove length", offset);

        DefaultDocumentEvent event =
          new DefaultDocumentEvent(offset, length,
                                   DocumentEvent.EventType.REMOVE);

        // The order of the operations below is critical!
        removeUpdate(event);
        UndoableEdit temp = content.remove(offset, length);

        postRemoveUpdate(event);
        fireRemoveUpdate(event);
      }
  }

  /**
   * Replaces a piece of content in this <code>Document</code> with
   * another piece of content.
   *
   * <p>If a {@link DocumentFilter} is installed in this document, the
   * corresponding method of the filter object is called.</p>
   *
   * <p>The method has no effect if <code>length</code> is zero (and
   * only zero) and, at the same time, <code>text</code> is
   * <code>null</code> or has zero length.</p>
   *
   * @param offset the start offset of the fragment to be removed
   * @param length the length of the fragment to be removed
   * @param text the text to replace the content with
   * @param attributes the text attributes to assign to the new content
   *
   * @throws BadLocationException if <code>offset</code> or
   *         <code>offset + length</code> or invalid locations within this
   *         document
   *
   * @since 1.4
   */
  public void replace(int offset, int length, String text,
                      AttributeSet attributes)
    throws BadLocationException
  {
    // Bail out if we have a bogus replacement (Behavior observed in RI).
    if (length == 0
        && (text == null || text.length() == 0))
      return;

    writeLock();
    try
      {
        if (documentFilter == null)
          {
            // It is important to call the methods which again do the checks
            // of the arguments and the DocumentFilter because subclasses may
            // have overridden these methods and provide crucial behavior
            // which would be skipped if we call the non-checking variants.
            // An example for this is PlainDocument where insertString can
            // provide a filtering of newlines.
            remove(offset, length);
            insertString(offset, text, attributes);
          }
        else
          documentFilter.replace(getBypass(), offset, length, text, attributes);
      }
    finally
      {
        writeUnlock();
      }
  }

  void replaceImpl(int offset, int length, String text,
                      AttributeSet attributes)
    throws BadLocationException
  {
    removeImpl(offset, length);
    insertStringImpl(offset, text, attributes);
  }

  /**
   * Adds a <code>DocumentListener</code> object to this document.
   *
   * @param listener the listener to add
   */
  public void addDocumentListener(DocumentListener listener)
  {
    listenerList.add(DocumentListener.class, listener);
  }

  /**
   * Removes a <code>DocumentListener</code> object from this document.
   *
   * @param listener the listener to remove
   */
  public void removeDocumentListener(DocumentListener listener)
  {
    listenerList.remove(DocumentListener.class, listener);
  }

  /**
   * Returns all registered <code>DocumentListener</code>s.
   *
   * @return all registered <code>DocumentListener</code>s
   */
  public DocumentListener[] getDocumentListeners()
  {
    return (DocumentListener[]) getListeners(DocumentListener.class);
  }

  /**
   * Adds an {@link UndoableEditListener} to this <code>Document</code>.
   *
   * @param listener the listener to add
   */
  public void addUndoableEditListener(UndoableEditListener listener)
  {
    listenerList.add(UndoableEditListener.class, listener);
  }

  /**
   * Removes an {@link UndoableEditListener} from this <code>Document</code>.
   *
   * @param listener the listener to remove
   */
  public void removeUndoableEditListener(UndoableEditListener listener)
  {
    listenerList.remove(UndoableEditListener.class, listener);
  }

  /**
   * Returns all registered {@link UndoableEditListener}s.
   *
   * @return all registered {@link UndoableEditListener}s
   */
  public UndoableEditListener[] getUndoableEditListeners()
  {
    return (UndoableEditListener[]) getListeners(UndoableEditListener.class);
  }

  /**
   * Called before some content gets removed from this <code>Document</code>.
   * The default implementation does nothing but may be overridden by
   * subclasses to modify the <code>Document</code> structure in response
   * to a remove request. The method is executed within a write lock.
   *
   * @param chng the <code>DefaultDocumentEvent</code> describing the change
   */
  protected void removeUpdate(DefaultDocumentEvent chng)
  {
    // Do nothing here. Subclasses may wish to override this.
  }

  /**
   * Called to render this <code>Document</code> visually. It obtains a read
   * lock, ensuring that no changes will be made to the <code>document</code>
   * during the rendering process. It then calls the {@link Runnable#run()}
   * method on <code>runnable</code>. This method <em>must not</em> attempt
   * to modifiy the <code>Document</code>, since a deadlock will occur if it
   * tries to obtain a write lock. When the {@link Runnable#run()} method
   * completes (either naturally or by throwing an exception), the read lock
   * is released. Note that there is nothing in this method related to
   * the actual rendering. It could be used to execute arbitrary code within
   * a read lock.
   *
   * @param runnable the {@link Runnable} to execute
   */
  public void render(Runnable runnable)
  {
    readLock();
    try
    {
      runnable.run();
    }
    finally
    {
      readUnlock();
    }
  }

  /**
   * Sets the asynchronous loading priority for this <code>Document</code>.
   * A value of <code>-1</code> indicates that this <code>Document</code>
   * should be loaded synchronously.
   *
   * @param p the asynchronous loading priority to set
   */
  public void setAsynchronousLoadPriority(int p)
  {
    Integer val = p >= 0 ? new Integer(p) : null;
    putProperty(AsyncLoadPriority, val);
  }

  /**
   * Sets the properties of this <code>Document</code>.
   *
   * @param p the document properties to set
   */
  public void setDocumentProperties(Dictionary<Object, Object> p)
  {
    // FIXME: make me thread-safe
    properties = p;
  }

  /**
   * Blocks until a write lock can be obtained.  Must wait if there are
   * readers currently reading or another thread is currently writing.
   */
  protected synchronized final void writeLock()
  {
    try
      {
        while (numReaders > 0 || currentWriter != null)
          {
            if (Thread.currentThread() == currentWriter)
              {
                if (notifyListeners)
                  throw new IllegalStateException("Mutation during notify");
                numWriters++;
                return;
              }
            wait();
          }
        currentWriter = Thread.currentThread();
        numWriters = 1;
      }
    catch (InterruptedException ex)
      {
        throw new Error("Interupted during grab write lock");
      }
  }

  /**
   * Releases the write lock. This allows waiting readers or writers to
   * obtain the lock.
   */
  protected final synchronized void writeUnlock()
  {
    if (--numWriters <= 0)
      {
        numWriters = 0;
        currentWriter = null;
        notifyAll();
      }
  }

  /**
   * Returns the currently installed {@link DocumentFilter} for this
   * <code>Document</code>.
   *
   * @return the currently installed {@link DocumentFilter} for this
   *         <code>Document</code>
   *
   * @since 1.4
   */
  public DocumentFilter getDocumentFilter()
  {
    return documentFilter;
  }

  /**
   * Sets the {@link DocumentFilter} for this <code>Document</code>.
   *
   * @param filter the <code>DocumentFilter</code> to set
   *
   * @since 1.4
   */
  public void setDocumentFilter(DocumentFilter filter)
  {
    this.documentFilter = filter;
  }

  /**
   * Dumps diagnostic information to the specified <code>PrintStream</code>.
   *
   * @param out the stream to write the diagnostic information to
   */
  public void dump(PrintStream out)
  {
    ((AbstractElement) getDefaultRootElement()).dump(out, 0);
    ((AbstractElement) getBidiRootElement()).dump(out, 0);
  }

  /**
   * Defines a set of methods for managing text attributes for one or more
   * <code>Document</code>s.
   *
   * Replicating {@link AttributeSet}s throughout a <code>Document</code> can
   * be very expensive. Implementations of this interface are intended to
   * provide intelligent management of <code>AttributeSet</code>s, eliminating
   * costly duplication.
   *
   * @see StyleContext
   */
  public interface AttributeContext
  {
    /**
     * Returns an {@link AttributeSet} that contains the attributes
     * of <code>old</code> plus the new attribute specified by
     * <code>name</code> and <code>value</code>.
     *
     * @param old the attribute set to be merged with the new attribute
     * @param name the name of the attribute to be added
     * @param value the value of the attribute to be added
     *
     * @return the old attributes plus the new attribute
     */
    AttributeSet addAttribute(AttributeSet old, Object name, Object value);

    /**
     * Returns an {@link AttributeSet} that contains the attributes
     * of <code>old</code> plus the new attributes in <code>attributes</code>.
     *
     * @param old the set of attributes where to add the new attributes
     * @param attributes the attributes to be added
     *
     * @return an {@link AttributeSet} that contains the attributes
     *         of <code>old</code> plus the new attributes in
     *         <code>attributes</code>
     */
    AttributeSet addAttributes(AttributeSet old, AttributeSet attributes);

    /**
     * Returns an empty {@link AttributeSet}.
     *
     * @return  an empty {@link AttributeSet}
     */
    AttributeSet getEmptySet();

    /**
     * Called to indicate that the attributes in <code>attributes</code> are
     * no longer used.
     *
     * @param attributes the attributes are no longer used
     */
    void reclaim(AttributeSet attributes);

    /**
     * Returns a {@link AttributeSet} that has the attribute with the specified
     * <code>name</code> removed from <code>old</code>.
     *
     * @param old the attribute set from which an attribute is removed
     * @param name the name of the attribute to be removed
     *
     * @return the attributes of <code>old</code> minus the attribute
     *         specified by <code>name</code>
     */
    AttributeSet removeAttribute(AttributeSet old, Object name);

    /**
     * Removes all attributes in <code>attributes</code> from <code>old</code>
     * and returns the resulting <code>AttributeSet</code>.
     *
     * @param old the set of attributes from which to remove attributes
     * @param attributes the attributes to be removed from <code>old</code>
     *
     * @return the attributes of <code>old</code> minus the attributes in
     *         <code>attributes</code>
     */
    AttributeSet removeAttributes(AttributeSet old, AttributeSet attributes);

    /**
     * Removes all attributes specified by <code>names</code> from
     * <code>old</code> and returns the resulting <code>AttributeSet</code>.
     *
     * @param old the set of attributes from which to remove attributes
     * @param names the names of the attributes to be removed from
     *        <code>old</code>
     *
     * @return the attributes of <code>old</code> minus the attributes in
     *         <code>attributes</code>
     */
    AttributeSet removeAttributes(AttributeSet old, Enumeration<?> names);
  }

  /**
   * A sequence of data that can be edited. This is were the actual content
   * in <code>AbstractDocument</code>'s is stored.
   */
  public interface Content
  {
    /**
     * Creates a {@link Position} that keeps track of the location at
     * <code>offset</code>.
     *
     * @return a {@link Position} that keeps track of the location at
     *         <code>offset</code>.
     *
     * @throw BadLocationException if <code>offset</code> is not a valid
     *        location in this <code>Content</code> model
     */
    Position createPosition(int offset) throws BadLocationException;

    /**
     * Returns the length of the content.
     *
     * @return the length of the content
     */
    int length();

    /**
     * Inserts a string into the content model.
     *
     * @param where the offset at which to insert the string
     * @param str the string to be inserted
     *
     * @return an <code>UndoableEdit</code> or <code>null</code> if undo is
     *         not supported by this <code>Content</code> model
     *
     * @throws BadLocationException if <code>where</code> is not a valid
     *         location in this <code>Content</code> model
     */
    UndoableEdit insertString(int where, String str)
      throws BadLocationException;

    /**
     * Removes a piece of content from the content model.
     *
     * @param where the offset at which to remove content
     * @param nitems the number of characters to be removed
     *
     * @return an <code>UndoableEdit</code> or <code>null</code> if undo is
     *         not supported by this <code>Content</code> model
     *
     * @throws BadLocationException if <code>where</code> is not a valid
     *         location in this <code>Content</code> model
     */
    UndoableEdit remove(int where, int nitems) throws BadLocationException;

    /**
     * Returns a piece of content.
     *
     * @param where the start offset of the requested fragment
     * @param len the length of the requested fragment
     *
     * @return the requested fragment
     * @throws BadLocationException if <code>offset</code> or
     *         <code>offset + len</code>is not a valid
     *         location in this <code>Content</code> model
     */
    String getString(int where, int len) throws BadLocationException;

    /**
     * Fetches a piece of content and stores it in <code>txt</code>.
     *
     * @param where the start offset of the requested fragment
     * @param len the length of the requested fragment
     * @param txt the <code>Segment</code> where to fragment is stored into
     *
     * @throws BadLocationException if <code>offset</code> or
     *         <code>offset + len</code>is not a valid
     *         location in this <code>Content</code> model
     */
    void getChars(int where, int len, Segment txt) throws BadLocationException;
  }

  /**
   * An abstract base implementation of the {@link Element} interface.
   */
  public abstract class AbstractElement
    implements Element, MutableAttributeSet, TreeNode, Serializable
  {
    /** The serialization UID (compatible with JDK1.5). */
    private static final long serialVersionUID = 1712240033321461704L;

    /** The number of characters that this Element spans. */
    int count;

    /** The starting offset of this Element. */
    int offset;

    /** The attributes of this Element. */
    AttributeSet attributes;

    /** The parent element. */
    Element element_parent;

    /** The parent in the TreeNode interface. */
    TreeNode tree_parent;

    /** The children of this element. */
    Vector tree_children;

    /**
     * Creates a new instance of <code>AbstractElement</code> with a
     * specified parent <code>Element</code> and <code>AttributeSet</code>.
     *
     * @param p the parent of this <code>AbstractElement</code>
     * @param s the attributes to be assigned to this
     *        <code>AbstractElement</code>
     */
    public AbstractElement(Element p, AttributeSet s)
    {
      element_parent = p;
      AttributeContext ctx = getAttributeContext();
      attributes = ctx.getEmptySet();
      if (s != null)
        addAttributes(s);
    }

    /**
     * Returns the child nodes of this <code>Element</code> as an
     * <code>Enumeration</code> of {@link TreeNode}s.
     *
     * @return the child nodes of this <code>Element</code> as an
     *         <code>Enumeration</code> of {@link TreeNode}s
     */
    public abstract Enumeration children();

    /**
     * Returns <code>true</code> if this <code>AbstractElement</code>
     * allows children.
     *
     * @return <code>true</code> if this <code>AbstractElement</code>
     *         allows children
     */
    public abstract boolean getAllowsChildren();

    /**
     * Returns the child of this <code>AbstractElement</code> at
     * <code>index</code>.
     *
     * @param index the position in the child list of the child element to
     *        be returned
     *
     * @return the child of this <code>AbstractElement</code> at
     *         <code>index</code>
     */
    public TreeNode getChildAt(int index)
    {
      return (TreeNode) tree_children.get(index);
    }

    /**
     * Returns the number of children of this <code>AbstractElement</code>.
     *
     * @return the number of children of this <code>AbstractElement</code>
     */
    public int getChildCount()
    {
      return tree_children.size();
    }

    /**
     * Returns the index of a given child <code>TreeNode</code> or
     * <code>-1</code> if <code>node</code> is not a child of this
     * <code>AbstractElement</code>.
     *
     * @param node the node for which the index is requested
     *
     * @return the index of a given child <code>TreeNode</code> or
     *         <code>-1</code> if <code>node</code> is not a child of this
     *         <code>AbstractElement</code>
     */
    public int getIndex(TreeNode node)
    {
      return tree_children.indexOf(node);
    }

    /**
     * Returns the parent <code>TreeNode</code> of this
     * <code>AbstractElement</code> or <code>null</code> if this element
     * has no parent.
     *
     * @return the parent <code>TreeNode</code> of this
     *         <code>AbstractElement</code> or <code>null</code> if this
     *         element has no parent
     */
    public TreeNode getParent()
    {
      return tree_parent;
    }

    /**
     * Returns <code>true</code> if this <code>AbstractElement</code> is a
     * leaf element, <code>false</code> otherwise.
     *
     * @return <code>true</code> if this <code>AbstractElement</code> is a
     *         leaf element, <code>false</code> otherwise
     */
    public abstract boolean isLeaf();

    /**
     * Adds an attribute to this element.
     *
     * @param name the name of the attribute to be added
     * @param value the value of the attribute to be added
     */
    public void addAttribute(Object name, Object value)
    {
      attributes = getAttributeContext().addAttribute(attributes, name, value);
    }

    /**
     * Adds a set of attributes to this element.
     *
     * @param attrs the attributes to be added to this element
     */
    public void addAttributes(AttributeSet attrs)
    {
      attributes = getAttributeContext().addAttributes(attributes, attrs);
    }

    /**
     * Removes an attribute from this element.
     *
     * @param name the name of the attribute to be removed
     */
    public void removeAttribute(Object name)
    {
      attributes = getAttributeContext().removeAttribute(attributes, name);
    }

    /**
     * Removes a set of attributes from this element.
     *
     * @param attrs the attributes to be removed
     */
    public void removeAttributes(AttributeSet attrs)
    {
      attributes = getAttributeContext().removeAttributes(attributes, attrs);
    }

    /**
     * Removes a set of attribute from this element.
     *
     * @param names the names of the attributes to be removed
     */
    public void removeAttributes(Enumeration<?> names)
    {
      attributes = getAttributeContext().removeAttributes(attributes, names);
    }

    /**
     * Sets the parent attribute set against which the element can resolve
     * attributes that are not defined in itself.
     *
     * @param parent the resolve parent to set
     */
    public void setResolveParent(AttributeSet parent)
    {
      attributes = getAttributeContext().addAttribute(attributes,
                                                      ResolveAttribute,
                                                      parent);
    }

    /**
     * Returns <code>true</code> if this element contains the specified
     * attribute.
     *
     * @param name the name of the attribute to check
     * @param value the value of the attribute to check
     *
     * @return <code>true</code> if this element contains the specified
     *         attribute
     */
    public boolean containsAttribute(Object name, Object value)
    {
      return attributes.containsAttribute(name, value);
    }

    /**
     * Returns <code>true</code> if this element contains all of the
     * specified attributes.
     *
     * @param attrs the attributes to check
     *
     * @return <code>true</code> if this element contains all of the
     *         specified attributes
     */
    public boolean containsAttributes(AttributeSet attrs)
    {
      return attributes.containsAttributes(attrs);
    }

    /**
     * Returns a copy of the attributes of this element.
     *
     * @return a copy of the attributes of this element
     */
    public AttributeSet copyAttributes()
    {
      return attributes.copyAttributes();
    }

    /**
     * Returns the attribute value with the specified key. If this attribute
     * is not defined in this element and this element has a resolving
     * parent, the search goes upward to the resolve parent chain.
     *
     * @param key the key of the requested attribute
     *
     * @return the attribute value for <code>key</code> of <code>null</code>
     *         if <code>key</code> is not found locally and cannot be resolved
     *         in this element's resolve parents
     */
    public Object getAttribute(Object key)
    {
      Object result = attributes.getAttribute(key);
      if (result == null)
        {
          AttributeSet resParent = getResolveParent();
          if (resParent != null)
            result = resParent.getAttribute(key);
        }
      return result;
    }

    /**
     * Returns the number of defined attributes in this element.
     *
     * @return the number of defined attributes in this element
     */
    public int getAttributeCount()
    {
      return attributes.getAttributeCount();
    }

    /**
     * Returns the names of the attributes of this element.
     *
     * @return the names of the attributes of this element
     */
    public Enumeration<?> getAttributeNames()
    {
      return attributes.getAttributeNames();
    }

    /**
     * Returns the resolve parent of this element.
     * This is taken from the AttributeSet, but if this is null,
     * this method instead returns the Element's parent's
     * AttributeSet
     *
     * @return the resolve parent of this element
     *
     * @see #setResolveParent(AttributeSet)
     */
    public AttributeSet getResolveParent()
    {
      return attributes.getResolveParent();
    }

    /**
     * Returns <code>true</code> if an attribute with the specified name
     * is defined in this element, <code>false</code> otherwise.
     *
     * @param attrName the name of the requested attributes
     *
     * @return <code>true</code> if an attribute with the specified name
     *         is defined in this element, <code>false</code> otherwise
     */
    public boolean isDefined(Object attrName)
    {
      return attributes.isDefined(attrName);
    }

    /**
     * Returns <code>true</code> if the specified <code>AttributeSet</code>
     * is equal to this element's <code>AttributeSet</code>, <code>false</code>
     * otherwise.
     *
     * @param attrs the attributes to compare this element to
     *
     * @return <code>true</code> if the specified <code>AttributeSet</code>
     *         is equal to this element's <code>AttributeSet</code>,
     *         <code>false</code> otherwise
     */
    public boolean isEqual(AttributeSet attrs)
    {
      return attributes.isEqual(attrs);
    }

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

    /**
     * Returns the {@link Document} to which this element belongs.
     *
     * @return the {@link Document} to which this element belongs
     */
    public Document getDocument()
    {
      return AbstractDocument.this;
    }

    /**
     * Returns the child element at the specified <code>index</code>.
     *
     * @param index the index of the requested child element
     *
     * @return the requested element
     */
    public abstract Element getElement(int index);

    /**
     * Returns the name of this element.
     *
     * @return the name of this element
     */
    public String getName()
    {
      return (String) attributes.getAttribute(ElementNameAttribute);
    }

    /**
     * Returns the parent element of this element.
     *
     * @return the parent element of this element
     */
    public Element getParentElement()
    {
      return element_parent;
    }

    /**
     * Returns the offset inside the document model that is after the last
     * character of this element.
     *
     * @return the offset inside the document model that is after the last
     *         character of this element
     */
    public abstract int getEndOffset();

    /**
     * Returns the number of child elements of this element.
     *
     * @return the number of child elements of this element
     */
    public abstract int getElementCount();

    /**
     * Returns the index of the child element that spans the specified
     * offset in the document model.
     *
     * @param offset the offset for which the responsible element is searched
     *
     * @return the index of the child element that spans the specified
     *         offset in the document model
     */
    public abstract int getElementIndex(int offset);

    /**
     * Returns the start offset if this element inside the document model.
     *
     * @return the start offset if this element inside the document model
     */
    public abstract int getStartOffset();

    /**
     * Prints diagnostic output to the specified stream.
     *
     * @param stream the stream to write to
     * @param indent the indentation level
     */
    public void dump(PrintStream stream, int indent)
    {
      CPStringBuilder b = new CPStringBuilder();
      for (int i = 0; i < indent; ++i)
        b.append(' ');
      b.append('<');
      b.append(getName());
      // Dump attributes if there are any.
      if (getAttributeCount() > 0)
        {
          b.append('\n');
          Enumeration attNames = getAttributeNames();
          while (attNames.hasMoreElements())
            {
              for (int i = 0; i < indent + 2; ++i)
                b.append(' ');
              Object attName = attNames.nextElement();
              b.append(attName);
              b.append('=');
              Object attribute = getAttribute(attName);
              b.append(attribute);
              b.append('\n');
            }
        }
      if (getAttributeCount() > 0)
        {
          for (int i = 0; i < indent; ++i)
            b.append(' ');
        }
      b.append(">\n");

      // Dump element content for leaf elements.
      if (isLeaf())
        {
          for (int i = 0; i < indent + 2; ++i)
            b.append(' ');
          int start = getStartOffset();
          int end = getEndOffset();
          b.append('[');
          b.append(start);
          b.append(',');
          b.append(end);
          b.append("][");
          try
            {
              b.append(getDocument().getText(start, end - start));
            }
          catch (BadLocationException ex)
            {
              AssertionError err = new AssertionError("BadLocationException "
                                                      + "must not be thrown "
                                                      + "here.");
              err.initCause(ex);
              throw err;
            }
          b.append("]\n");
        }
      stream.print(b.toString());

      // Dump child elements if any.
      int count = getElementCount();
      for (int i = 0; i < count; ++i)
        {
          Element el = getElement(i);
          if (el instanceof AbstractElement)
            ((AbstractElement) el).dump(stream, indent + 2);
        }
    }
  }

  /**
   * An implementation of {@link Element} to represent composite
   * <code>Element</code>s that contain other <code>Element</code>s.
   */
  public class BranchElement extends AbstractElement
  {
    /** The serialization UID (compatible with JDK1.5). */
    private static final long serialVersionUID = -6037216547466333183L;

    /**
     * The child elements of this BranchElement.
     */
    private Element[] children;

    /**
     * The number of children in the branch element.
     */
    private int numChildren;

    /**
     * The last found index in getElementIndex(). Used for faster searching.
     */
    private int lastIndex;

    /**
     * Creates a new <code>BranchElement</code> with the specified
     * parent and attributes.
     *
     * @param parent the parent element of this <code>BranchElement</code>
     * @param attributes the attributes to set on this
     *        <code>BranchElement</code>
     */
    public BranchElement(Element parent, AttributeSet attributes)
    {
      super(parent, attributes);
      children = new Element[1];
      numChildren = 0;
      lastIndex = -1;
    }

    /**
     * Returns the children of this <code>BranchElement</code>.
     *
     * @return the children of this <code>BranchElement</code>
     */
    public Enumeration children()
    {
      if (numChildren == 0)
        return null;

      Vector tmp = new Vector();

      for (int index = 0; index < numChildren; ++index)
        tmp.add(children[index]);

      return tmp.elements();
    }

    /**
     * Returns <code>true</code> since <code>BranchElements</code> allow
     * child elements.
     *
     * @return <code>true</code> since <code>BranchElements</code> allow
     *         child elements
     */
    public boolean getAllowsChildren()
    {
      return true;
    }

    /**
     * Returns the child element at the specified <code>index</code>.
     *
     * @param index the index of the requested child element
     *
     * @return the requested element
     */
    public Element getElement(int index)
    {
      if (index < 0 || index >= numChildren)
        return null;

      return children[index];
    }

    /**
     * Returns the number of child elements of this element.
     *
     * @return the number of child elements of this element
     */
    public int getElementCount()
    {
      return numChildren;
    }

    /**
     * Returns the index of the child element that spans the specified
     * offset in the document model.
     *
     * @param offset the offset for which the responsible element is searched
     *
     * @return the index of the child element that spans the specified
     *         offset in the document model
     */
    public int getElementIndex(int offset)
    {
      // Implemented using an improved linear search.
      // This makes use of the fact that searches are not random but often
      // close to the previous search. So we try to start the binary
      // search at the last found index.

      int i0 = 0; // The lower bounds.
      int i1 = numChildren - 1; // The upper bounds.
      int index = -1; // The found index.

      int p0 = getStartOffset();
      int p1; // Start and end offset local variables.

      if (numChildren == 0)
        index = 0;
      else if (offset >= getEndOffset())
        index = numChildren - 1;
      else
        {
          // Try lastIndex.
          if (lastIndex >= i0 && lastIndex <= i1)
            {
              Element last = getElement(lastIndex);
              p0 = last.getStartOffset();
              p1 = last.getEndOffset();
              if (offset >= p0 && offset < p1)
                index = lastIndex;
              else
                {
                  // Narrow the search bounds using the lastIndex, even
                  // if it hasn't been a hit.
                  if (offset < p0)
                    i1 = lastIndex;
                  else
                    i0 = lastIndex;
                }
            }
          // The actual search.
          int i = 0;
          while (i0 <= i1 && index == -1)
            {
              i = i0 + (i1 - i0) / 2;
              Element el = getElement(i);
              p0 = el.getStartOffset();
              p1 = el.getEndOffset();
              if (offset >= p0 && offset < p1)
                {
                  // Found it!
                  index = i;
                }
              else if (offset < p0)
                i1 = i - 1;
              else
                i0 = i + 1;
            }

          if (index == -1)
            {
              // Didn't find it. Return the boundary index.
              if (offset < p0)
                index = i;
              else
                index = i + 1;
            }

          lastIndex = index;
        }
      return index;
    }

    /**
     * Returns the offset inside the document model that is after the last
     * character of this element.
     * This is the end offset of the last child element. If this element
     * has no children, this method throws a <code>NullPointerException</code>.
     *
     * @return the offset inside the document model that is after the last
     *         character of this element
     *
     * @throws NullPointerException if this branch element has no children
     */
    public int getEndOffset()
    {
      // This might accss one cached element or trigger an NPE for
      // numChildren == 0. This is checked by a Mauve test.
      Element child = numChildren > 0 ? children[numChildren - 1]
                                      : children[0];
      return child.getEndOffset();
    }

    /**
     * Returns the name of this element. This is {@link #ParagraphElementName}
     * in this case.
     *
     * @return the name of this element
     */
    public String getName()
    {
      return ParagraphElementName;
    }

    /**
     * Returns the start offset of this element inside the document model.
     * This is the start offset of the first child element. If this element
     * has no children, this method throws a <code>NullPointerException</code>.
     *
     * @return the start offset of this element inside the document model
     *
     * @throws NullPointerException if this branch element has no children and
     *         no startOffset value has been cached
     */
    public int getStartOffset()
    {
      // Do not explicitly throw an NPE here. If the first element is null
      // then the NPE gets thrown anyway. If it isn't, then it either
      // holds a real value (for numChildren > 0) or a cached value
      // (for numChildren == 0) as we don't fully remove elements in replace()
      // when removing single elements.
      // This is checked by a Mauve test.
      return children[0].getStartOffset();
    }

    /**
     * Returns <code>false</code> since <code>BranchElement</code> are no
     * leafes.
     *
     * @return <code>false</code> since <code>BranchElement</code> are no
     *         leafes
     */
    public boolean isLeaf()
    {
      return false;
    }

    /**
     * Returns the <code>Element</code> at the specified <code>Document</code>
     * offset.
     *
     * @return the <code>Element</code> at the specified <code>Document</code>
     *         offset
     *
     * @see #getElementIndex(int)
     */
    public Element positionToElement(int position)
    {
      // XXX: There is surely a better algorithm
      // as beginning from first element each time.
      for (int index = 0; index < numChildren; ++index)
        {
          Element elem = children[index];

          if ((elem.getStartOffset() <= position)
              && (position < elem.getEndOffset()))
            return elem;
        }

      return null;
    }

    /**
     * Replaces a set of child elements with a new set of child elemens.
     *
     * @param offset the start index of the elements to be removed
     * @param length the number of elements to be removed
     * @param elements the new elements to be inserted
     */
    public void replace(int offset, int length, Element[] elements)
    {
      int delta = elements.length - length;
      int copyFrom = offset + length; // From where to copy.
      int copyTo = copyFrom + delta;    // Where to copy to.
      int numMove = numChildren - copyFrom; // How many elements are moved.
      if (numChildren + delta > children.length)
        {
          // Gotta grow the array.
          int newSize = Math.max(2 * children.length, numChildren + delta);
          Element[] target = new Element[newSize];
          System.arraycopy(children, 0, target, 0, offset);
          System.arraycopy(elements, 0, target, offset, elements.length);
          System.arraycopy(children, copyFrom, target, copyTo, numMove);
          children = target;
        }
      else
        {
          System.arraycopy(children, copyFrom, children, copyTo, numMove);
          System.arraycopy(elements, 0, children, offset, elements.length);
        }
      numChildren += delta;
    }

    /**
     * Returns a string representation of this element.
     *
     * @return a string representation of this element
     */
    public String toString()
    {
      return ("BranchElement(" + getName() + ") "
              + getStartOffset() + "," + getEndOffset() + "\n");
    }
  }

  /**
   * Stores the changes when a <code>Document</code> is beeing modified.
   */
  public class DefaultDocumentEvent extends CompoundEdit
    implements DocumentEvent
  {
    /** The serialization UID (compatible with JDK1.5). */
    private static final long serialVersionUID = 5230037221564563284L;

    /**
     * The threshold that indicates when we switch to using a Hashtable.
     */
    private static final int THRESHOLD = 10;

    /** The starting offset of the change. */
    private int offset;

    /** The length of the change. */
    private int length;

    /** The type of change. */
    private DocumentEvent.EventType type;

    /**
     * Maps <code>Element</code> to their change records. This is only
     * used when the changes array gets too big. We can use an
     * (unsync'ed) HashMap here, since changes to this are (should) always
     * be performed inside a write lock.
     */
    private HashMap changes;

    /**
     * Indicates if this event has been modified or not. This is used to
     * determine if this event is thrown.
     */
    private boolean modified;

    /**
     * Creates a new <code>DefaultDocumentEvent</code>.
     *
     * @param offset the starting offset of the change
     * @param length the length of the change
     * @param type the type of change
     */
    public DefaultDocumentEvent(int offset, int length,
                                DocumentEvent.EventType type)
    {
      this.offset = offset;
      this.length = length;
      this.type = type;
      modified = false;
    }

    /**
     * Adds an UndoableEdit to this <code>DocumentEvent</code>. If this
     * edit is an instance of {@link ElementEdit}, then this record can
     * later be fetched by calling {@link #getChange}.
     *
     * @param edit the undoable edit to add
     */
    public boolean addEdit(UndoableEdit edit)
    {
      // Start using Hashtable when we pass a certain threshold. This
      // gives a good memory/performance compromise.
      if (changes == null && edits.size() > THRESHOLD)
        {
          changes = new HashMap();
          int count = edits.size();
          for (int i = 0; i < count; i++)
            {
              Object o = edits.elementAt(i);
              if (o instanceof ElementChange)
                {
                  ElementChange ec = (ElementChange) o;
                  changes.put(ec.getElement(), ec);
                }
            }
        }

      if (changes != null && edit instanceof ElementChange)
        {
          ElementChange elEdit = (ElementChange) edit;
          changes.put(elEdit.getElement(), elEdit);
        }
      return super.addEdit(edit);
    }

    /**
     * Returns the document that has been modified.
     *
     * @return the document that has been modified
     */
    public Document getDocument()
    {
      return AbstractDocument.this;
    }

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

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

    /**
     * Returns the type of the modification.
     *
     * @return the type of the modification
     */
    public DocumentEvent.EventType getType()
    {
      return type;
    }

    /**
     * Returns the changes for an element.
     *
     * @param elem the element for which the changes are requested
     *
     * @return the changes for <code>elem</code> or <code>null</code> if
     *         <code>elem</code> has not been changed
     */
    public ElementChange getChange(Element elem)
    {
      ElementChange change = null;
      if (changes != null)
        {
          change = (ElementChange) changes.get(elem);
        }
      else
        {
          int count = edits.size();
          for (int i = 0; i < count && change == null; i++)
            {
              Object o = edits.get(i);
              if (o instanceof ElementChange)
                {
                  ElementChange ec = (ElementChange) o;
                  if (elem.equals(ec.getElement()))
                    change = ec;
                }
            }
        }
      return change;
    }

    /**
     * Returns a String description of the change event.  This returns the
     * toString method of the Vector of edits.
     */
    public String toString()
    {
      return edits.toString();
    }
  }

  /**
   * An implementation of {@link DocumentEvent.ElementChange} to be added
   * to {@link DefaultDocumentEvent}s.
   */
  public static class ElementEdit extends AbstractUndoableEdit
    implements DocumentEvent.ElementChange
  {
    /** The serial version UID of ElementEdit. */
    private static final long serialVersionUID = -1216620962142928304L;

    /**
     * The changed element.
     */
    private Element elem;

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

    /**
     * The removed elements.
     */
    private Element[] removed;

    /**
     * The added elements.
     */
    private Element[] added;

    /**
     * Creates a new <code>ElementEdit</code>.
     *
     * @param elem the changed element
     * @param index the index of the change
     * @param removed the removed elements
     * @param added the added elements
     */
    public ElementEdit(Element elem, int index,
                       Element[] removed, Element[] added)
    {
      this.elem = elem;
      this.index = index;
      this.removed = removed;
      this.added = added;
    }

    /**
     * Returns the added elements.
     *
     * @return the added elements
     */
    public Element[] getChildrenAdded()
    {
      return added;
    }

    /**
     * Returns the removed elements.
     *
     * @return the removed elements
     */
    public Element[] getChildrenRemoved()
    {
      return removed;
    }

    /**
     * Returns the changed element.
     *
     * @return the changed element
     */
    public Element getElement()
    {
      return elem;
    }

    /**
     * Returns the index of the change.
     *
     * @return the index of the change
     */
    public int getIndex()
    {
      return index;
    }
  }

  /**
   * An implementation of {@link Element} that represents a leaf in the
   * document structure. This is used to actually store content.
   */
  public class LeafElement extends AbstractElement
  {
    /** The serialization UID (compatible with JDK1.5). */
    private static final long serialVersionUID = -8906306331347768017L;

    /**
     * Manages the start offset of this element.
     */
    private Position startPos;

    /**
     * Manages the end offset of this element.
     */
    private Position endPos;

    /**
     * Creates a new <code>LeafElement</code>.
     *
     * @param parent the parent of this <code>LeafElement</code>
     * @param attributes the attributes to be set
     * @param start the start index of this element inside the document model
     * @param end the end index of this element inside the document model
     */
    public LeafElement(Element parent, AttributeSet attributes, int start,
                       int end)
    {
      super(parent, attributes);
      try
        {
          startPos = createPosition(start);
          endPos = createPosition(end);
        }
      catch (BadLocationException ex)
        {
          AssertionError as;
          as = new AssertionError("BadLocationException thrown "
                                  + "here. start=" + start
                                  + ", end=" + end
                                  + ", length=" + getLength());
          as.initCause(ex);
          throw as;
        }
    }

    /**
     * Returns <code>null</code> since <code>LeafElement</code>s cannot have
     * children.
     *
     * @return <code>null</code> since <code>LeafElement</code>s cannot have
     *         children
     */
    public Enumeration children()
    {
      return null;
    }

    /**
     * Returns <code>false</code> since <code>LeafElement</code>s cannot have
     * children.
     *
     * @return <code>false</code> since <code>LeafElement</code>s cannot have
     *         children
     */
    public boolean getAllowsChildren()
    {
      return false;
    }

    /**
     * Returns <code>null</code> since <code>LeafElement</code>s cannot have
     * children.
     *
     * @return <code>null</code> since <code>LeafElement</code>s cannot have
     *         children
     */
    public Element getElement(int index)
    {
      return null;
    }

    /**
     * Returns <code>0</code> since <code>LeafElement</code>s cannot have
     * children.
     *
     * @return <code>0</code> since <code>LeafElement</code>s cannot have
     *         children
     */
    public int getElementCount()
    {
      return 0;
    }

    /**
     * Returns <code>-1</code> since <code>LeafElement</code>s cannot have
     * children.
     *
     * @return <code>-1</code> since <code>LeafElement</code>s cannot have
     *         children
     */
    public int getElementIndex(int offset)
    {
      return -1;
    }

    /**
     * Returns the end offset of this <code>Element</code> inside the
     * document.
     *
     * @return the end offset of this <code>Element</code> inside the
     *         document
     */
    public int getEndOffset()
    {
      return endPos.getOffset();
    }

    /**
     * Returns the name of this <code>Element</code>. This is
     * {@link #ContentElementName} in this case.
     *
     * @return the name of this <code>Element</code>
     */
    public String getName()
    {
      String name = super.getName();
      if (name == null)
        name = ContentElementName;
      return name;
    }

    /**
     * Returns the start offset of this <code>Element</code> inside the
     * document.
     *
     * @return the start offset of this <code>Element</code> inside the
     *         document
     */
    public int getStartOffset()
    {
      return startPos.getOffset();
    }

    /**
     * Returns <code>true</code>.
     *
     * @return <code>true</code>
     */
    public boolean isLeaf()
    {
      return true;
    }

    /**
     * Returns a string representation of this <code>Element</code>.
     *
     * @return a string representation of this <code>Element</code>
     */
    public String toString()
    {
      return ("LeafElement(" + getName() + ") "
              + getStartOffset() + "," + getEndOffset() + "\n");
    }
  }

  /**
   * The root element for bidirectional text.
   */
  private class BidiRootElement
    extends BranchElement
  {
    /**
     * Creates a new bidi root element.
     */
    BidiRootElement()
    {
      super(null, null);
    }

    /**
     * Returns the name of the element.
     *
     * @return the name of the element
     */
    public String getName()
    {
      return BidiRootName;
    }
  }

  /**
   * A leaf element for the bidi structure.
   */
  private class BidiElement
    extends LeafElement
  {
    /**
     * Creates a new BidiElement.
     *
     * @param parent the parent element
     * @param start the start offset
     * @param end the end offset
     * @param level the bidi level
     */
    BidiElement(Element parent, int start, int end, int level)
    {
      super(parent, new SimpleAttributeSet(), start, end);
      addAttribute(StyleConstants.BidiLevel, new Integer(level));
    }

    /**
     * Returns the name of the element.
     *
     * @return the name of the element
     */
    public String getName()
    {
      return BidiElementName;
    }
  }

  /** A class whose methods delegate to the insert, remove and replace methods
   * of this document which do not check for an installed DocumentFilter.
   */
  class Bypass extends DocumentFilter.FilterBypass
  {

    public Document getDocument()
    {
      return AbstractDocument.this;
    }

    public void insertString(int offset, String string, AttributeSet attr)
    throws BadLocationException
    {
      AbstractDocument.this.insertStringImpl(offset, string, attr);
    }

    public void remove(int offset, int length)
    throws BadLocationException
    {
      AbstractDocument.this.removeImpl(offset, length);
    }

    public void replace(int offset, int length, String string,
                        AttributeSet attrs)
    throws BadLocationException
    {
      AbstractDocument.this.replaceImpl(offset, length, string, attrs);
    }

  }

}
