/*
 * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
package javax.swing.text.html;

import java.awt.Color;
import java.awt.Component;
import java.awt.font.TextAttribute;
import java.util.*;
import java.net.URL;
import java.net.URLEncoder;
import java.net.MalformedURLException;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.undo.*;
import java.text.Bidi;
import sun.swing.SwingUtilities2;

/**
 * A document that models HTML.  The purpose of this model is to
 * support both browsing and editing.  As a result, the structure
 * described by an HTML document is not exactly replicated by default.
 * The element structure that is modeled by default, is built by the
 * class <code>HTMLDocument.HTMLReader</code>, which implements the
 * <code>HTMLEditorKit.ParserCallback</code> protocol that the parser
 * expects.  To change the structure one can subclass
 * <code>HTMLReader</code>, and reimplement the method {@link
 * #getReader(int)} to return the new reader implementation.  The
 * documentation for <code>HTMLReader</code> should be consulted for
 * the details of the default structure created.  The intent is that
 * the document be non-lossy (although reproducing the HTML format may
 * result in a different format).
 *
 * <p>The document models only HTML, and makes no attempt to store
 * view attributes in it.  The elements are identified by the
 * <code>StyleContext.NameAttribute</code> attribute, which should
 * always have a value of type <code>HTML.Tag</code> that identifies
 * the kind of element.  Some of the elements (such as comments) are
 * synthesized.  The <code>HTMLFactory</code> uses this attribute to
 * determine what kind of view to build.</p>
 *
 * <p>This document supports incremental loading.  The
 * <code>TokenThreshold</code> property controls how much of the parse
 * is buffered before trying to update the element structure of the
 * document.  This property is set by the <code>EditorKit</code> so
 * that subclasses can disable it.</p>
 *
 * <p>The <code>Base</code> property determines the URL against which
 * relative URLs are resolved.  By default, this will be the
 * <code>Document.StreamDescriptionProperty</code> if the value of the
 * property is a URL.  If a &lt;BASE&gt; tag is encountered, the base
 * will become the URL specified by that tag.  Because the base URL is
 * a property, it can of course be set directly.</p>
 *
 * <p>The default content storage mechanism for this document is a gap
 * buffer (<code>GapContent</code>).  Alternatives can be supplied by
 * using the constructor that takes a <code>Content</code>
 * implementation.</p>
 *
 * <h2>Modifying HTMLDocument</h2>
 *
 * <p>In addition to the methods provided by Document and
 * StyledDocument for mutating an HTMLDocument, HTMLDocument provides
 * a number of convenience methods.  The following methods can be used
 * to insert HTML content into an existing document.</p>
 *
 * <ul>
 *   <li>{@link #setInnerHTML(Element, String)}</li>
 *   <li>{@link #setOuterHTML(Element, String)}</li>
 *   <li>{@link #insertBeforeStart(Element, String)}</li>
 *   <li>{@link #insertAfterStart(Element, String)}</li>
 *   <li>{@link #insertBeforeEnd(Element, String)}</li>
 *   <li>{@link #insertAfterEnd(Element, String)}</li>
 * </ul>
 *
 * <p>The following examples illustrate using these methods.  Each
 * example assumes the HTML document is initialized in the following
 * way:</p>
 *
 * <pre>
 * JEditorPane p = new JEditorPane();
 * p.setContentType("text/html");
 * p.setText("..."); // Document text is provided below.
 * HTMLDocument d = (HTMLDocument) p.getDocument();
 * </pre>
 *
 * <p>With the following HTML content:</p>
 *
 * <pre>
 * &lt;html>
 *   &lt;head>
 *     &lt;title>An example HTMLDocument&lt;/title>
 *     &lt;style type="text/css">
 *       div { background-color: silver; }
 *       ul { color: red; }
 *     &lt;/style>
 *   &lt;/head>
 *   &lt;body>
 *     &lt;div id="BOX">
 *       &lt;p>Paragraph 1&lt;/p>
 *       &lt;p>Paragraph 2&lt;/p>
 *     &lt;/div>
 *   &lt;/body>
 * &lt;/html>
 * </pre>
 *
 * <p>All the methods for modifying an HTML document require an {@link
 * Element}.  Elements can be obtained from an HTML document by using
 * the method {@link #getElement(Element e, Object attribute, Object
 * value)}.  It returns the first descendant element that contains the
 * specified attribute with the given value, in depth-first order.
 * For example, <code>d.getElement(d.getDefaultRootElement(),
 * StyleConstants.NameAttribute, HTML.Tag.P)</code> returns the first
 * paragraph element.</p>
 *
 * <p>A convenient shortcut for locating elements is the method {@link
 * #getElement(String)}; returns an element whose <code>ID</code>
 * attribute matches the specified value.  For example,
 * <code>d.getElement("BOX")</code> returns the <code>DIV</code>
 * element.</p>
 *
 * <p>The {@link #getIterator(HTML.Tag t)} method can also be used for
 * finding all occurrences of the specified HTML tag in the
 * document.</p>
 *
 * <h3>Inserting elements</h3>
 *
 * <p>Elements can be inserted before or after the existing children
 * of any non-leaf element by using the methods
 * <code>insertAfterStart</code> and <code>insertBeforeEnd</code>.
 * For example, if <code>e</code> is the <code>DIV</code> element,
 * <code>d.insertAfterStart(e, "&lt;ul>&lt;li>List
 * Item&lt;/li>&lt;/ul>")</code> inserts the list before the first
 * paragraph, and <code>d.insertBeforeEnd(e, "&lt;ul>&lt;li>List
 * Item&lt;/li>&lt;/ul>")</code> inserts the list after the last
 * paragraph.  The <code>DIV</code> block becomes the parent of the
 * newly inserted elements.</p>
 *
 * <p>Sibling elements can be inserted before or after any element by
 * using the methods <code>insertBeforeStart</code> and
 * <code>insertAfterEnd</code>.  For example, if <code>e</code> is the
 * <code>DIV</code> element, <code>d.insertBeforeStart(e,
 * "&lt;ul>&lt;li>List Item&lt;/li>&lt;/ul>")</code> inserts the list
 * before the <code>DIV</code> element, and <code>d.insertAfterEnd(e,
 * "&lt;ul>&lt;li>List Item&lt;/li>&lt;/ul>")</code> inserts the list
 * after the <code>DIV</code> element.  The newly inserted elements
 * become siblings of the <code>DIV</code> element.</p>
 *
 * <h3>Replacing elements</h3>
 *
 * <p>Elements and all their descendants can be replaced by using the
 * methods <code>setInnerHTML</code> and <code>setOuterHTML</code>.
 * For example, if <code>e</code> is the <code>DIV</code> element,
 * <code>d.setInnerHTML(e, "&lt;ul>&lt;li>List
 * Item&lt;/li>&lt;/ul>")</code> replaces all children paragraphs with
 * the list, and <code>d.setOuterHTML(e, "&lt;ul>&lt;li>List
 * Item&lt;/li>&lt;/ul>")</code> replaces the <code>DIV</code> element
 * itself.  In latter case the parent of the list is the
 * <code>BODY</code> element.
 *
 * <h3>Summary</h3>
 *
 * <p>The following table shows the example document and the results
 * of various methods described above.</p>
 *
 * <table border=1 cellspacing=0>
 *   <tr>
 *     <th>Example</th>
 *     <th><code>insertAfterStart</code></th>
 *     <th><code>insertBeforeEnd</code></th>
 *     <th><code>insertBeforeStart</code></th>
 *     <th><code>insertAfterEnd</code></th>
 *     <th><code>setInnerHTML</code></th>
 *     <th><code>setOuterHTML</code></th>
 *   </tr>
 *   <tr valign="top">
 *     <td nowrap="nowrap">
 *       <div style="background-color: silver;">
 *         <p>Paragraph 1</p>
 *         <p>Paragraph 2</p>
 *       </div>
 *     </td>
 * <!--insertAfterStart-->
 *     <td nowrap="nowrap">
 *       <div style="background-color: silver;">
 *         <ul style="color: red;">
 *           <li>List Item</li>
 *         </ul>
 *         <p>Paragraph 1</p>
 *         <p>Paragraph 2</p>
 *       </div>
 *     </td>
 * <!--insertBeforeEnd-->
 *     <td nowrap="nowrap">
 *       <div style="background-color: silver;">
 *         <p>Paragraph 1</p>
 *         <p>Paragraph 2</p>
 *         <ul style="color: red;">
 *           <li>List Item</li>
 *         </ul>
 *       </div>
 *     </td>
 * <!--insertBeforeStart-->
 *     <td nowrap="nowrap">
 *       <ul style="color: red;">
 *         <li>List Item</li>
 *       </ul>
 *       <div style="background-color: silver;">
 *         <p>Paragraph 1</p>
 *         <p>Paragraph 2</p>
 *       </div>
 *     </td>
 * <!--insertAfterEnd-->
 *     <td nowrap="nowrap">
 *       <div style="background-color: silver;">
 *         <p>Paragraph 1</p>
 *         <p>Paragraph 2</p>
 *       </div>
 *       <ul style="color: red;">
 *         <li>List Item</li>
 *       </ul>
 *     </td>
 * <!--setInnerHTML-->
 *     <td nowrap="nowrap">
 *       <div style="background-color: silver;">
 *         <ul style="color: red;">
 *           <li>List Item</li>
 *         </ul>
 *       </div>
 *     </td>
 * <!--setOuterHTML-->
 *     <td nowrap="nowrap">
 *       <ul style="color: red;">
 *         <li>List Item</li>
 *       </ul>
 *     </td>
 *   </tr>
 * </table>
 *
 * <p><strong>Warning:</strong> Serialized objects of this class will
 * not be compatible with future Swing releases. The current
 * serialization support is appropriate for short term storage or RMI
 * between applications running the same version of Swing.  As of 1.4,
 * support for long term storage of all JavaBeans<sup><font
 * size="-2">TM</font></sup> has been added to the
 * <code>java.beans</code> package.  Please see {@link
 * java.beans.XMLEncoder}.</p>
 *
 * @author  Timothy Prinzing
 * @author  Scott Violet
 * @author  Sunita Mani
 */
public class HTMLDocument extends DefaultStyledDocument {
    /**
     * Constructs an HTML document using the default buffer size
     * and a default <code>StyleSheet</code>.  This is a convenience
     * method for the constructor
     * <code>HTMLDocument(Content, StyleSheet)</code>.
     */
    public HTMLDocument() {
        this(new GapContent(BUFFER_SIZE_DEFAULT), new StyleSheet());
    }

    /**
     * Constructs an HTML document with the default content
     * storage implementation and the specified style/attribute
     * storage mechanism.  This is a convenience method for the
     * constructor
     * <code>HTMLDocument(Content, StyleSheet)</code>.
     *
     * @param styles  the styles
     */
    public HTMLDocument(StyleSheet styles) {
        this(new GapContent(BUFFER_SIZE_DEFAULT), styles);
    }

    /**
     * Constructs an HTML document with the given content
     * storage implementation and the given style/attribute
     * storage mechanism.
     *
     * @param c  the container for the content
     * @param styles the styles
     */
    public HTMLDocument(Content c, StyleSheet styles) {
        super(c, styles);
    }

    /**
     * Fetches the reader for the parser to use when loading the document
     * with HTML.  This is implemented to return an instance of
     * <code>HTMLDocument.HTMLReader</code>.
     * Subclasses can reimplement this
     * method to change how the document gets structured if desired.
     * (For example, to handle custom tags, or structurally represent character
     * style elements.)
     *
     * @param pos the starting position
     * @return the reader used by the parser to load the document
     */
    public HTMLEditorKit.ParserCallback getReader(int pos) {
        Object desc = getProperty(Document.StreamDescriptionProperty);
        if (desc instanceof URL) {
            setBase((URL)desc);
        }
        HTMLReader reader = new HTMLReader(pos);
        return reader;
    }

    /**
     * Returns the reader for the parser to use to load the document
     * with HTML.  This is implemented to return an instance of
     * <code>HTMLDocument.HTMLReader</code>.
     * Subclasses can reimplement this
     * method to change how the document gets structured if desired.
     * (For example, to handle custom tags, or structurally represent character
     * style elements.)
     * <p>This is a convenience method for
     * <code>getReader(int, int, int, HTML.Tag, TRUE)</code>.
     *
     * @param popDepth   the number of <code>ElementSpec.EndTagTypes</code>
     *          to generate before inserting
     * @param pushDepth  the number of <code>ElementSpec.StartTagTypes</code>
     *          with a direction of <code>ElementSpec.JoinNextDirection</code>
     *          that should be generated before inserting,
     *          but after the end tags have been generated
     * @param insertTag  the first tag to start inserting into document
     * @return the reader used by the parser to load the document
     */
    public HTMLEditorKit.ParserCallback getReader(int pos, int popDepth,
                                                  int pushDepth,
                                                  HTML.Tag insertTag) {
        return getReader(pos, popDepth, pushDepth, insertTag, true);
    }

    /**
     * Fetches the reader for the parser to use to load the document
     * with HTML.  This is implemented to return an instance of
     * HTMLDocument.HTMLReader.  Subclasses can reimplement this
     * method to change how the document get structured if desired
     * (e.g. to handle custom tags, structurally represent character
     * style elements, etc.).
     *
     * @param popDepth   the number of <code>ElementSpec.EndTagTypes</code>
     *          to generate before inserting
     * @param pushDepth  the number of <code>ElementSpec.StartTagTypes</code>
     *          with a direction of <code>ElementSpec.JoinNextDirection</code>
     *          that should be generated before inserting,
     *          but after the end tags have been generated
     * @param insertTag  the first tag to start inserting into document
     * @param insertInsertTag  false if all the Elements after insertTag should
     *        be inserted; otherwise insertTag will be inserted
     * @return the reader used by the parser to load the document
     */
    HTMLEditorKit.ParserCallback getReader(int pos, int popDepth,
                                           int pushDepth,
                                           HTML.Tag insertTag,
                                           boolean insertInsertTag) {
        Object desc = getProperty(Document.StreamDescriptionProperty);
        if (desc instanceof URL) {
            setBase((URL)desc);
        }
        HTMLReader reader = new HTMLReader(pos, popDepth, pushDepth,
                                           insertTag, insertInsertTag, false,
                                           true);
        return reader;
    }

    /**
     * Returns the location to resolve relative URLs against.  By
     * default this will be the document's URL if the document
     * was loaded from a URL.  If a base tag is found and
     * can be parsed, it will be used as the base location.
     *
     * @return the base location
     */
    public URL getBase() {
        return base;
    }

    /**
     * Sets the location to resolve relative URLs against.  By
     * default this will be the document's URL if the document
     * was loaded from a URL.  If a base tag is found and
     * can be parsed, it will be used as the base location.
     * <p>This also sets the base of the <code>StyleSheet</code>
     * to be <code>u</code> as well as the base of the document.
     *
     * @param u  the desired base URL
     */
    public void setBase(URL u) {
        base = u;
        getStyleSheet().setBase(u);
    }

    /**
     * Inserts new elements in bulk.  This is how elements get created
     * in the document.  The parsing determines what structure is needed
     * and creates the specification as a set of tokens that describe the
     * edit while leaving the document free of a write-lock.  This method
     * can then be called in bursts by the reader to acquire a write-lock
     * for a shorter duration (i.e. while the document is actually being
     * altered).
     *
     * @param offset the starting offset
     * @param data the element data
     * @exception BadLocationException  if the given position does not
     *   represent a valid location in the associated document.
     */
    protected void insert(int offset, ElementSpec[] data) throws BadLocationException {
        super.insert(offset, data);
    }

    /**
     * Updates document structure as a result of text insertion.  This
     * will happen within a write lock.  This implementation simply
     * parses the inserted content for line breaks and builds up a set
     * of instructions for the element buffer.
     *
     * @param chng a description of the document change
     * @param attr the attributes
     */
    protected void insertUpdate(DefaultDocumentEvent chng, AttributeSet attr) {
        if(attr == null) {
            attr = contentAttributeSet;
        }

        // If this is the composed text element, merge the content attribute to it
        else if (attr.isDefined(StyleConstants.ComposedTextAttribute)) {
            ((MutableAttributeSet)attr).addAttributes(contentAttributeSet);
        }

        if (attr.isDefined(IMPLIED_CR)) {
            ((MutableAttributeSet)attr).removeAttribute(IMPLIED_CR);
        }

        super.insertUpdate(chng, attr);
    }

    /**
     * Replaces the contents of the document with the given
     * element specifications.  This is called before insert if
     * the loading is done in bursts.  This is the only method called
     * if loading the document entirely in one burst.
     *
     * @param data  the new contents of the document
     */
    protected void create(ElementSpec[] data) {
        super.create(data);
    }

    /**
     * Sets attributes for a paragraph.
     * <p>
     * This method is thread safe, although most Swing methods
     * are not. Please see
     * <A HREF="http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html">How
     * to Use Threads</A> for more information.
     *
     * @param offset the offset into the paragraph (must be at least 0)
     * @param length the number of characters affected (must be at least 0)
     * @param s the attributes
     * @param replace whether to replace existing attributes, or merge them
     */
    public void setParagraphAttributes(int offset, int length, AttributeSet s,
                                       boolean replace) {
        try {
            writeLock();
            // Make sure we send out a change for the length of the paragraph.
            int end = Math.min(offset + length, getLength());
            Element e = getParagraphElement(offset);
            offset = e.getStartOffset();
            e = getParagraphElement(end);
            length = Math.max(0, e.getEndOffset() - offset);
            DefaultDocumentEvent changes =
                new DefaultDocumentEvent(offset, length,
                                         DocumentEvent.EventType.CHANGE);
            AttributeSet sCopy = s.copyAttributes();
            int lastEnd = Integer.MAX_VALUE;
            for (int pos = offset; pos <= end; pos = lastEnd) {
                Element paragraph = getParagraphElement(pos);
                if (lastEnd == paragraph.getEndOffset()) {
                    lastEnd++;
                }
                else {
                    lastEnd = paragraph.getEndOffset();
                }
                MutableAttributeSet attr =
                    (MutableAttributeSet) paragraph.getAttributes();
                changes.addEdit(new AttributeUndoableEdit(paragraph, sCopy, replace));
                if (replace) {
                    attr.removeAttributes(attr);
                }
                attr.addAttributes(s);
            }
            changes.end();
            fireChangedUpdate(changes);
            fireUndoableEditUpdate(new UndoableEditEvent(this, changes));
        } finally {
            writeUnlock();
        }
    }

    /**
     * Fetches the <code>StyleSheet</code> with the document-specific display
     * rules (CSS) that were specified in the HTML document itself.
     *
     * @return the <code>StyleSheet</code>
     */
    public StyleSheet getStyleSheet() {
        return (StyleSheet) getAttributeContext();
    }

    /**
     * Fetches an iterator for the specified HTML tag.
     * This can be used for things like iterating over the
     * set of anchors contained, or iterating over the input
     * elements.
     *
     * @param t the requested <code>HTML.Tag</code>
     * @return the <code>Iterator</code> for the given HTML tag
     * @see javax.swing.text.html.HTML.Tag
     */
    public Iterator getIterator(HTML.Tag t) {
        if (t.isBlock()) {
            // TBD
            return null;
        }
        return new LeafIterator(t, this);
    }

    /**
     * Creates a document leaf element that directly represents
     * text (doesn't have any children).  This is implemented
     * to return an element of type
     * <code>HTMLDocument.RunElement</code>.
     *
     * @param parent the parent element
     * @param a the attributes for the element
     * @param p0 the beginning of the range (must be at least 0)
     * @param p1 the end of the range (must be at least p0)
     * @return the new element
     */
    protected Element createLeafElement(Element parent, AttributeSet a, int p0, int p1) {
        return new RunElement(parent, a, p0, p1);
    }

    /**
     * Creates a document branch element, that can contain other elements.
     * This is implemented to return an element of type
     * <code>HTMLDocument.BlockElement</code>.
     *
     * @param parent the parent element
     * @param a the attributes
     * @return the element
     */
    protected Element createBranchElement(Element parent, AttributeSet a) {
        return new BlockElement(parent, a);
    }

    /**
     * Creates the root element to be used to represent the
     * default document structure.
     *
     * @return the element base
     */
    protected AbstractElement createDefaultRoot() {
        // grabs a write-lock for this initialization and
        // abandon it during initialization so in normal
        // operation we can detect an illegitimate attempt
        // to mutate attributes.
        writeLock();
        MutableAttributeSet a = new SimpleAttributeSet();
        a.addAttribute(StyleConstants.NameAttribute, HTML.Tag.HTML);
        BlockElement html = new BlockElement(null, a.copyAttributes());
        a.removeAttributes(a);
        a.addAttribute(StyleConstants.NameAttribute, HTML.Tag.BODY);
        BlockElement body = new BlockElement(html, a.copyAttributes());
        a.removeAttributes(a);
        a.addAttribute(StyleConstants.NameAttribute, HTML.Tag.P);
        getStyleSheet().addCSSAttributeFromHTML(a, CSS.Attribute.MARGIN_TOP, "0");
        BlockElement paragraph = new BlockElement(body, a.copyAttributes());
        a.removeAttributes(a);
        a.addAttribute(StyleConstants.NameAttribute, HTML.Tag.CONTENT);
        RunElement brk = new RunElement(paragraph, a, 0, 1);
        Element[] buff = new Element[1];
        buff[0] = brk;
        paragraph.replace(0, 0, buff);
        buff[0] = paragraph;
        body.replace(0, 0, buff);
        buff[0] = body;
        html.replace(0, 0, buff);
        writeUnlock();
        return html;
    }

    /**
     * Sets the number of tokens to buffer before trying to update
     * the documents element structure.
     *
     * @param n  the number of tokens to buffer
     */
    public void setTokenThreshold(int n) {
        putProperty(TokenThreshold, new Integer(n));
    }

    /**
     * Gets the number of tokens to buffer before trying to update
     * the documents element structure.  The default value is
     * <code>Integer.MAX_VALUE</code>.
     *
     * @return the number of tokens to buffer
     */
    public int getTokenThreshold() {
        Integer i = (Integer) getProperty(TokenThreshold);
        if (i != null) {
            return i.intValue();
        }
        return Integer.MAX_VALUE;
    }

    /**
     * Determines how unknown tags are handled by the parser.
     * If set to true, unknown
     * tags are put in the model, otherwise they are dropped.
     *
     * @param preservesTags  true if unknown tags should be
     *          saved in the model, otherwise tags are dropped
     * @see javax.swing.text.html.HTML.Tag
     */
    public void setPreservesUnknownTags(boolean preservesTags) {
        preservesUnknownTags = preservesTags;
    }

    /**
     * Returns the behavior the parser observes when encountering
     * unknown tags.
     *
     * @see javax.swing.text.html.HTML.Tag
     * @return true if unknown tags are to be preserved when parsing
     */
    public boolean getPreservesUnknownTags() {
        return preservesUnknownTags;
    }

    /**
     * Processes <code>HyperlinkEvents</code> that
     * are generated by documents in an HTML frame.
     * The <code>HyperlinkEvent</code> type, as the parameter suggests,
     * is <code>HTMLFrameHyperlinkEvent</code>.
     * In addition to the typical information contained in a
     * <code>HyperlinkEvent</code>,
     * this event contains the element that corresponds to the frame in
     * which the click happened (the source element) and the
     * target name.  The target name has 4 possible values:
     * <ul>
     * <li>  _self
     * <li>  _parent
     * <li>  _top
     * <li>  a named frame
     * </ul>
     *
     * If target is _self, the action is to change the value of the
     * <code>HTML.Attribute.SRC</code> attribute and fires a
     * <code>ChangedUpdate</code> event.
     *<p>
     * If the target is _parent, then it deletes the parent element,
     * which is a &lt;FRAMESET&gt; element, and inserts a new &lt;FRAME&gt;
     * element, and sets its <code>HTML.Attribute.SRC</code> attribute
     * to have a value equal to the destination URL and fire a
     * <code>RemovedUpdate</code> and <code>InsertUpdate</code>.
     *<p>
     * If the target is _top, this method does nothing. In the implementation
     * of the view for a frame, namely the <code>FrameView</code>,
     * the processing of _top is handled.  Given that _top implies
     * replacing the entire document, it made sense to handle this outside
     * of the document that it will replace.
     *<p>
     * If the target is a named frame, then the element hierarchy is searched
     * for an element with a name equal to the target, its
     * <code>HTML.Attribute.SRC</code> attribute is updated and a
     * <code>ChangedUpdate</code> event is fired.
     *
     * @param e the event
     */
    public void processHTMLFrameHyperlinkEvent(HTMLFrameHyperlinkEvent e) {
        String frameName = e.getTarget();
        Element element = e.getSourceElement();
        String urlStr = e.getURL().toString();

        if (frameName.equals("_self")) {
            /*
              The source and destination elements
              are the same.
            */
            updateFrame(element, urlStr);
        } else if (frameName.equals("_parent")) {
            /*
              The destination is the parent of the frame.
            */
            updateFrameSet(element.getParentElement(), urlStr);
        } else {
            /*
              locate a named frame
            */
            Element targetElement = findFrame(frameName);
            if (targetElement != null) {
                updateFrame(targetElement, urlStr);
            }
        }
    }


    /**
     * Searches the element hierarchy for an FRAME element
     * that has its name attribute equal to the <code>frameName</code>.
     *
     * @param frameName
     * @return the element whose NAME attribute has a value of
     *          <code>frameName</code>; returns <code>null</code>
     *          if not found
     */
    private Element findFrame(String frameName) {
        ElementIterator it = new ElementIterator(this);
        Element next = null;

        while ((next = it.next()) != null) {
            AttributeSet attr = next.getAttributes();
            if (matchNameAttribute(attr, HTML.Tag.FRAME)) {
                String frameTarget = (String)attr.getAttribute(HTML.Attribute.NAME);
                if (frameTarget != null && frameTarget.equals(frameName)) {
                    break;
                }
            }
        }
        return next;
    }

    /**
     * Returns true if <code>StyleConstants.NameAttribute</code> is
     * equal to the tag that is passed in as a parameter.
     *
     * @param attr the attributes to be matched
     * @param tag the value to be matched
     * @return true if there is a match, false otherwise
     * @see javax.swing.text.html.HTML.Attribute
     */
    static boolean matchNameAttribute(AttributeSet attr, HTML.Tag tag) {
        Object o = attr.getAttribute(StyleConstants.NameAttribute);
        if (o instanceof HTML.Tag) {
            HTML.Tag name = (HTML.Tag) o;
            if (name == tag) {
                return true;
            }
        }
        return false;
    }

    /**
     * Replaces a frameset branch Element with a frame leaf element.
     *
     * @param element the frameset element to remove
     * @param url     the value for the SRC attribute for the
     *                new frame that will replace the frameset
     */
    private void updateFrameSet(Element element, String url) {
        try {
            int startOffset = element.getStartOffset();
            int endOffset = Math.min(getLength(), element.getEndOffset());
            String html = "<frame";
            if (url != null) {
                html += " src=\"" + url + "\"";
            }
            html += ">";
            installParserIfNecessary();
            setOuterHTML(element, html);
        } catch (BadLocationException e1) {
            // Should handle this better
        } catch (IOException ioe) {
            // Should handle this better
        }
    }


    /**
     * Updates the Frame elements <code>HTML.Attribute.SRC attribute</code>
     * and fires a <code>ChangedUpdate</code> event.
     *
     * @param element a FRAME element whose SRC attribute will be updated
     * @param url     a string specifying the new value for the SRC attribute
     */
    private void updateFrame(Element element, String url) {

        try {
            writeLock();
            DefaultDocumentEvent changes = new DefaultDocumentEvent(element.getStartOffset(),
                                                                    1,
                                                                    DocumentEvent.EventType.CHANGE);
            AttributeSet sCopy = element.getAttributes().copyAttributes();
            MutableAttributeSet attr = (MutableAttributeSet) element.getAttributes();
            changes.addEdit(new AttributeUndoableEdit(element, sCopy, false));
            attr.removeAttribute(HTML.Attribute.SRC);
            attr.addAttribute(HTML.Attribute.SRC, url);
            changes.end();
            fireChangedUpdate(changes);
            fireUndoableEditUpdate(new UndoableEditEvent(this, changes));
        } finally {
            writeUnlock();
        }
    }


    /**
     * Returns true if the document will be viewed in a frame.
     * @return true if document will be viewed in a frame, otherwise false
     */
    boolean isFrameDocument() {
        return frameDocument;
    }

    /**
     * Sets a boolean state about whether the document will be
     * viewed in a frame.
     * @param frameDoc  true if the document will be viewed in a frame,
     *          otherwise false
     */
    void setFrameDocumentState(boolean frameDoc) {
        this.frameDocument = frameDoc;
    }

    /**
     * Adds the specified map, this will remove a Map that has been
     * previously registered with the same name.
     *
     * @param map  the <code>Map</code> to be registered
     */
    void addMap(Map map) {
        String     name = map.getName();

        if (name != null) {
            Object     maps = getProperty(MAP_PROPERTY);

            if (maps == null) {
                maps = new Hashtable(11);
                putProperty(MAP_PROPERTY, maps);
            }
            if (maps instanceof Hashtable) {
                ((Hashtable)maps).put("#" + name, map);
            }
        }
    }

    /**
     * Removes a previously registered map.
     * @param map the <code>Map</code> to be removed
     */
    void removeMap(Map map) {
        String     name = map.getName();

        if (name != null) {
            Object     maps = getProperty(MAP_PROPERTY);

            if (maps instanceof Hashtable) {
                ((Hashtable)maps).remove("#" + name);
            }
        }
    }

    /**
     * Returns the Map associated with the given name.
     * @param the name of the desired <code>Map</code>
     * @return the <code>Map</code> or <code>null</code> if it can't
     *          be found, or if <code>name</code> is <code>null</code>
     */
    Map getMap(String name) {
        if (name != null) {
            Object     maps = getProperty(MAP_PROPERTY);

            if (maps != null && (maps instanceof Hashtable)) {
                return (Map)((Hashtable)maps).get(name);
            }
        }
        return null;
    }

    /**
     * Returns an <code>Enumeration</code> of the possible Maps.
     * @return the enumerated list of maps, or <code>null</code>
     *          if the maps are not an instance of <code>Hashtable</code>
     */
    Enumeration getMaps() {
        Object     maps = getProperty(MAP_PROPERTY);

        if (maps instanceof Hashtable) {
            return ((Hashtable)maps).elements();
        }
        return null;
    }

    /**
     * Sets the content type language used for style sheets that do not
     * explicitly specify the type. The default is text/css.
     * @param contentType  the content type language for the style sheets
     */
    /* public */
    void setDefaultStyleSheetType(String contentType) {
        putProperty(StyleType, contentType);
    }

    /**
     * Returns the content type language used for style sheets. The default
     * is text/css.
     * @return the content type language used for the style sheets
     */
    /* public */
    String getDefaultStyleSheetType() {
        String retValue = (String)getProperty(StyleType);
        if (retValue == null) {
            return "text/css";
        }
        return retValue;
    }

    /**
     * Sets the parser that is used by the methods that insert html
     * into the existing document, such as <code>setInnerHTML</code>,
     * and <code>setOuterHTML</code>.
     * <p>
     * <code>HTMLEditorKit.createDefaultDocument</code> will set the parser
     * for you. If you create an <code>HTMLDocument</code> by hand,
     * be sure and set the parser accordingly.
     * @param parser the parser to be used for text insertion
     *
     * @since 1.3
     */
    public void setParser(HTMLEditorKit.Parser parser) {
        this.parser = parser;
        putProperty("__PARSER__", null);
    }

    /**
     * Returns the parser that is used when inserting HTML into the existing
     * document.
     * @return the parser used for text insertion
     *
     * @since 1.3
     */
    public HTMLEditorKit.Parser getParser() {
        Object p = getProperty("__PARSER__");

        if (p instanceof HTMLEditorKit.Parser) {
            return (HTMLEditorKit.Parser)p;
        }
        return parser;
    }

    /**
     * Replaces the children of the given element with the contents
     * specified as an HTML string.
     *
     * <p>This will be seen as at least two events, n inserts followed by
     * a remove.</p>
     *
     * <p>Consider the following structure (the <code>elem</code>
     * parameter is <b>in bold</b>).</p>
     *
     * <pre>
     *     &lt;body>
     *       |
     *     <b>&lt;div></b>
     *      /  \
     *    &lt;p>   &lt;p>
     * </pre>
     *
     * <p>Invoking <code>setInnerHTML(elem, "&lt;ul>&lt;li>")</code>
     * results in the following structure (new elements are <font
     * color="red">in red</font>).</p>
     *
     * <pre>
     *     &lt;body>
     *       |
     *     <b>&lt;div></b>
     *         \
     *         <font color="red">&lt;ul></font>
     *           \
     *           <font color="red">&lt;li></font>
     * </pre>
     *
     * <p>Parameter <code>elem</code> must not be a leaf element,
     * otherwise an <code>IllegalArgumentException</code> is thrown.
     * If either <code>elem</code> or <code>htmlText</code> parameter
     * is <code>null</code>, no changes are made to the document.</p>
     *
     * <p>For this to work correcty, the document must have an
     * <code>HTMLEditorKit.Parser</code> set. This will be the case
     * if the document was created from an HTMLEditorKit via the
     * <code>createDefaultDocument</code> method.</p>
     *
     * @param elem the branch element whose children will be replaced
     * @param htmlText the string to be parsed and assigned to <code>elem</code>
     * @throws IllegalArgumentException if <code>elem</code> is a leaf
     * @throws IllegalStateException if an <code>HTMLEditorKit.Parser</code>
     *         has not been defined
     * @since 1.3
     */
    public void setInnerHTML(Element elem, String htmlText) throws
                             BadLocationException, IOException {
        verifyParser();
        if (elem != null && elem.isLeaf()) {
            throw new IllegalArgumentException
                ("Can not set inner HTML of a leaf");
        }
        if (elem != null && htmlText != null) {
            int oldCount = elem.getElementCount();
            int insertPosition = elem.getStartOffset();
            insertHTML(elem, elem.getStartOffset(), htmlText, true);
            if (elem.getElementCount() > oldCount) {
                // Elements were inserted, do the cleanup.
                removeElements(elem, elem.getElementCount() - oldCount,
                               oldCount);
            }
        }
    }

    /**
     * Replaces the given element in the parent with the contents
     * specified as an HTML string.
     *
     * <p>This will be seen as at least two events, n inserts followed by
     * a remove.</p>
     *
     * <p>When replacing a leaf this will attempt to make sure there is
     * a newline present if one is needed. This may result in an additional
     * element being inserted. Consider, if you were to replace a character
     * element that contained a newline with &lt;img&gt; this would create
     * two elements, one for the image, ane one for the newline.</p>
     *
     * <p>If you try to replace the element at length you will most
     * likely end up with two elements, eg
     * <code>setOuterHTML(getCharacterElement (getLength()),
     * "blah")</code> will result in two leaf elements at the end, one
     * representing 'blah', and the other representing the end
     * element.</p>
     *
     * <p>Consider the following structure (the <code>elem</code>
     * parameter is <b>in bold</b>).</p>
     *
     * <pre>
     *     &lt;body>
     *       |
     *     <b>&lt;div></b>
     *      /  \
     *    &lt;p>   &lt;p>
     * </pre>
     *
     * <p>Invoking <code>setOuterHTML(elem, "&lt;ul>&lt;li>")</code>
     * results in the following structure (new elements are <font
     * color="red">in red</font>).</p>
     *
     * <pre>
     *    &lt;body>
     *      |
     *     <font color="red">&lt;ul></font>
     *       \
     *       <font color="red">&lt;li></font>
     * </pre>
     *
     * <p>If either <code>elem</code> or <code>htmlText</code>
     * parameter is <code>null</code>, no changes are made to the
     * document.</p>
     *
     * <p>For this to work correcty, the document must have an
     * HTMLEditorKit.Parser set. This will be the case if the document
     * was created from an HTMLEditorKit via the
     * <code>createDefaultDocument</code> method.</p>
     *
     * @param elem the element to replace
     * @param htmlText the string to be parsed and inserted in place of <code>elem</code>
     * @throws IllegalStateException if an HTMLEditorKit.Parser has not
     *         been set
     * @since 1.3
     */
    public void setOuterHTML(Element elem, String htmlText) throws
                            BadLocationException, IOException {
        verifyParser();
        if (elem != null && elem.getParentElement() != null &&
            htmlText != null) {
            int start = elem.getStartOffset();
            int end = elem.getEndOffset();
            int startLength = getLength();
            // We don't want a newline if elem is a leaf, and doesn't contain
            // a newline.
            boolean wantsNewline = !elem.isLeaf();
            if (!wantsNewline && (end > startLength ||
                                 getText(end - 1, 1).charAt(0) == NEWLINE[0])){
                wantsNewline = true;
            }
            Element parent = elem.getParentElement();
            int oldCount = parent.getElementCount();
            insertHTML(parent, start, htmlText, wantsNewline);
            // Remove old.
            int newLength = getLength();
            if (oldCount != parent.getElementCount()) {
                int removeIndex = parent.getElementIndex(start + newLength -
                                                         startLength);
                removeElements(parent, removeIndex, 1);
            }
        }
    }

    /**
     * Inserts the HTML specified as a string at the start
     * of the element.
     *
     * <p>Consider the following structure (the <code>elem</code>
     * parameter is <b>in bold</b>).</p>
     *
     * <pre>
     *     &lt;body>
     *       |
     *     <b>&lt;div></b>
     *      /  \
     *    &lt;p>   &lt;p>
     * </pre>
     *
     * <p>Invoking <code>insertAfterStart(elem,
     * "&lt;ul>&lt;li>")</code> results in the following structure
     * (new elements are <font color="red">in red</font>).</p>
     *
     * <pre>
     *        &lt;body>
     *          |
     *        <b>&lt;div></b>
     *       /  |  \
     *    <font color="red">&lt;ul></font> &lt;p> &lt;p>
     *     /
     *  <font color="red">&lt;li></font>
     * </pre>
     *
     * <p>Unlike the <code>insertBeforeStart</code> method, new
     *  elements become <em>children</em> of the specified element,
     *  not siblings.</p>
     *
     * <p>Parameter <code>elem</code> must not be a leaf element,
     * otherwise an <code>IllegalArgumentException</code> is thrown.
     * If either <code>elem</code> or <code>htmlText</code> parameter
     * is <code>null</code>, no changes are made to the document.</p>
     *
     * <p>For this to work correcty, the document must have an
     * <code>HTMLEditorKit.Parser</code> set. This will be the case
     * if the document was created from an HTMLEditorKit via the
     * <code>createDefaultDocument</code> method.</p>
     *
     * @param elem the branch element to be the root for the new text
     * @param htmlText the string to be parsed and assigned to <code>elem</code>
     * @throws IllegalArgumentException if <code>elem</code> is a leaf
     * @throws IllegalStateException if an HTMLEditorKit.Parser has not
     *         been set on the document
     * @since 1.3
     */
    public void insertAfterStart(Element elem, String htmlText) throws
                                 BadLocationException, IOException {
        verifyParser();
        if (elem != null && elem.isLeaf()) {
            throw new IllegalArgumentException
                ("Can not insert HTML after start of a leaf");
        }
        insertHTML(elem, elem.getStartOffset(), htmlText, false);
    }

    /**
     * Inserts the HTML specified as a string at the end of
     * the element.
     *
     * <p> If <code>elem</code>'s children are leaves, and the
     * character at a <code>elem.getEndOffset() - 1</code> is a newline,
     * this will insert before the newline so that there isn't text after
     * the newline.</p>
     *
     * <p>Consider the following structure (the <code>elem</code>
     * parameter is <b>in bold</b>).</p>
     *
     * <pre>
     *     &lt;body>
     *       |
     *     <b>&lt;div></b>
     *      /  \
     *    &lt;p>   &lt;p>
     * </pre>
     *
     * <p>Invoking <code>insertBeforeEnd(elem, "&lt;ul>&lt;li>")</code>
     * results in the following structure (new elements are <font
     * color="red">in red</font>).</p>
     *
     * <pre>
     *        &lt;body>
     *          |
     *        <b>&lt;div></b>
     *       /  |  \
     *     &lt;p> &lt;p> <font color="red">&lt;ul></font>
     *               \
     *               <font color="red">&lt;li></font>
     * </pre>
     *
     * <p>Unlike the <code>insertAfterEnd</code> method, new elements
     * become <em>children</em> of the specified element, not
     * siblings.</p>
     *
     * <p>Parameter <code>elem</code> must not be a leaf element,
     * otherwise an <code>IllegalArgumentException</code> is thrown.
     * If either <code>elem</code> or <code>htmlText</code> parameter
     * is <code>null</code>, no changes are made to the document.</p>
     *
     * <p>For this to work correcty, the document must have an
     * <code>HTMLEditorKit.Parser</code> set. This will be the case
     * if the document was created from an HTMLEditorKit via the
     * <code>createDefaultDocument</code> method.</p>
     *
     * @param elem the element to be the root for the new text
     * @param htmlText the string to be parsed and assigned to <code>elem</code>
     * @throws IllegalArgumentException if <code>elem</code> is a leaf
     * @throws IllegalStateException if an HTMLEditorKit.Parser has not
     *         been set on the document
     * @since 1.3
     */
    public void insertBeforeEnd(Element elem, String htmlText) throws
                                BadLocationException, IOException {
        verifyParser();
        if (elem != null && elem.isLeaf()) {
            throw new IllegalArgumentException
                ("Can not set inner HTML before end of leaf");
        }
        if (elem != null) {
            int offset = elem.getEndOffset();
            if (elem.getElement(elem.getElementIndex(offset - 1)).isLeaf() &&
                getText(offset - 1, 1).charAt(0) == NEWLINE[0]) {
                offset--;
            }
            insertHTML(elem, offset, htmlText, false);
        }
    }

    /**
     * Inserts the HTML specified as a string before the start of
     * the given element.
     *
     * <p>Consider the following structure (the <code>elem</code>
     * parameter is <b>in bold</b>).</p>
     *
     * <pre>
     *     &lt;body>
     *       |
     *     <b>&lt;div></b>
     *      /  \
     *    &lt;p>   &lt;p>
     * </pre>
     *
     * <p>Invoking <code>insertBeforeStart(elem,
     * "&lt;ul>&lt;li>")</code> results in the following structure
     * (new elements are <font color="red">in red</font>).</p>
     *
     * <pre>
     *        &lt;body>
     *         /  \
     *      <font color="red">&lt;ul></font> <b>&lt;div></b>
     *       /    /  \
     *     <font color="red">&lt;li></font> &lt;p>  &lt;p>
     * </pre>
     *
     * <p>Unlike the <code>insertAfterStart</code> method, new
     * elements become <em>siblings</em> of the specified element, not
     * children.</p>
     *
     * <p>If either <code>elem</code> or <code>htmlText</code>
     * parameter is <code>null</code>, no changes are made to the
     * document.</p>
     *
     * <p>For this to work correcty, the document must have an
     * <code>HTMLEditorKit.Parser</code> set. This will be the case
     * if the document was created from an HTMLEditorKit via the
     * <code>createDefaultDocument</code> method.</p>
     *
     * @param elem the element the content is inserted before
     * @param htmlText the string to be parsed and inserted before <code>elem</code>
     * @throws IllegalStateException if an HTMLEditorKit.Parser has not
     *         been set on the document
     * @since 1.3
     */
    public void insertBeforeStart(Element elem, String htmlText) throws
                                  BadLocationException, IOException {
        verifyParser();
        if (elem != null) {
            Element parent = elem.getParentElement();

            if (parent != null) {
                insertHTML(parent, elem.getStartOffset(), htmlText, false);
            }
        }
    }

    /**
     * Inserts the HTML specified as a string after the the end of the
     * given element.
     *
     * <p>Consider the following structure (the <code>elem</code>
     * parameter is <b>in bold</b>).</p>
     *
     * <pre>
     *     &lt;body>
     *       |
     *     <b>&lt;div></b>
     *      /  \
     *    &lt;p>   &lt;p>
     * </pre>
     *
     * <p>Invoking <code>insertAfterEnd(elem, "&lt;ul>&lt;li>")</code>
     * results in the following structure (new elements are <font
     * color="red">in red</font>).</p>
     *
     * <pre>
     *        &lt;body>
     *         /  \
     *      <b>&lt;div></b> <font color="red">&lt;ul></font>
     *       / \    \
     *     &lt;p> &lt;p>  <font color="red">&lt;li></font>
     * </pre>
     *
     * <p>Unlike the <code>insertBeforeEnd</code> method, new elements
     * become <em>siblings</em> of the specified element, not
     * children.</p>
     *
     * <p>If either <code>elem</code> or <code>htmlText</code>
     * parameter is <code>null</code>, no changes are made to the
     * document.</p>
     *
     * <p>For this to work correcty, the document must have an
     * <code>HTMLEditorKit.Parser</code> set. This will be the case
     * if the document was created from an HTMLEditorKit via the
     * <code>createDefaultDocument</code> method.</p>
     *
     * @param elem the element the content is inserted after
     * @param htmlText the string to be parsed and inserted after <code>elem</code>
     * @throws IllegalStateException if an HTMLEditorKit.Parser has not
     *         been set on the document
     * @since 1.3
     */
    public void insertAfterEnd(Element elem, String htmlText) throws
                               BadLocationException, IOException {
        verifyParser();
        if (elem != null) {
            Element parent = elem.getParentElement();

            if (parent != null) {
                int offset = elem.getEndOffset();
                if (offset > getLength()) {
                    offset--;
                }
                else if (elem.isLeaf() && getText(offset - 1, 1).
                    charAt(0) == NEWLINE[0]) {
                    offset--;
                }
                insertHTML(parent, offset, htmlText, false);
            }
        }
    }

    /**
     * Returns the element that has the given id <code>Attribute</code>.
     * If the element can't be found, <code>null</code> is returned.
     * Note that this method works on an <code>Attribute</code>,
     * <i>not</i> a character tag.  In the following HTML snippet:
     * <code>&lt;a id="HelloThere"&gt;</code> the attribute is
     * 'id' and the character tag is 'a'.
     * This is a convenience method for
     * <code>getElement(RootElement, HTML.Attribute.id, id)</code>.
     * This is not thread-safe.
     *
     * @param id  the string representing the desired <code>Attribute</code>
     * @return the element with the specified <code>Attribute</code>
     *          or <code>null</code> if it can't be found,
     *          or <code>null</code> if <code>id</code> is <code>null</code>
     * @see javax.swing.text.html.HTML.Attribute
     * @since 1.3
     */
    public Element getElement(String id) {
        if (id == null) {
            return null;
        }
        return getElement(getDefaultRootElement(), HTML.Attribute.ID, id,
                          true);
    }

    /**
     * Returns the child element of <code>e</code> that contains the
     * attribute, <code>attribute</code> with value <code>value</code>, or
     * <code>null</code> if one isn't found. This is not thread-safe.
     *
     * @param e the root element where the search begins
     * @param attribute the desired <code>Attribute</code>
     * @param value the values for the specified <code>Attribute</code>
     * @return the element with the specified <code>Attribute</code>
     *          and the specified <code>value</code>, or <code>null</code>
     *          if it can't be found
     * @see javax.swing.text.html.HTML.Attribute
     * @since 1.3
     */
    public Element getElement(Element e, Object attribute, Object value) {
        return getElement(e, attribute, value, true);
    }

    /**
     * Returns the child element of <code>e</code> that contains the
     * attribute, <code>attribute</code> with value <code>value</code>, or
     * <code>null</code> if one isn't found. This is not thread-safe.
     * <p>
     * If <code>searchLeafAttributes</code> is true, and <code>e</code> is
     * a leaf, any attributes that are instances of <code>HTML.Tag</code>
     * with a value that is an <code>AttributeSet</code> will also be checked.
     *
     * @param e the root element where the search begins
     * @param attribute the desired <code>Attribute</code>
     * @param value the values for the specified <code>Attribute</code>
     * @return the element with the specified <code>Attribute</code>
     *          and the specified <code>value</code>, or <code>null</code>
     *          if it can't be found
     * @see javax.swing.text.html.HTML.Attribute
     */
    private Element getElement(Element e, Object attribute, Object value,
                               boolean searchLeafAttributes) {
        AttributeSet attr = e.getAttributes();

        if (attr != null && attr.isDefined(attribute)) {
            if (value.equals(attr.getAttribute(attribute))) {
                return e;
            }
        }
        if (!e.isLeaf()) {
            for (int counter = 0, maxCounter = e.getElementCount();
                 counter < maxCounter; counter++) {
                Element retValue = getElement(e.getElement(counter), attribute,
                                              value, searchLeafAttributes);

                if (retValue != null) {
                    return retValue;
                }
            }
        }
        else if (searchLeafAttributes && attr != null) {
            // For some leaf elements we store the actual attributes inside
            // the AttributeSet of the Element (such as anchors).
            Enumeration names = attr.getAttributeNames();
            if (names != null) {
                while (names.hasMoreElements()) {
                    Object name = names.nextElement();
                    if ((name instanceof HTML.Tag) &&
                        (attr.getAttribute(name) instanceof AttributeSet)) {

                        AttributeSet check = (AttributeSet)attr.
                                             getAttribute(name);
                        if (check.isDefined(attribute) &&
                            value.equals(check.getAttribute(attribute))) {
                            return e;
                        }
                    }
                }
            }
        }
        return null;
    }

    /**
     * Verifies the document has an <code>HTMLEditorKit.Parser</code> set.
     * If <code>getParser</code> returns <code>null</code>, this will throw an
     * IllegalStateException.
     *
     * @throws IllegalStateException if the document does not have a Parser
     */
    private void verifyParser() {
        if (getParser() == null) {
            throw new IllegalStateException("No HTMLEditorKit.Parser");
        }
    }

    /**
     * Installs a default Parser if one has not been installed yet.
     */
    private void installParserIfNecessary() {
        if (getParser() == null) {
            setParser(new HTMLEditorKit().getParser());
        }
    }

    /**
     * Inserts a string of HTML into the document at the given position.
     * <code>parent</code> is used to identify the location to insert the
     * <code>html</code>. If <code>parent</code> is a leaf this can have
     * unexpected results.
     */
    private void insertHTML(Element parent, int offset, String html,
                            boolean wantsTrailingNewline)
                 throws BadLocationException, IOException {
        if (parent != null && html != null) {
            HTMLEditorKit.Parser parser = getParser();
            if (parser != null) {
                int lastOffset = Math.max(0, offset - 1);
                Element charElement = getCharacterElement(lastOffset);
                Element commonParent = parent;
                int pop = 0;
                int push = 0;

                if (parent.getStartOffset() > lastOffset) {
                    while (commonParent != null &&
                           commonParent.getStartOffset() > lastOffset) {
                        commonParent = commonParent.getParentElement();
                        push++;
                    }
                    if (commonParent == null) {
                        throw new BadLocationException("No common parent",
                                                       offset);
                    }
                }
                while (charElement != null && charElement != commonParent) {
                    pop++;
                    charElement = charElement.getParentElement();
                }
                if (charElement != null) {
                    // Found it, do the insert.
                    HTMLReader reader = new HTMLReader(offset, pop - 1, push,
                                                       null, false, true,
                                                       wantsTrailingNewline);

                    parser.parse(new StringReader(html), reader, true);
                    reader.flush();
                }
            }
        }
    }

    /**
     * Removes child Elements of the passed in Element <code>e</code>. This
     * will do the necessary cleanup to ensure the element representing the
     * end character is correctly created.
     * <p>This is not a general purpose method, it assumes that <code>e</code>
     * will still have at least one child after the remove, and it assumes
     * the character at <code>e.getStartOffset() - 1</code> is a newline and
     * is of length 1.
     */
    private void removeElements(Element e, int index, int count) throws BadLocationException {
        writeLock();
        try {
            int start = e.getElement(index).getStartOffset();
            int end = e.getElement(index + count - 1).getEndOffset();
            if (end > getLength()) {
                removeElementsAtEnd(e, index, count, start, end);
            }
            else {
                removeElements(e, index, count, start, end);
            }
        } finally {
            writeUnlock();
        }
    }

    /**
     * Called to remove child elements of <code>e</code> when one of the
     * elements to remove is representing the end character.
     * <p>Since the Content will not allow a removal to the end character
     * this will do a remove from <code>start - 1</code> to <code>end</code>.
     * The end Element(s) will be removed, and the element representing
     * <code>start - 1</code> to <code>start</code> will be recreated. This
     * Element has to be recreated as after the content removal its offsets
     * become <code>start - 1</code> to <code>start - 1</code>.
     */
    private void removeElementsAtEnd(Element e, int index, int count,
                         int start, int end) throws BadLocationException {
        // index must be > 0 otherwise no insert would have happened.
        boolean isLeaf = (e.getElement(index - 1).isLeaf());
        DefaultDocumentEvent dde = new DefaultDocumentEvent(
                       start - 1, end - start + 1, DocumentEvent.
                       EventType.REMOVE);

        if (isLeaf) {
            Element endE = getCharacterElement(getLength());
            // e.getElement(index - 1) should represent the newline.
            index--;
            if (endE.getParentElement() != e) {
                // The hiearchies don't match, we'll have to manually
                // recreate the leaf at e.getElement(index - 1)
                replace(dde, e, index, ++count, start, end, true, true);
            }
            else {
                // The hierarchies for the end Element and
                // e.getElement(index - 1), match, we can safely remove
                // the Elements and the end content will be aligned
                // appropriately.
                replace(dde, e, index, count, start, end, true, false);
            }
        }
        else {
            // Not a leaf, descend until we find the leaf representing
            // start - 1 and remove it.
            Element newLineE = e.getElement(index - 1);
            while (!newLineE.isLeaf()) {
                newLineE = newLineE.getElement(newLineE.getElementCount() - 1);
            }
            newLineE = newLineE.getParentElement();
            replace(dde, e, index, count, start, end, false, false);
            replace(dde, newLineE, newLineE.getElementCount() - 1, 1, start,
                    end, true, true);
        }
        postRemoveUpdate(dde);
        dde.end();
        fireRemoveUpdate(dde);
        fireUndoableEditUpdate(new UndoableEditEvent(this, dde));
    }

    /**
     * This is used by <code>removeElementsAtEnd</code>, it removes
     * <code>count</code> elements starting at <code>start</code> from
     * <code>e</code>.  If <code>remove</code> is true text of length
     * <code>start - 1</code> to <code>end - 1</code> is removed.  If
     * <code>create</code> is true a new leaf is created of length 1.
     */
    private void replace(DefaultDocumentEvent dde, Element e, int index,
                         int count, int start, int end, boolean remove,
                         boolean create) throws BadLocationException {
        Element[] added;
        AttributeSet attrs = e.getElement(index).getAttributes();
        Element[] removed = new Element[count];

        for (int counter = 0; counter < count; counter++) {
            removed[counter] = e.getElement(counter + index);
        }
        if (remove) {
            UndoableEdit u = getContent().remove(start - 1, end - start);
            if (u != null) {
                dde.addEdit(u);
            }
        }
        if (create) {
            added = new Element[1];
            added[0] = createLeafElement(e, attrs, start - 1, start);
        }
        else {
            added = new Element[0];
        }
        dde.addEdit(new ElementEdit(e, index, removed, added));
        ((AbstractDocument.BranchElement)e).replace(
                                             index, removed.length, added);
    }

    /**
     * Called to remove child Elements when the end is not touched.
     */
    private void removeElements(Element e, int index, int count,
                             int start, int end) throws BadLocationException {
        Element[] removed = new Element[count];
        Element[] added = new Element[0];
        for (int counter = 0; counter < count; counter++) {
            removed[counter] = e.getElement(counter + index);
        }
        DefaultDocumentEvent dde = new DefaultDocumentEvent
                (start, end - start, DocumentEvent.EventType.REMOVE);
        ((AbstractDocument.BranchElement)e).replace(index, removed.length,
                                                    added);
        dde.addEdit(new ElementEdit(e, index, removed, added));
        UndoableEdit u = getContent().remove(start, end - start);
        if (u != null) {
            dde.addEdit(u);
        }
        postRemoveUpdate(dde);
        dde.end();
        fireRemoveUpdate(dde);
        if (u != null) {
            fireUndoableEditUpdate(new UndoableEditEvent(this, dde));
        }
    }


    // These two are provided for inner class access. The are named different
    // than the super class as the super class implementations are final.
    void obtainLock() {
        writeLock();
    }

    void releaseLock() {
        writeUnlock();
    }

    //
    // Provided for inner class access.
    //

    /**
     * Notifies all listeners that have registered interest for
     * notification on this event type.  The event instance
     * is lazily created using the parameters passed into
     * the fire method.
     *
     * @param e the event
     * @see EventListenerList
     */
    protected void fireChangedUpdate(DocumentEvent e) {
        super.fireChangedUpdate(e);
    }

    /**
     * Notifies all listeners that have registered interest for
     * notification on this event type.  The event instance
     * is lazily created using the parameters passed into
     * the fire method.
     *
     * @param e the event
     * @see EventListenerList
     */
    protected void fireUndoableEditUpdate(UndoableEditEvent e) {
        super.fireUndoableEditUpdate(e);
    }

    boolean hasBaseTag() {
        return hasBaseTag;
    }

    String getBaseTarget() {
        return baseTarget;
    }

    /*
     * state defines whether the document is a frame document
     * or not.
     */
    private boolean frameDocument = false;
    private boolean preservesUnknownTags = true;

    /*
     * Used to store button groups for radio buttons in
     * a form.
     */
    private HashMap radioButtonGroupsMap;

    /**
     * Document property for the number of tokens to buffer
     * before building an element subtree to represent them.
     */
    static final String TokenThreshold = "token threshold";

    private static final int MaxThreshold = 10000;

    private static final int StepThreshold = 5;


    /**
     * Document property key value. The value for the key will be a Vector
     * of Strings that are comments not found in the body.
     */
    public static final String AdditionalComments = "AdditionalComments";

    /**
     * Document property key value. The value for the key will be a
     * String indicating the default type of stylesheet links.
     */
    /* public */ static final String StyleType = "StyleType";

    /**
     * The location to resolve relative URLs against.  By
     * default this will be the document's URL if the document
     * was loaded from a URL.  If a base tag is found and
     * can be parsed, it will be used as the base location.
     */
    URL base;

    /**
     * does the document have base tag
     */
    boolean hasBaseTag = false;

    /**
     * BASE tag's TARGET attribute value
     */
    private String baseTarget = null;

    /**
     * The parser that is used when inserting html into the existing
     * document.
     */
    private HTMLEditorKit.Parser parser;

    /**
     * Used for inserts when a null AttributeSet is supplied.
     */
    private static AttributeSet contentAttributeSet;

    /**
     * Property Maps are registered under, will be a Hashtable.
     */
    static String MAP_PROPERTY = "__MAP__";

    private static char[] NEWLINE;
    private static final String IMPLIED_CR = "CR";

    /**
     * I18N property key.
     *
     * @see AbstractDocument.I18NProperty
     */
    private static final String I18NProperty = "i18n";

    static {
        contentAttributeSet = new SimpleAttributeSet();
        ((MutableAttributeSet)contentAttributeSet).
                        addAttribute(StyleConstants.NameAttribute,
                                     HTML.Tag.CONTENT);
        NEWLINE = new char[1];
        NEWLINE[0] = '\n';
    }


    /**
     * An iterator to iterate over a particular type of
     * tag.  The iterator is not thread safe.  If reliable
     * access to the document is not already ensured by
     * the context under which the iterator is being used,
     * its use should be performed under the protection of
     * Document.render.
     */
    public static abstract class Iterator {

        /**
         * Return the attributes for this tag.
         * @return the <code>AttributeSet</code> for this tag, or
         *      <code>null</code> if none can be found
         */
        public abstract AttributeSet getAttributes();

        /**
         * Returns the start of the range for which the current occurrence of
         * the tag is defined and has the same attributes.
         *
         * @return the start of the range, or -1 if it can't be found
         */
        public abstract int getStartOffset();

        /**
         * Returns the end of the range for which the current occurrence of
         * the tag is defined and has the same attributes.
         *
         * @return the end of the range
         */
        public abstract int getEndOffset();

        /**
         * Move the iterator forward to the next occurrence
         * of the tag it represents.
         */
        public abstract void next();

        /**
         * Indicates if the iterator is currently
         * representing an occurrence of a tag.  If
         * false there are no more tags for this iterator.
         * @return true if the iterator is currently representing an
         *              occurrence of a tag, otherwise returns false
         */
        public abstract boolean isValid();

        /**
         * Type of tag this iterator represents.
         */
        public abstract HTML.Tag getTag();
    }

    /**
     * An iterator to iterate over a particular type of tag.
     */
    static class LeafIterator extends Iterator {

        LeafIterator(HTML.Tag t, Document doc) {
            tag = t;
            pos = new ElementIterator(doc);
            endOffset = 0;
            next();
        }

        /**
         * Returns the attributes for this tag.
         * @return the <code>AttributeSet</code> for this tag,
         *              or <code>null</code> if none can be found
         */
        public AttributeSet getAttributes() {
            Element elem = pos.current();
            if (elem != null) {
                AttributeSet a = (AttributeSet)
                    elem.getAttributes().getAttribute(tag);
                if (a == null) {
                    a = (AttributeSet)elem.getAttributes();
                }
                return a;
            }
            return null;
        }

        /**
         * Returns the start of the range for which the current occurrence of
         * the tag is defined and has the same attributes.
         *
         * @return the start of the range, or -1 if it can't be found
         */
        public int getStartOffset() {
            Element elem = pos.current();
            if (elem != null) {
                return elem.getStartOffset();
            }
            return -1;
        }

        /**
         * Returns the end of the range for which the current occurrence of
         * the tag is defined and has the same attributes.
         *
         * @return the end of the range
         */
        public int getEndOffset() {
            return endOffset;
        }

        /**
         * Moves the iterator forward to the next occurrence
         * of the tag it represents.
         */
        public void next() {
            for (nextLeaf(pos); isValid(); nextLeaf(pos)) {
                Element elem = pos.current();
                if (elem.getStartOffset() >= endOffset) {
                    AttributeSet a = pos.current().getAttributes();

                    if (a.isDefined(tag) ||
                        a.getAttribute(StyleConstants.NameAttribute) == tag) {

                        // we found the next one
                        setEndOffset();
                        break;
                    }
                }
            }
        }

        /**
         * Returns the type of tag this iterator represents.
         *
         * @return the <code>HTML.Tag</code> that this iterator represents.
         * @see javax.swing.text.html.HTML.Tag
         */
        public HTML.Tag getTag() {
            return tag;
        }

        /**
         * Returns true if the current position is not <code>null</code>.
         * @return true if current position is not <code>null</code>,
         *              otherwise returns false
         */
        public boolean isValid() {
            return (pos.current() != null);
        }

        /**
         * Moves the given iterator to the next leaf element.
         * @param iter  the iterator to be scanned
         */
        void nextLeaf(ElementIterator iter) {
            for (iter.next(); iter.current() != null; iter.next()) {
                Element e = iter.current();
                if (e.isLeaf()) {
                    break;
                }
            }
        }

        /**
         * Marches a cloned iterator forward to locate the end
         * of the run.  This sets the value of <code>endOffset</code>.
         */
        void setEndOffset() {
            AttributeSet a0 = getAttributes();
            endOffset = pos.current().getEndOffset();
            ElementIterator fwd = (ElementIterator) pos.clone();
            for (nextLeaf(fwd); fwd.current() != null; nextLeaf(fwd)) {
                Element e = fwd.current();
                AttributeSet a1 = (AttributeSet) e.getAttributes().getAttribute(tag);
                if ((a1 == null) || (! a1.equals(a0))) {
                    break;
                }
                endOffset = e.getEndOffset();
            }
        }

        private int endOffset;
        private HTML.Tag tag;
        private ElementIterator pos;

    }

    /**
     * An HTML reader to load an HTML document with an HTML
     * element structure.  This is a set of callbacks from
     * the parser, implemented to create a set of elements
     * tagged with attributes.  The parse builds up tokens
     * (ElementSpec) that describe the element subtree desired,
     * and burst it into the document under the protection of
     * a write lock using the insert method on the document
     * outer class.
     * <p>
     * The reader can be configured by registering actions
     * (of type <code>HTMLDocument.HTMLReader.TagAction</code>)
     * that describe how to handle the action.  The idea behind
     * the actions provided is that the most natural text editing
     * operations can be provided if the element structure boils
     * down to paragraphs with runs of some kind of style
     * in them.  Some things are more naturally specified
     * structurally, so arbitrary structure should be allowed
     * above the paragraphs, but will need to be edited with structural
     * actions.  The implication of this is that some of the
     * HTML elements specified in the stream being parsed will
     * be collapsed into attributes, and in some cases paragraphs
     * will be synthesized.  When HTML elements have been
     * converted to attributes, the attribute key will be of
     * type HTML.Tag, and the value will be of type AttributeSet
     * so that no information is lost.  This enables many of the
     * existing actions to work so that the user can type input,
     * hit the return key, backspace, delete, etc and have a
     * reasonable result.  Selections can be created, and attributes
     * applied or removed, etc.  With this in mind, the work done
     * by the reader can be categorized into the following kinds
     * of tasks:
     * <dl>
     * <dt>Block
     * <dd>Build the structure like it's specified in the stream.
     * This produces elements that contain other elements.
     * <dt>Paragraph
     * <dd>Like block except that it's expected that the element
     * will be used with a paragraph view so a paragraph element
     * won't need to be synthesized.
     * <dt>Character
     * <dd>Contribute the element as an attribute that will start
     * and stop at arbitrary text locations.  This will ultimately
     * be mixed into a run of text, with all of the currently
     * flattened HTML character elements.
     * <dt>Special
     * <dd>Produce an embedded graphical element.
     * <dt>Form
     * <dd>Produce an element that is like the embedded graphical
     * element, except that it also has a component model associated
     * with it.
     * <dt>Hidden
     * <dd>Create an element that is hidden from view when the
     * document is being viewed read-only, and visible when the
     * document is being edited.  This is useful to keep the
     * model from losing information, and used to store things
     * like comments and unrecognized tags.
     *
     * </dl>
     * <p>
     * Currently, &lt;APPLET&gt;, &lt;PARAM&gt;, &lt;MAP&gt;, &lt;AREA&gt;, &lt;LINK&gt;,
     * &lt;SCRIPT&gt; and &lt;STYLE&gt; are unsupported.
     *
     * <p>
     * The assignment of the actions described is shown in the
     * following table for the tags defined in <code>HTML.Tag</code>.<P>
     * <table border=1 summary="HTML tags and assigned actions">
     * <tr><th>Tag</th><th>Action</th></tr>
     * <tr><td><code>HTML.Tag.A</code>         <td>CharacterAction
     * <tr><td><code>HTML.Tag.ADDRESS</code>   <td>CharacterAction
     * <tr><td><code>HTML.Tag.APPLET</code>    <td>HiddenAction
     * <tr><td><code>HTML.Tag.AREA</code>      <td>AreaAction
     * <tr><td><code>HTML.Tag.B</code>         <td>CharacterAction
     * <tr><td><code>HTML.Tag.BASE</code>      <td>BaseAction
     * <tr><td><code>HTML.Tag.BASEFONT</code>  <td>CharacterAction
     * <tr><td><code>HTML.Tag.BIG</code>       <td>CharacterAction
     * <tr><td><code>HTML.Tag.BLOCKQUOTE</code><td>BlockAction
     * <tr><td><code>HTML.Tag.BODY</code>      <td>BlockAction
     * <tr><td><code>HTML.Tag.BR</code>        <td>SpecialAction
     * <tr><td><code>HTML.Tag.CAPTION</code>   <td>BlockAction
     * <tr><td><code>HTML.Tag.CENTER</code>    <td>BlockAction
     * <tr><td><code>HTML.Tag.CITE</code>      <td>CharacterAction
     * <tr><td><code>HTML.Tag.CODE</code>      <td>CharacterAction
     * <tr><td><code>HTML.Tag.DD</code>        <td>BlockAction
     * <tr><td><code>HTML.Tag.DFN</code>       <td>CharacterAction
     * <tr><td><code>HTML.Tag.DIR</code>       <td>BlockAction
     * <tr><td><code>HTML.Tag.DIV</code>       <td>BlockAction
     * <tr><td><code>HTML.Tag.DL</code>        <td>BlockAction
     * <tr><td><code>HTML.Tag.DT</code>        <td>ParagraphAction
     * <tr><td><code>HTML.Tag.EM</code>        <td>CharacterAction
     * <tr><td><code>HTML.Tag.FONT</code>      <td>CharacterAction
     * <tr><td><code>HTML.Tag.FORM</code>      <td>As of 1.4 a BlockAction
     * <tr><td><code>HTML.Tag.FRAME</code>     <td>SpecialAction
     * <tr><td><code>HTML.Tag.FRAMESET</code>  <td>BlockAction
     * <tr><td><code>HTML.Tag.H1</code>        <td>ParagraphAction
     * <tr><td><code>HTML.Tag.H2</code>        <td>ParagraphAction
     * <tr><td><code>HTML.Tag.H3</code>        <td>ParagraphAction
     * <tr><td><code>HTML.Tag.H4</code>        <td>ParagraphAction
     * <tr><td><code>HTML.Tag.H5</code>        <td>ParagraphAction
     * <tr><td><code>HTML.Tag.H6</code>        <td>ParagraphAction
     * <tr><td><code>HTML.Tag.HEAD</code>      <td>HeadAction
     * <tr><td><code>HTML.Tag.HR</code>        <td>SpecialAction
     * <tr><td><code>HTML.Tag.HTML</code>      <td>BlockAction
     * <tr><td><code>HTML.Tag.I</code>         <td>CharacterAction
     * <tr><td><code>HTML.Tag.IMG</code>       <td>SpecialAction
     * <tr><td><code>HTML.Tag.INPUT</code>     <td>FormAction
     * <tr><td><code>HTML.Tag.ISINDEX</code>   <td>IsndexAction
     * <tr><td><code>HTML.Tag.KBD</code>       <td>CharacterAction
     * <tr><td><code>HTML.Tag.LI</code>        <td>BlockAction
     * <tr><td><code>HTML.Tag.LINK</code>      <td>LinkAction
     * <tr><td><code>HTML.Tag.MAP</code>       <td>MapAction
     * <tr><td><code>HTML.Tag.MENU</code>      <td>BlockAction
     * <tr><td><code>HTML.Tag.META</code>      <td>MetaAction
     * <tr><td><code>HTML.Tag.NOFRAMES</code>  <td>BlockAction
     * <tr><td><code>HTML.Tag.OBJECT</code>    <td>SpecialAction
     * <tr><td><code>HTML.Tag.OL</code>        <td>BlockAction
     * <tr><td><code>HTML.Tag.OPTION</code>    <td>FormAction
     * <tr><td><code>HTML.Tag.P</code>         <td>ParagraphAction
     * <tr><td><code>HTML.Tag.PARAM</code>     <td>HiddenAction
     * <tr><td><code>HTML.Tag.PRE</code>       <td>PreAction
     * <tr><td><code>HTML.Tag.SAMP</code>      <td>CharacterAction
     * <tr><td><code>HTML.Tag.SCRIPT</code>    <td>HiddenAction
     * <tr><td><code>HTML.Tag.SELECT</code>    <td>FormAction
     * <tr><td><code>HTML.Tag.SMALL</code>     <td>CharacterAction
     * <tr><td><code>HTML.Tag.STRIKE</code>    <td>CharacterAction
     * <tr><td><code>HTML.Tag.S</code>         <td>CharacterAction
     * <tr><td><code>HTML.Tag.STRONG</code>    <td>CharacterAction
     * <tr><td><code>HTML.Tag.STYLE</code>     <td>StyleAction
     * <tr><td><code>HTML.Tag.SUB</code>       <td>CharacterAction
     * <tr><td><code>HTML.Tag.SUP</code>       <td>CharacterAction
     * <tr><td><code>HTML.Tag.TABLE</code>     <td>BlockAction
     * <tr><td><code>HTML.Tag.TD</code>        <td>BlockAction
     * <tr><td><code>HTML.Tag.TEXTAREA</code>  <td>FormAction
     * <tr><td><code>HTML.Tag.TH</code>        <td>BlockAction
     * <tr><td><code>HTML.Tag.TITLE</code>     <td>TitleAction
     * <tr><td><code>HTML.Tag.TR</code>        <td>BlockAction
     * <tr><td><code>HTML.Tag.TT</code>        <td>CharacterAction
     * <tr><td><code>HTML.Tag.U</code>         <td>CharacterAction
     * <tr><td><code>HTML.Tag.UL</code>        <td>BlockAction
     * <tr><td><code>HTML.Tag.VAR</code>       <td>CharacterAction
     * </table>
     * <p>
     * Once &lt;/html> is encountered, the Actions are no longer notified.
     */
    public class HTMLReader extends HTMLEditorKit.ParserCallback {

        public HTMLReader(int offset) {
            this(offset, 0, 0, null);
        }

        public HTMLReader(int offset, int popDepth, int pushDepth,
                          HTML.Tag insertTag) {
            this(offset, popDepth, pushDepth, insertTag, true, false, true);
        }

        /**
         * Generates a RuntimeException (will eventually generate
         * a BadLocationException when API changes are alloced) if inserting
         * into non empty document, <code>insertTag</code> is
         * non-<code>null</code>, and <code>offset</code> is not in the body.
         */
        // PENDING(sky): Add throws BadLocationException and remove
        // RuntimeException
        HTMLReader(int offset, int popDepth, int pushDepth,
                   HTML.Tag insertTag, boolean insertInsertTag,
                   boolean insertAfterImplied, boolean wantsTrailingNewline) {
            emptyDocument = (getLength() == 0);
            isStyleCSS = "text/css".equals(getDefaultStyleSheetType());
            this.offset = offset;
            threshold = HTMLDocument.this.getTokenThreshold();
            tagMap = new Hashtable(57);
            TagAction na = new TagAction();
            TagAction ba = new BlockAction();
            TagAction pa = new ParagraphAction();
            TagAction ca = new CharacterAction();
            TagAction sa = new SpecialAction();
            TagAction fa = new FormAction();
            TagAction ha = new HiddenAction();
            TagAction conv = new ConvertAction();

            // register handlers for the well known tags
            tagMap.put(HTML.Tag.A, new AnchorAction());
            tagMap.put(HTML.Tag.ADDRESS, ca);
            tagMap.put(HTML.Tag.APPLET, ha);
            tagMap.put(HTML.Tag.AREA, new AreaAction());
            tagMap.put(HTML.Tag.B, conv);
            tagMap.put(HTML.Tag.BASE, new BaseAction());
            tagMap.put(HTML.Tag.BASEFONT, ca);
            tagMap.put(HTML.Tag.BIG, ca);
            tagMap.put(HTML.Tag.BLOCKQUOTE, ba);
            tagMap.put(HTML.Tag.BODY, ba);
            tagMap.put(HTML.Tag.BR, sa);
            tagMap.put(HTML.Tag.CAPTION, ba);
            tagMap.put(HTML.Tag.CENTER, ba);
            tagMap.put(HTML.Tag.CITE, ca);
            tagMap.put(HTML.Tag.CODE, ca);
            tagMap.put(HTML.Tag.DD, ba);
            tagMap.put(HTML.Tag.DFN, ca);
            tagMap.put(HTML.Tag.DIR, ba);
            tagMap.put(HTML.Tag.DIV, ba);
            tagMap.put(HTML.Tag.DL, ba);
            tagMap.put(HTML.Tag.DT, pa);
            tagMap.put(HTML.Tag.EM, ca);
            tagMap.put(HTML.Tag.FONT, conv);
            tagMap.put(HTML.Tag.FORM, new FormTagAction());
            tagMap.put(HTML.Tag.FRAME, sa);
            tagMap.put(HTML.Tag.FRAMESET, ba);
            tagMap.put(HTML.Tag.H1, pa);
            tagMap.put(HTML.Tag.H2, pa);
            tagMap.put(HTML.Tag.H3, pa);
            tagMap.put(HTML.Tag.H4, pa);
            tagMap.put(HTML.Tag.H5, pa);
            tagMap.put(HTML.Tag.H6, pa);
            tagMap.put(HTML.Tag.HEAD, new HeadAction());
            tagMap.put(HTML.Tag.HR, sa);
            tagMap.put(HTML.Tag.HTML, ba);
            tagMap.put(HTML.Tag.I, conv);
            tagMap.put(HTML.Tag.IMG, sa);
            tagMap.put(HTML.Tag.INPUT, fa);
            tagMap.put(HTML.Tag.ISINDEX, new IsindexAction());
            tagMap.put(HTML.Tag.KBD, ca);
            tagMap.put(HTML.Tag.LI, ba);
            tagMap.put(HTML.Tag.LINK, new LinkAction());
            tagMap.put(HTML.Tag.MAP, new MapAction());
            tagMap.put(HTML.Tag.MENU, ba);
            tagMap.put(HTML.Tag.META, new MetaAction());
            tagMap.put(HTML.Tag.NOBR, ca);
            tagMap.put(HTML.Tag.NOFRAMES, ba);
            tagMap.put(HTML.Tag.OBJECT, sa);
            tagMap.put(HTML.Tag.OL, ba);
            tagMap.put(HTML.Tag.OPTION, fa);
            tagMap.put(HTML.Tag.P, pa);
            tagMap.put(HTML.Tag.PARAM, new ObjectAction());
            tagMap.put(HTML.Tag.PRE, new PreAction());
            tagMap.put(HTML.Tag.SAMP, ca);
            tagMap.put(HTML.Tag.SCRIPT, ha);
            tagMap.put(HTML.Tag.SELECT, fa);
            tagMap.put(HTML.Tag.SMALL, ca);
            tagMap.put(HTML.Tag.SPAN, ca);
            tagMap.put(HTML.Tag.STRIKE, conv);
            tagMap.put(HTML.Tag.S, ca);
            tagMap.put(HTML.Tag.STRONG, ca);
            tagMap.put(HTML.Tag.STYLE, new StyleAction());
            tagMap.put(HTML.Tag.SUB, conv);
            tagMap.put(HTML.Tag.SUP, conv);
            tagMap.put(HTML.Tag.TABLE, ba);
            tagMap.put(HTML.Tag.TD, ba);
            tagMap.put(HTML.Tag.TEXTAREA, fa);
            tagMap.put(HTML.Tag.TH, ba);
            tagMap.put(HTML.Tag.TITLE, new TitleAction());
            tagMap.put(HTML.Tag.TR, ba);
            tagMap.put(HTML.Tag.TT, ca);
            tagMap.put(HTML.Tag.U, conv);
            tagMap.put(HTML.Tag.UL, ba);
            tagMap.put(HTML.Tag.VAR, ca);

            if (insertTag != null) {
                this.insertTag = insertTag;
                this.popDepth = popDepth;
                this.pushDepth = pushDepth;
                this.insertInsertTag = insertInsertTag;
                foundInsertTag = false;
            }
            else {
                foundInsertTag = true;
            }
            if (insertAfterImplied) {
                this.popDepth = popDepth;
                this.pushDepth = pushDepth;
                this.insertAfterImplied = true;
                foundInsertTag = false;
                midInsert = false;
                this.insertInsertTag = true;
                this.wantsTrailingNewline = wantsTrailingNewline;
            }
            else {
                midInsert = (!emptyDocument && insertTag == null);
                if (midInsert) {
                    generateEndsSpecsForMidInsert();
                }
            }

            /**
             * This block initializes the <code>inParagraph</code> flag.
             * It is left in <code>false</code> value automatically
             * if the target document is empty or future inserts
             * were positioned into the 'body' tag.
             */
            if (!emptyDocument && !midInsert) {
                int targetOffset = Math.max(this.offset - 1, 0);
                Element elem =
                        HTMLDocument.this.getCharacterElement(targetOffset);
                /* Going up by the left document structure path */
                for (int i = 0; i <= this.popDepth; i++) {
                    elem = elem.getParentElement();
                }
                /* Going down by the right document structure path */
                for (int i = 0; i < this.pushDepth; i++) {
                    int index = elem.getElementIndex(this.offset);
                    elem = elem.getElement(index);
                }
                AttributeSet attrs = elem.getAttributes();
                if (attrs != null) {
                    HTML.Tag tagToInsertInto =
                            (HTML.Tag) attrs.getAttribute(StyleConstants.NameAttribute);
                    if (tagToInsertInto != null) {
                        this.inParagraph = tagToInsertInto.isParagraph();
                    }
                }
            }
        }

        /**
         * Generates an initial batch of end <code>ElementSpecs</code>
         * in parseBuffer to position future inserts into the body.
         */
        private void generateEndsSpecsForMidInsert() {
            int           count = heightToElementWithName(HTML.Tag.BODY,
                                                   Math.max(0, offset - 1));
            boolean       joinNext = false;

            if (count == -1 && offset > 0) {
                count = heightToElementWithName(HTML.Tag.BODY, offset);
                if (count != -1) {
                    // Previous isn't in body, but current is. Have to
                    // do some end specs, followed by join next.
                    count = depthTo(offset - 1) - 1;
                    joinNext = true;
                }
            }
            if (count == -1) {
                throw new RuntimeException("Must insert new content into body element-");
            }
            if (count != -1) {
                // Insert a newline, if necessary.
                try {
                    if (!joinNext && offset > 0 &&
                        !getText(offset - 1, 1).equals("\n")) {
                        SimpleAttributeSet newAttrs = new SimpleAttributeSet();
                        newAttrs.addAttribute(StyleConstants.NameAttribute,
                                              HTML.Tag.CONTENT);
                        ElementSpec spec = new ElementSpec(newAttrs,
                                    ElementSpec.ContentType, NEWLINE, 0, 1);
                        parseBuffer.addElement(spec);
                    }
                    // Should never throw, but will catch anyway.
                } catch (BadLocationException ble) {}
                while (count-- > 0) {
                    parseBuffer.addElement(new ElementSpec
                                           (null, ElementSpec.EndTagType));
                }
                if (joinNext) {
                    ElementSpec spec = new ElementSpec(null, ElementSpec.
                                                       StartTagType);

                    spec.setDirection(ElementSpec.JoinNextDirection);
                    parseBuffer.addElement(spec);
                }
            }
            // We should probably throw an exception if (count == -1)
            // Or look for the body and reset the offset.
        }

        /**
         * @return number of parents to reach the child at offset.
         */
        private int depthTo(int offset) {
            Element       e = getDefaultRootElement();
            int           count = 0;

            while (!e.isLeaf()) {
                count++;
                e = e.getElement(e.getElementIndex(offset));
            }
            return count;
        }

        /**
         * @return number of parents of the leaf at <code>offset</code>
         *         until a parent with name, <code>name</code> has been
         *         found. -1 indicates no matching parent with
         *         <code>name</code>.
         */
        private int heightToElementWithName(Object name, int offset) {
            Element       e = getCharacterElement(offset).getParentElement();
            int           count = 0;

            while (e != null && e.getAttributes().getAttribute
                   (StyleConstants.NameAttribute) != name) {
                count++;
                e = e.getParentElement();
            }
            return (e == null) ? -1 : count;
        }

        /**
         * This will make sure there aren't two BODYs (the second is
         * typically created when you do a remove all, and then an insert).
         */
        private void adjustEndElement() {
            int length = getLength();
            if (length == 0) {
                return;
            }
            obtainLock();
            try {
                Element[] pPath = getPathTo(length - 1);
                int pLength = pPath.length;
                if (pLength > 1 && pPath[1].getAttributes().getAttribute
                         (StyleConstants.NameAttribute) == HTML.Tag.BODY &&
                         pPath[1].getEndOffset() == length) {
                    String lastText = getText(length - 1, 1);
                    DefaultDocumentEvent event = null;
                    Element[] added;
                    Element[] removed;
                    int index;
                    // Remove the fake second body.
                    added = new Element[0];
                    removed = new Element[1];
                    index = pPath[0].getElementIndex(length);
                    removed[0] = pPath[0].getElement(index);
                    ((BranchElement)pPath[0]).replace(index, 1, added);
                    ElementEdit firstEdit = new ElementEdit(pPath[0], index,
                                                            removed, added);

                    // Insert a new element to represent the end that the
                    // second body was representing.
                    SimpleAttributeSet sas = new SimpleAttributeSet();
                    sas.addAttribute(StyleConstants.NameAttribute,
                                         HTML.Tag.CONTENT);
                    sas.addAttribute(IMPLIED_CR, Boolean.TRUE);
                    added = new Element[1];
                    added[0] = createLeafElement(pPath[pLength - 1],
                                                     sas, length, length + 1);
                    index = pPath[pLength - 1].getElementCount();
                    ((BranchElement)pPath[pLength - 1]).replace(index, 0,
                                                                added);
                    event = new DefaultDocumentEvent(length, 1,
                                            DocumentEvent.EventType.CHANGE);
                    event.addEdit(new ElementEdit(pPath[pLength - 1],
                                         index, new Element[0], added));
                    event.addEdit(firstEdit);
                    event.end();
                    fireChangedUpdate(event);
                    fireUndoableEditUpdate(new UndoableEditEvent(this, event));

                    if (lastText.equals("\n")) {
                        // We now have two \n's, one part of the Document.
                        // We need to remove one
                        event = new DefaultDocumentEvent(length - 1, 1,
                                           DocumentEvent.EventType.REMOVE);
                        removeUpdate(event);
                        UndoableEdit u = getContent().remove(length - 1, 1);
                        if (u != null) {
                            event.addEdit(u);
                        }
                        postRemoveUpdate(event);
                        // Mark the edit as done.
                        event.end();
                        fireRemoveUpdate(event);
                        fireUndoableEditUpdate(new UndoableEditEvent(
                                               this, event));
                    }
                }
            }
            catch (BadLocationException ble) {
            }
            finally {
                releaseLock();
            }
        }

        private Element[] getPathTo(int offset) {
            Stack elements = new Stack();
            Element e = getDefaultRootElement();
            int index;
            while (!e.isLeaf()) {
                elements.push(e);
                e = e.getElement(e.getElementIndex(offset));
            }
            Element[] retValue = new Element[elements.size()];
            elements.copyInto(retValue);
            return retValue;
        }

        // -- HTMLEditorKit.ParserCallback methods --------------------

        /**
         * The last method called on the reader.  It allows
         * any pending changes to be flushed into the document.
         * Since this is currently loading synchronously, the entire
         * set of changes are pushed in at this point.
         */
        public void flush() throws BadLocationException {
            if (emptyDocument && !insertAfterImplied) {
                if (HTMLDocument.this.getLength() > 0 ||
                                      parseBuffer.size() > 0) {
                    flushBuffer(true);
                    adjustEndElement();
                }
                // We won't insert when
            }
            else {
                flushBuffer(true);
            }
        }

        /**
         * Called by the parser to indicate a block of text was
         * encountered.
         */
        public void handleText(char[] data, int pos) {
            if (receivedEndHTML || (midInsert && !inBody)) {
                return;
            }

            // see if complex glyph layout support is needed
            if(HTMLDocument.this.getProperty(I18NProperty).equals( Boolean.FALSE ) ) {
                // if a default direction of right-to-left has been specified,
                // we want complex layout even if the text is all left to right.
                Object d = getProperty(TextAttribute.RUN_DIRECTION);
                if ((d != null) && (d.equals(TextAttribute.RUN_DIRECTION_RTL))) {
                    HTMLDocument.this.putProperty( I18NProperty, Boolean.TRUE);
                } else {
                    if (SwingUtilities2.isComplexLayout(data, 0, data.length)) {
                        HTMLDocument.this.putProperty( I18NProperty, Boolean.TRUE);
                    }
                }
            }

            if (inTextArea) {
                textAreaContent(data);
            } else if (inPre) {
                preContent(data);
            } else if (inTitle) {
                putProperty(Document.TitleProperty, new String(data));
            } else if (option != null) {
                option.setLabel(new String(data));
            } else if (inStyle) {
                if (styles != null) {
                    styles.addElement(new String(data));
                }
            } else if (inBlock > 0) {
                if (!foundInsertTag && insertAfterImplied) {
                    // Assume content should be added.
                    foundInsertTag(false);
                    foundInsertTag = true;
                    inParagraph = impliedP = true;
                }
                if (data.length >= 1) {
                    addContent(data, 0, data.length);
                }
            }
        }

        /**
         * Callback from the parser.  Route to the appropriate
         * handler for the tag.
         */
        public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
            if (receivedEndHTML) {
                return;
            }
            if (midInsert && !inBody) {
                if (t == HTML.Tag.BODY) {
                    inBody = true;
                    // Increment inBlock since we know we are in the body,
                    // this is needed incase an implied-p is needed. If
                    // inBlock isn't incremented, and an implied-p is
                    // encountered, addContent won't be called!
                    inBlock++;
                }
                return;
            }
            if (!inBody && t == HTML.Tag.BODY) {
                inBody = true;
            }
            if (isStyleCSS && a.isDefined(HTML.Attribute.STYLE)) {
                // Map the style attributes.
                String decl = (String)a.getAttribute(HTML.Attribute.STYLE);
                a.removeAttribute(HTML.Attribute.STYLE);
                styleAttributes = getStyleSheet().getDeclaration(decl);
                a.addAttributes(styleAttributes);
            }
            else {
                styleAttributes = null;
            }
            TagAction action = (TagAction) tagMap.get(t);

            if (action != null) {
                action.start(t, a);
            }
        }

        public void handleComment(char[] data, int pos) {
            if (receivedEndHTML) {
                addExternalComment(new String(data));
                return;
            }
            if (inStyle) {
                if (styles != null) {
                    styles.addElement(new String(data));
                }
            }
            else if (getPreservesUnknownTags()) {
                if (inBlock == 0 && (foundInsertTag ||
                                     insertTag != HTML.Tag.COMMENT)) {
                    // Comment outside of body, will not be able to show it,
                    // but can add it as a property on the Document.
                    addExternalComment(new String(data));
                    return;
                }
                SimpleAttributeSet sas = new SimpleAttributeSet();
                sas.addAttribute(HTML.Attribute.COMMENT, new String(data));
                addSpecialElement(HTML.Tag.COMMENT, sas);
            }

            TagAction action = (TagAction)tagMap.get(HTML.Tag.COMMENT);
            if (action != null) {
                action.start(HTML.Tag.COMMENT, new SimpleAttributeSet());
                action.end(HTML.Tag.COMMENT);
            }
        }

        /**
         * Adds the comment <code>comment</code> to the set of comments
         * maintained outside of the scope of elements.
         */
        private void addExternalComment(String comment) {
            Object comments = getProperty(AdditionalComments);
            if (comments != null && !(comments instanceof Vector)) {
                // No place to put comment.
                return;
            }
            if (comments == null) {
                comments = new Vector();
                putProperty(AdditionalComments, comments);
            }
            ((Vector)comments).addElement(comment);
        }

        /**
         * Callback from the parser.  Route to the appropriate
         * handler for the tag.
         */
        public void handleEndTag(HTML.Tag t, int pos) {
            if (receivedEndHTML || (midInsert && !inBody)) {
                return;
            }
            if (t == HTML.Tag.HTML) {
                receivedEndHTML = true;
            }
            if (t == HTML.Tag.BODY) {
                inBody = false;
                if (midInsert) {
                    inBlock--;
                }
            }
            TagAction action = (TagAction) tagMap.get(t);
            if (action != null) {
                action.end(t);
            }
        }

        /**
         * Callback from the parser.  Route to the appropriate
         * handler for the tag.
         */
        public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) {
            if (receivedEndHTML || (midInsert && !inBody)) {
                return;
            }

            if (isStyleCSS && a.isDefined(HTML.Attribute.STYLE)) {
                // Map the style attributes.
                String decl = (String)a.getAttribute(HTML.Attribute.STYLE);
                a.removeAttribute(HTML.Attribute.STYLE);
                styleAttributes = getStyleSheet().getDeclaration(decl);
                a.addAttributes(styleAttributes);
            }
            else {
                styleAttributes = null;
            }

            TagAction action = (TagAction) tagMap.get(t);
            if (action != null) {
                action.start(t, a);
                action.end(t);
            }
            else if (getPreservesUnknownTags()) {
                // unknown tag, only add if should preserve it.
                addSpecialElement(t, a);
            }
        }

        /**
         * This is invoked after the stream has been parsed, but before
         * <code>flush</code>. <code>eol</code> will be one of \n, \r
         * or \r\n, which ever is encountered the most in parsing the
         * stream.
         *
         * @since 1.3
         */
        public void handleEndOfLineString(String eol) {
            if (emptyDocument && eol != null) {
                putProperty(DefaultEditorKit.EndOfLineStringProperty,
                            eol);
            }
        }

        // ---- tag handling support ------------------------------

        /**
         * Registers a handler for the given tag.  By default
         * all of the well-known tags will have been registered.
         * This can be used to change the handling of a particular
         * tag or to add support for custom tags.
         */
        protected void registerTag(HTML.Tag t, TagAction a) {
            tagMap.put(t, a);
        }

        /**
         * An action to be performed in response
         * to parsing a tag.  This allows customization
         * of how each tag is handled and avoids a large
         * switch statement.
         */
        public class TagAction {

            /**
             * Called when a start tag is seen for the
             * type of tag this action was registered
             * to.  The tag argument indicates the actual
             * tag for those actions that are shared across
             * many tags.  By default this does nothing and
             * completely ignores the tag.
             */
            public void start(HTML.Tag t, MutableAttributeSet a) {
            }

            /**
             * Called when an end tag is seen for the
             * type of tag this action was registered
             * to.  The tag argument indicates the actual
             * tag for those actions that are shared across
             * many tags.  By default this does nothing and
             * completely ignores the tag.
             */
            public void end(HTML.Tag t) {
            }

        }

        public class BlockAction extends TagAction {

            public void start(HTML.Tag t, MutableAttributeSet attr) {
                blockOpen(t, attr);
            }

            public void end(HTML.Tag t) {
                blockClose(t);
            }
        }


        /**
         * Action used for the actual element form tag. This is named such
         * as there was already a public class named FormAction.
         */
        private class FormTagAction extends BlockAction {
            public void start(HTML.Tag t, MutableAttributeSet attr) {
                super.start(t, attr);
                // initialize a ButtonGroupsMap when
                // FORM tag is encountered.  This will
                // be used for any radio buttons that
                // might be defined in the FORM.
                // for new group new ButtonGroup will be created (fix for 4529702)
                // group name is a key in radioButtonGroupsMap
                radioButtonGroupsMap = new HashMap();
            }

            public void end(HTML.Tag t) {
                super.end(t);
                // reset the button group to null since
                // the form has ended.
                radioButtonGroupsMap = null;
            }
        }


        public class ParagraphAction extends BlockAction {

            public void start(HTML.Tag t, MutableAttributeSet a) {
                super.start(t, a);
                inParagraph = true;
            }

            public void end(HTML.Tag t) {
                super.end(t);
                inParagraph = false;
            }
        }

        public class SpecialAction extends TagAction {

            public void start(HTML.Tag t, MutableAttributeSet a) {
                addSpecialElement(t, a);
            }

        }

        public class IsindexAction extends TagAction {

            public void start(HTML.Tag t, MutableAttributeSet a) {
                blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
                addSpecialElement(t, a);
                blockClose(HTML.Tag.IMPLIED);
            }

        }


        public class HiddenAction extends TagAction {

            public void start(HTML.Tag t, MutableAttributeSet a) {
                addSpecialElement(t, a);
            }

            public void end(HTML.Tag t) {
                if (!isEmpty(t)) {
                    MutableAttributeSet a = new SimpleAttributeSet();
                    a.addAttribute(HTML.Attribute.ENDTAG, "true");
                    addSpecialElement(t, a);
                }
            }

            boolean isEmpty(HTML.Tag t) {
                if (t == HTML.Tag.APPLET ||
                    t == HTML.Tag.SCRIPT) {
                    return false;
                }
                return true;
            }
        }


        /**
         * Subclass of HiddenAction to set the content type for style sheets,
         * and to set the name of the default style sheet.
         */
        class MetaAction extends HiddenAction {

            public void start(HTML.Tag t, MutableAttributeSet a) {
                Object equiv = a.getAttribute(HTML.Attribute.HTTPEQUIV);
                if (equiv != null) {
                    equiv = ((String)equiv).toLowerCase();
                    if (equiv.equals("content-style-type")) {
                        String value = (String)a.getAttribute
                                       (HTML.Attribute.CONTENT);
                        setDefaultStyleSheetType(value);
                        isStyleCSS = "text/css".equals
                                      (getDefaultStyleSheetType());
                    }
                    else if (equiv.equals("default-style")) {
                        defaultStyle = (String)a.getAttribute
                                       (HTML.Attribute.CONTENT);
                    }
                }
                super.start(t, a);
            }

            boolean isEmpty(HTML.Tag t) {
                return true;
            }
        }


        /**
         * End if overridden to create the necessary stylesheets that
         * are referenced via the link tag. It is done in this manner
         * as the meta tag can be used to specify an alternate style sheet,
         * and is not guaranteed to come before the link tags.
         */
        class HeadAction extends BlockAction {

            public void start(HTML.Tag t, MutableAttributeSet a) {
                inHead = true;
                // This check of the insertTag is put in to avoid considering
                // the implied-p that is generated for the head. This allows
                // inserts for HR to work correctly.
                if ((insertTag == null && !insertAfterImplied) ||
                    (insertTag == HTML.Tag.HEAD) ||
                    (insertAfterImplied &&
                     (foundInsertTag || !a.isDefined(IMPLIED)))) {
                    super.start(t, a);
                }
            }

            public void end(HTML.Tag t) {
                inHead = inStyle = false;
                // See if there is a StyleSheet to link to.
                if (styles != null) {
                    boolean isDefaultCSS = isStyleCSS;
                    for (int counter = 0, maxCounter = styles.size();
                         counter < maxCounter;) {
                        Object value = styles.elementAt(counter);
                        if (value == HTML.Tag.LINK) {
                            handleLink((AttributeSet)styles.
                                       elementAt(++counter));
                            counter++;
                        }
                        else {
                            // Rule.
                            // First element gives type.
                            String type = (String)styles.elementAt(++counter);
                            boolean isCSS = (type == null) ? isDefaultCSS :
                                            type.equals("text/css");
                            while (++counter < maxCounter &&
                                   (styles.elementAt(counter)
                                    instanceof String)) {
                                if (isCSS) {
                                    addCSSRules((String)styles.elementAt
                                                (counter));
                                }
                            }
                        }
                    }
                }
                if ((insertTag == null && !insertAfterImplied) ||
                    insertTag == HTML.Tag.HEAD ||
                    (insertAfterImplied && foundInsertTag)) {
                    super.end(t);
                }
            }

            boolean isEmpty(HTML.Tag t) {
                return false;
            }

            private void handleLink(AttributeSet attr) {
                // Link.
                String type = (String)attr.getAttribute(HTML.Attribute.TYPE);
                if (type == null) {
                    type = getDefaultStyleSheetType();
                }
                // Only choose if type==text/css
                // Select link if rel==stylesheet.
                // Otherwise if rel==alternate stylesheet and
                //   title matches default style.
                if (type.equals("text/css")) {
                    String rel = (String)attr.getAttribute(HTML.Attribute.REL);
                    String title = (String)attr.getAttribute
                                               (HTML.Attribute.TITLE);
                    String media = (String)attr.getAttribute
                                                   (HTML.Attribute.MEDIA);
                    if (media == null) {
                        media = "all";
                    }
                    else {
                        media = media.toLowerCase();
                    }
                    if (rel != null) {
                        rel = rel.toLowerCase();
                        if ((media.indexOf("all") != -1 ||
                             media.indexOf("screen") != -1) &&
                            (rel.equals("stylesheet") ||
                             (rel.equals("alternate stylesheet") &&
                              title.equals(defaultStyle)))) {
                            linkCSSStyleSheet((String)attr.getAttribute
                                              (HTML.Attribute.HREF));
                        }
                    }
                }
            }
        }


        /**
         * A subclass to add the AttributeSet to styles if the
         * attributes contains an attribute for 'rel' with value
         * 'stylesheet' or 'alternate stylesheet'.
         */
        class LinkAction extends HiddenAction {

            public void start(HTML.Tag t, MutableAttributeSet a) {
                String rel = (String)a.getAttribute(HTML.Attribute.REL);
                if (rel != null) {
                    rel = rel.toLowerCase();
                    if (rel.equals("stylesheet") ||
                        rel.equals("alternate stylesheet")) {
                        if (styles == null) {
                            styles = new Vector(3);
                        }
                        styles.addElement(t);
                        styles.addElement(a.copyAttributes());
                    }
                }
                super.start(t, a);
            }
        }

        class MapAction extends TagAction {

            public void start(HTML.Tag t, MutableAttributeSet a) {
                lastMap = new Map((String)a.getAttribute(HTML.Attribute.NAME));
                addMap(lastMap);
            }

            public void end(HTML.Tag t) {
            }
        }


        class AreaAction extends TagAction {

            public void start(HTML.Tag t, MutableAttributeSet a) {
                if (lastMap != null) {
                    lastMap.addArea(a.copyAttributes());
                }
            }

            public void end(HTML.Tag t) {
            }
        }


        class StyleAction extends TagAction {

            public void start(HTML.Tag t, MutableAttributeSet a) {
                if (inHead) {
                    if (styles == null) {
                        styles = new Vector(3);
                    }
                    styles.addElement(t);
                    styles.addElement(a.getAttribute(HTML.Attribute.TYPE));
                    inStyle = true;
                }
            }

            public void end(HTML.Tag t) {
                inStyle = false;
            }

            boolean isEmpty(HTML.Tag t) {
                return false;
            }
        }


        public class PreAction extends BlockAction {

            public void start(HTML.Tag t, MutableAttributeSet attr) {
                inPre = true;
                blockOpen(t, attr);
                attr.addAttribute(CSS.Attribute.WHITE_SPACE, "pre");
                blockOpen(HTML.Tag.IMPLIED, attr);
            }

            public void end(HTML.Tag t) {
                blockClose(HTML.Tag.IMPLIED);
                // set inPre to false after closing, so that if a newline
                // is added it won't generate a blockOpen.
                inPre = false;
                blockClose(t);
            }
        }

        public class CharacterAction extends TagAction {

            public void start(HTML.Tag t, MutableAttributeSet attr) {
                pushCharacterStyle();
                if (!foundInsertTag) {
                    // Note that the third argument should really be based off
                    // inParagraph and impliedP. If we're wrong (that is
                    // insertTagDepthDelta shouldn't be changed), we'll end up
                    // removing an extra EndSpec, which won't matter anyway.
                    boolean insert = canInsertTag(t, attr, false);
                    if (foundInsertTag) {
                        if (!inParagraph) {
                            inParagraph = impliedP = true;
                        }
                    }
                    if (!insert) {
                        return;
                    }
                }
                if (attr.isDefined(IMPLIED)) {
                    attr.removeAttribute(IMPLIED);
                }
                charAttr.addAttribute(t, attr.copyAttributes());
                if (styleAttributes != null) {
                    charAttr.addAttributes(styleAttributes);
                }
            }

            public void end(HTML.Tag t) {
                popCharacterStyle();
            }
        }

        /**
         * Provides conversion of HTML tag/attribute
         * mappings that have a corresponding StyleConstants
         * and CSS mapping.  The conversion is to CSS attributes.
         */
        class ConvertAction extends TagAction {

            public void start(HTML.Tag t, MutableAttributeSet attr) {
                pushCharacterStyle();
                if (!foundInsertTag) {
                    // Note that the third argument should really be based off
                    // inParagraph and impliedP. If we're wrong (that is
                    // insertTagDepthDelta shouldn't be changed), we'll end up
                    // removing an extra EndSpec, which won't matter anyway.
                    boolean insert = canInsertTag(t, attr, false);
                    if (foundInsertTag) {
                        if (!inParagraph) {
                            inParagraph = impliedP = true;
                        }
                    }
                    if (!insert) {
                        return;
                    }
                }
                if (attr.isDefined(IMPLIED)) {
                    attr.removeAttribute(IMPLIED);
                }
                if (styleAttributes != null) {
                    charAttr.addAttributes(styleAttributes);
                }
                // We also need to add attr, otherwise we lose custom
                // attributes, including class/id for style lookups, and
                // further confuse style lookup (doesn't have tag).
                charAttr.addAttribute(t, attr.copyAttributes());
                StyleSheet sheet = getStyleSheet();
                if (t == HTML.Tag.B) {
                    sheet.addCSSAttribute(charAttr, CSS.Attribute.FONT_WEIGHT, "bold");
                } else if (t == HTML.Tag.I) {
                    sheet.addCSSAttribute(charAttr, CSS.Attribute.FONT_STYLE, "italic");
                } else if (t == HTML.Tag.U) {
                    Object v = charAttr.getAttribute(CSS.Attribute.TEXT_DECORATION);
                    String value = "underline";
                    value = (v != null) ? value + "," + v.toString() : value;
                    sheet.addCSSAttribute(charAttr, CSS.Attribute.TEXT_DECORATION, value);
                } else if (t == HTML.Tag.STRIKE) {
                    Object v = charAttr.getAttribute(CSS.Attribute.TEXT_DECORATION);
                    String value = "line-through";
                    value = (v != null) ? value + "," + v.toString() : value;
                    sheet.addCSSAttribute(charAttr, CSS.Attribute.TEXT_DECORATION, value);
                } else if (t == HTML.Tag.SUP) {
                    Object v = charAttr.getAttribute(CSS.Attribute.VERTICAL_ALIGN);
                    String value = "sup";
                    value = (v != null) ? value + "," + v.toString() : value;
                    sheet.addCSSAttribute(charAttr, CSS.Attribute.VERTICAL_ALIGN, value);
                } else if (t == HTML.Tag.SUB) {
                    Object v = charAttr.getAttribute(CSS.Attribute.VERTICAL_ALIGN);
                    String value = "sub";
                    value = (v != null) ? value + "," + v.toString() : value;
                    sheet.addCSSAttribute(charAttr, CSS.Attribute.VERTICAL_ALIGN, value);
                } else if (t == HTML.Tag.FONT) {
                    String color = (String) attr.getAttribute(HTML.Attribute.COLOR);
                    if (color != null) {
                        sheet.addCSSAttribute(charAttr, CSS.Attribute.COLOR, color);
                    }
                    String face = (String) attr.getAttribute(HTML.Attribute.FACE);
                    if (face != null) {
                        sheet.addCSSAttribute(charAttr, CSS.Attribute.FONT_FAMILY, face);
                    }
                    String size = (String) attr.getAttribute(HTML.Attribute.SIZE);
                    if (size != null) {
                        sheet.addCSSAttributeFromHTML(charAttr, CSS.Attribute.FONT_SIZE, size);
                    }
                }
            }

            public void end(HTML.Tag t) {
                popCharacterStyle();
            }

        }

        class AnchorAction extends CharacterAction {

            public void start(HTML.Tag t, MutableAttributeSet attr) {
                // set flag to catch empty anchors
                emptyAnchor = true;
                super.start(t, attr);
            }

            public void end(HTML.Tag t) {
                if (emptyAnchor) {
                    // if the anchor was empty it was probably a
                    // named anchor point and we don't want to throw
                    // it away.
                    char[] one = new char[1];
                    one[0] = '\n';
                    addContent(one, 0, 1);
                }
                super.end(t);
            }
        }

        class TitleAction extends HiddenAction {

            public void start(HTML.Tag t, MutableAttributeSet attr) {
                inTitle = true;
                super.start(t, attr);
            }

            public void end(HTML.Tag t) {
                inTitle = false;
                super.end(t);
            }

            boolean isEmpty(HTML.Tag t) {
                return false;
            }
        }


        class BaseAction extends TagAction {

            public void start(HTML.Tag t, MutableAttributeSet attr) {
                String href = (String) attr.getAttribute(HTML.Attribute.HREF);
                if (href != null) {
                    try {
                        URL newBase = new URL(base, href);
                        setBase(newBase);
                        hasBaseTag = true;
                    } catch (MalformedURLException ex) {
                    }
                }
                baseTarget = (String) attr.getAttribute(HTML.Attribute.TARGET);
            }
        }

        class ObjectAction extends SpecialAction {

            public void start(HTML.Tag t, MutableAttributeSet a) {
                if (t == HTML.Tag.PARAM) {
                    addParameter(a);
                } else {
                    super.start(t, a);
                }
            }

            public void end(HTML.Tag t) {
                if (t != HTML.Tag.PARAM) {
                    super.end(t);
                }
            }

            void addParameter(AttributeSet a) {
                String name = (String) a.getAttribute(HTML.Attribute.NAME);
                String value = (String) a.getAttribute(HTML.Attribute.VALUE);
                if ((name != null) && (value != null)) {
                    ElementSpec objSpec = (ElementSpec) parseBuffer.lastElement();
                    MutableAttributeSet objAttr = (MutableAttributeSet) objSpec.getAttributes();
                    objAttr.addAttribute(name, value);
                }
            }
        }

        /**
         * Action to support forms by building all of the elements
         * used to represent form controls.  This will process
         * the &lt;INPUT&gt;, &lt;TEXTAREA&gt;, &lt;SELECT&gt;,
         * and &lt;OPTION&gt; tags.  The element created by
         * this action is expected to have the attribute
         * <code>StyleConstants.ModelAttribute</code> set to
         * the model that holds the state for the form control.
         * This enables multiple views, and allows document to
         * be iterated over picking up the data of the form.
         * The following are the model assignments for the
         * various type of form elements.
         * <table summary="model assignments for the various types of form elements">
         * <tr>
         *   <th>Element Type
         *   <th>Model Type
         * <tr>
         *   <td>input, type button
         *   <td>{@link DefaultButtonModel}
         * <tr>
         *   <td>input, type checkbox
         *   <td>{@link javax.swing.JToggleButton.ToggleButtonModel}
         * <tr>
         *   <td>input, type image
         *   <td>{@link DefaultButtonModel}
         * <tr>
         *   <td>input, type password
         *   <td>{@link PlainDocument}
         * <tr>
         *   <td>input, type radio
         *   <td>{@link javax.swing.JToggleButton.ToggleButtonModel}
         * <tr>
         *   <td>input, type reset
         *   <td>{@link DefaultButtonModel}
         * <tr>
         *   <td>input, type submit
         *   <td>{@link DefaultButtonModel}
         * <tr>
         *   <td>input, type text or type is null.
         *   <td>{@link PlainDocument}
         * <tr>
         *   <td>select
         *   <td>{@link DefaultComboBoxModel} or an {@link DefaultListModel}, with an item type of Option
         * <tr>
         *   <td>textarea
         *   <td>{@link PlainDocument}
         * </table>
         *
         */
        public class FormAction extends SpecialAction {

            public void start(HTML.Tag t, MutableAttributeSet attr) {
                if (t == HTML.Tag.INPUT) {
                    String type = (String)
                        attr.getAttribute(HTML.Attribute.TYPE);
                    /*
                     * if type is not defined teh default is
                     * assumed to be text.
                     */
                    if (type == null) {
                        type = "text";
                        attr.addAttribute(HTML.Attribute.TYPE, "text");
                    }
                    setModel(type, attr);
                } else if (t == HTML.Tag.TEXTAREA) {
                    inTextArea = true;
                    textAreaDocument = new TextAreaDocument();
                    attr.addAttribute(StyleConstants.ModelAttribute,
                                      textAreaDocument);
                } else if (t == HTML.Tag.SELECT) {
                    int size = HTML.getIntegerAttributeValue(attr,
                                                             HTML.Attribute.SIZE,
                                                             1);
                    boolean multiple = ((String)attr.getAttribute(HTML.Attribute.MULTIPLE) != null);
                    if ((size > 1) || multiple) {
                        OptionListModel m = new OptionListModel();
                        if (multiple) {
                            m.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
                        }
                        selectModel = m;
                    } else {
                        selectModel = new OptionComboBoxModel();
                    }
                    attr.addAttribute(StyleConstants.ModelAttribute,
                                      selectModel);

                }

                // build the element, unless this is an option.
                if (t == HTML.Tag.OPTION) {
                    option = new Option(attr);

                    if (selectModel instanceof OptionListModel) {
                        OptionListModel m = (OptionListModel)selectModel;
                        m.addElement(option);
                        if (option.isSelected()) {
                            m.addSelectionInterval(optionCount, optionCount);
                            m.setInitialSelection(optionCount);
                        }
                    } else if (selectModel instanceof OptionComboBoxModel) {
                        OptionComboBoxModel m = (OptionComboBoxModel)selectModel;
                        m.addElement(option);
                        if (option.isSelected()) {
                            m.setSelectedItem(option);
                            m.setInitialSelection(option);
                        }
                    }
                    optionCount++;
                } else {
                    super.start(t, attr);
                }
            }

            public void end(HTML.Tag t) {
                if (t == HTML.Tag.OPTION) {
                    option = null;
                } else {
                    if (t == HTML.Tag.SELECT) {
                        selectModel = null;
                        optionCount = 0;
                    } else if (t == HTML.Tag.TEXTAREA) {
                        inTextArea = false;

                        /* Now that the textarea has ended,
                         * store the entire initial text
                         * of the text area.  This will
                         * enable us to restore the initial
                         * state if a reset is requested.
                         */
                        textAreaDocument.storeInitialText();
                    }
                    super.end(t);
                }
            }

            void setModel(String type, MutableAttributeSet attr) {
                if (type.equals("submit") ||
                    type.equals("reset") ||
                    type.equals("image")) {

                    // button model
                    attr.addAttribute(StyleConstants.ModelAttribute,
                                      new DefaultButtonModel());
                } else if (type.equals("text") ||
                           type.equals("password")) {
                    // plain text model
                    int maxLength = HTML.getIntegerAttributeValue(
                                       attr, HTML.Attribute.MAXLENGTH, -1);
                    Document doc;

                    if (maxLength > 0) {
                        doc = new FixedLengthDocument(maxLength);
                    }
                    else {
                        doc = new PlainDocument();
                    }
                    String value = (String)
                        attr.getAttribute(HTML.Attribute.VALUE);
                    try {
                        doc.insertString(0, value, null);
                    } catch (BadLocationException e) {
                    }
                    attr.addAttribute(StyleConstants.ModelAttribute, doc);
                } else if (type.equals("file")) {
                    // plain text model
                    attr.addAttribute(StyleConstants.ModelAttribute,
                                      new PlainDocument());
                } else if (type.equals("checkbox") ||
                           type.equals("radio")) {
                    JToggleButton.ToggleButtonModel model = new JToggleButton.ToggleButtonModel();
                    if (type.equals("radio")) {
                        String name = (String) attr.getAttribute(HTML.Attribute.NAME);
                        if ( radioButtonGroupsMap == null ) { //fix for 4772743
                           radioButtonGroupsMap = new HashMap();
                        }
                        ButtonGroup radioButtonGroup = (ButtonGroup)radioButtonGroupsMap.get(name);
                        if (radioButtonGroup == null) {
                            radioButtonGroup = new ButtonGroup();
                            radioButtonGroupsMap.put(name,radioButtonGroup);
                        }
                        model.setGroup(radioButtonGroup);
                    }
                    boolean checked = (attr.getAttribute(HTML.Attribute.CHECKED) != null);
                    model.setSelected(checked);
                    attr.addAttribute(StyleConstants.ModelAttribute, model);
                }
            }

            /**
             * If a &lt;SELECT&gt; tag is being processed, this
             * model will be a reference to the model being filled
             * with the &lt;OPTION&gt; elements (which produce
             * objects of type <code>Option</code>.
             */
            Object selectModel;
            int optionCount;
        }


        // --- utility methods used by the reader ------------------

        /**
         * Pushes the current character style on a stack in preparation
         * for forming a new nested character style.
         */
        protected void pushCharacterStyle() {
            charAttrStack.push(charAttr.copyAttributes());
        }

        /**
         * Pops a previously pushed character style off the stack
         * to return to a previous style.
         */
        protected void popCharacterStyle() {
            if (!charAttrStack.empty()) {
                charAttr = (MutableAttributeSet) charAttrStack.peek();
                charAttrStack.pop();
            }
        }

        /**
         * Adds the given content to the textarea document.
         * This method gets called when we are in a textarea
         * context.  Therefore all text that is seen belongs
         * to the text area and is hence added to the
         * TextAreaDocument associated with the text area.
         */
        protected void textAreaContent(char[] data) {
            try {
                textAreaDocument.insertString(textAreaDocument.getLength(), new String(data), null);
            } catch (BadLocationException e) {
                // Should do something reasonable
            }
        }

        /**
         * Adds the given content that was encountered in a
         * PRE element.  This synthesizes lines to hold the
         * runs of text, and makes calls to addContent to
         * actually add the text.
         */
        protected void preContent(char[] data) {
            int last = 0;
            for (int i = 0; i < data.length; i++) {
                if (data[i] == '\n') {
                    addContent(data, last, i - last + 1);
                    blockClose(HTML.Tag.IMPLIED);
                    MutableAttributeSet a = new SimpleAttributeSet();
                    a.addAttribute(CSS.Attribute.WHITE_SPACE, "pre");
                    blockOpen(HTML.Tag.IMPLIED, a);
                    last = i + 1;
                }
            }
            if (last < data.length) {
                addContent(data, last, data.length - last);
            }
        }

        /**
         * Adds an instruction to the parse buffer to create a
         * block element with the given attributes.
         */
        protected void blockOpen(HTML.Tag t, MutableAttributeSet attr) {
            if (impliedP) {
                blockClose(HTML.Tag.IMPLIED);
            }

            inBlock++;

            if (!canInsertTag(t, attr, true)) {
                return;
            }
            if (attr.isDefined(IMPLIED)) {
                attr.removeAttribute(IMPLIED);
            }
            lastWasNewline = false;
            attr.addAttribute(StyleConstants.NameAttribute, t);
            ElementSpec es = new ElementSpec(
                attr.copyAttributes(), ElementSpec.StartTagType);
            parseBuffer.addElement(es);
        }

        /**
         * Adds an instruction to the parse buffer to close out
         * a block element of the given type.
         */
        protected void blockClose(HTML.Tag t) {
            inBlock--;

            if (!foundInsertTag) {
                return;
            }

            // Add a new line, if the last character wasn't one. This is
            // needed for proper positioning of the cursor. addContent
            // with true will force an implied paragraph to be generated if
            // there isn't one. This may result in a rather bogus structure
            // (perhaps a table with a child pargraph), but the paragraph
            // is needed for proper positioning and display.
            if(!lastWasNewline) {
                pushCharacterStyle();
                charAttr.addAttribute(IMPLIED_CR, Boolean.TRUE);
                addContent(NEWLINE, 0, 1, true);
                popCharacterStyle();
                lastWasNewline = true;
            }

            if (impliedP) {
                impliedP = false;
                inParagraph = false;
                if (t != HTML.Tag.IMPLIED) {
                    blockClose(HTML.Tag.IMPLIED);
                }
            }
            // an open/close with no content will be removed, so we
            // add a space of content to keep the element being formed.
            ElementSpec prev = (parseBuffer.size() > 0) ?
                (ElementSpec) parseBuffer.lastElement() : null;
            if (prev != null && prev.getType() == ElementSpec.StartTagType) {
                char[] one = new char[1];
                one[0] = ' ';
                addContent(one, 0, 1);
            }
            ElementSpec es = new ElementSpec(
                null, ElementSpec.EndTagType);
            parseBuffer.addElement(es);
        }

        /**
         * Adds some text with the current character attributes.
         *
         * @param data the content to add
         * @param offs the initial offset
         * @param length the length
         */
        protected void addContent(char[] data, int offs, int length) {
            addContent(data, offs, length, true);
        }

        /**
         * Adds some text with the current character attributes.
         *
         * @param data the content to add
         * @param offs the initial offset
         * @param length the length
         * @param generateImpliedPIfNecessary whether to generate implied
         * paragraphs
         */
        protected void addContent(char[] data, int offs, int length,
                                  boolean generateImpliedPIfNecessary) {
            if (!foundInsertTag) {
                return;
            }

            if (generateImpliedPIfNecessary && (! inParagraph) && (! inPre)) {
                blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
                inParagraph = true;
                impliedP = true;
            }
            emptyAnchor = false;
            charAttr.addAttribute(StyleConstants.NameAttribute, HTML.Tag.CONTENT);
            AttributeSet a = charAttr.copyAttributes();
            ElementSpec es = new ElementSpec(
                a, ElementSpec.ContentType, data, offs, length);
            parseBuffer.addElement(es);

            if (parseBuffer.size() > threshold) {
                if ( threshold <= MaxThreshold ) {
                    threshold *= StepThreshold;
                }
                try {
                    flushBuffer(false);
                } catch (BadLocationException ble) {
                }
            }
            if(length > 0) {
                lastWasNewline = (data[offs + length - 1] == '\n');
            }
        }

        /**
         * Adds content that is basically specified entirely
         * in the attribute set.
         */
        protected void addSpecialElement(HTML.Tag t, MutableAttributeSet a) {
            if ((t != HTML.Tag.FRAME) && (! inParagraph) && (! inPre)) {
                nextTagAfterPImplied = t;
                blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
                nextTagAfterPImplied = null;
                inParagraph = true;
                impliedP = true;
            }
            if (!canInsertTag(t, a, t.isBlock())) {
                return;
            }
            if (a.isDefined(IMPLIED)) {
                a.removeAttribute(IMPLIED);
            }
            emptyAnchor = false;
            a.addAttributes(charAttr);
            a.addAttribute(StyleConstants.NameAttribute, t);
            char[] one = new char[1];
            one[0] = ' ';
            ElementSpec es = new ElementSpec(
                a.copyAttributes(), ElementSpec.ContentType, one, 0, 1);
            parseBuffer.addElement(es);
            // Set this to avoid generating a newline for frames, frames
            // shouldn't have any content, and shouldn't need a newline.
            if (t == HTML.Tag.FRAME) {
                lastWasNewline = true;
            }
        }

        /**
         * Flushes the current parse buffer into the document.
         * @param endOfStream true if there is no more content to parser
         */
        void flushBuffer(boolean endOfStream) throws BadLocationException {
            int oldLength = HTMLDocument.this.getLength();
            int size = parseBuffer.size();
            if (endOfStream && (insertTag != null || insertAfterImplied) &&
                size > 0) {
                adjustEndSpecsForPartialInsert();
                size = parseBuffer.size();
            }
            ElementSpec[] spec = new ElementSpec[size];
            parseBuffer.copyInto(spec);

            if (oldLength == 0 && (insertTag == null && !insertAfterImplied)) {
                create(spec);
            } else {
                insert(offset, spec);
            }
            parseBuffer.removeAllElements();
            offset += HTMLDocument.this.getLength() - oldLength;
            flushCount++;
        }

        /**
         * This will be invoked for the last flush, if <code>insertTag</code>
         * is non null.
         */
        private void adjustEndSpecsForPartialInsert() {
            int size = parseBuffer.size();
            if (insertTagDepthDelta < 0) {
                // When inserting via an insertTag, the depths (of the tree
                // being read in, and existing hiearchy) may not match up.
                // This attemps to clean it up.
                int removeCounter = insertTagDepthDelta;
                while (removeCounter < 0 && size >= 0 &&
                       ((ElementSpec)parseBuffer.elementAt(size - 1)).
                       getType() == ElementSpec.EndTagType) {
                    parseBuffer.removeElementAt(--size);
                    removeCounter++;
                }
            }
            if (flushCount == 0 && (!insertAfterImplied ||
                                    !wantsTrailingNewline)) {
                // If this starts with content (or popDepth > 0 &&
                // pushDepth > 0) and ends with EndTagTypes, make sure
                // the last content isn't a \n, otherwise will end up with
                // an extra \n in the middle of content.
                int index = 0;
                if (pushDepth > 0) {
                    if (((ElementSpec)parseBuffer.elementAt(0)).getType() ==
                        ElementSpec.ContentType) {
                        index++;
                    }
                }
                index += (popDepth + pushDepth);
                int cCount = 0;
                int cStart = index;
                while (index < size && ((ElementSpec)parseBuffer.elementAt
                            (index)).getType() == ElementSpec.ContentType) {
                    index++;
                    cCount++;
                }
                if (cCount > 1) {
                    while (index < size && ((ElementSpec)parseBuffer.elementAt
                               (index)).getType() == ElementSpec.EndTagType) {
                        index++;
                    }
                    if (index == size) {
                        char[] lastText = ((ElementSpec)parseBuffer.elementAt
                                           (cStart + cCount - 1)).getArray();
                        if (lastText.length == 1 && lastText[0] == NEWLINE[0]){
                            index = cStart + cCount - 1;
                            while (size > index) {
                                parseBuffer.removeElementAt(--size);
                            }
                        }
                    }
                }
            }
            if (wantsTrailingNewline) {
                // Make sure there is in fact a newline
                for (int counter = parseBuffer.size() - 1; counter >= 0;
                                   counter--) {
                    ElementSpec spec = (ElementSpec)parseBuffer.
                                                    elementAt(counter);
                    if (spec.getType() == ElementSpec.ContentType) {
                        if (spec.getArray()[spec.getLength() - 1] != '\n') {
                            SimpleAttributeSet attrs =new SimpleAttributeSet();

                            attrs.addAttribute(StyleConstants.NameAttribute,
                                               HTML.Tag.CONTENT);
                            parseBuffer.insertElementAt(new ElementSpec(
                                    attrs,
                                    ElementSpec.ContentType, NEWLINE, 0, 1),
                                    counter + 1);
                        }
                        break;
                    }
                }
            }
        }

        /**
         * Adds the CSS rules in <code>rules</code>.
         */
        void addCSSRules(String rules) {
            StyleSheet ss = getStyleSheet();
            ss.addRule(rules);
        }

        /**
         * Adds the CSS stylesheet at <code>href</code> to the known list
         * of stylesheets.
         */
        void linkCSSStyleSheet(String href) {
            URL url = null;
            try {
                url = new URL(base, href);
            } catch (MalformedURLException mfe) {
                try {
                    url = new URL(href);
                } catch (MalformedURLException mfe2) {
                    url = null;
                }
            }
            if (url != null) {
                getStyleSheet().importStyleSheet(url);
            }
        }

        /**
         * Returns true if can insert starting at <code>t</code>. This
         * will return false if the insert tag is set, and hasn't been found
         * yet.
         */
        private boolean canInsertTag(HTML.Tag t, AttributeSet attr,
                                     boolean isBlockTag) {
            if (!foundInsertTag) {
                boolean needPImplied = ((t == HTML.Tag.IMPLIED)
                                                          && (!inParagraph)
                                                          && (!inPre));
                if (needPImplied && (nextTagAfterPImplied != null)) {

                    /*
                     * If insertTag == null then just proceed to
                     * foundInsertTag() call below and return true.
                     */
                    if (insertTag != null) {
                        boolean nextTagIsInsertTag =
                                isInsertTag(nextTagAfterPImplied);
                        if ( (! nextTagIsInsertTag) || (! insertInsertTag) ) {
                            return false;
                        }
                    }
                    /*
                     *  Proceed to foundInsertTag() call...
                     */
                 } else if ((insertTag != null && !isInsertTag(t))
                               || (insertAfterImplied
                                    && (attr == null
                                        || attr.isDefined(IMPLIED)
                                        || t == HTML.Tag.IMPLIED
                                       )
                                   )
                           ) {
                    return false;
                }

                // Allow the insert if t matches the insert tag, or
                // insertAfterImplied is true and the element is implied.
                foundInsertTag(isBlockTag);
                if (!insertInsertTag) {
                    return false;
                }
            }
            return true;
        }

        private boolean isInsertTag(HTML.Tag tag) {
            return (insertTag == tag);
        }

        private void foundInsertTag(boolean isBlockTag) {
            foundInsertTag = true;
            if (!insertAfterImplied && (popDepth > 0 || pushDepth > 0)) {
                try {
                    if (offset == 0 || !getText(offset - 1, 1).equals("\n")) {
                        // Need to insert a newline.
                        AttributeSet newAttrs = null;
                        boolean joinP = true;

                        if (offset != 0) {
                            // Determine if we can use JoinPrevious, we can't
                            // if the Element has some attributes that are
                            // not meant to be duplicated.
                            Element charElement = getCharacterElement
                                                    (offset - 1);
                            AttributeSet attrs = charElement.getAttributes();

                            if (attrs.isDefined(StyleConstants.
                                                ComposedTextAttribute)) {
                                joinP = false;
                            }
                            else {
                                Object name = attrs.getAttribute
                                              (StyleConstants.NameAttribute);
                                if (name instanceof HTML.Tag) {
                                    HTML.Tag tag = (HTML.Tag)name;
                                    if (tag == HTML.Tag.IMG ||
                                        tag == HTML.Tag.HR ||
                                        tag == HTML.Tag.COMMENT ||
                                        (tag instanceof HTML.UnknownTag)) {
                                        joinP = false;
                                    }
                                }
                            }
                        }
                        if (!joinP) {
                            // If not joining with the previous element, be
                            // sure and set the name (otherwise it will be
                            // inherited).
                            newAttrs = new SimpleAttributeSet();
                            ((SimpleAttributeSet)newAttrs).addAttribute
                                              (StyleConstants.NameAttribute,
                                               HTML.Tag.CONTENT);
                        }
                        ElementSpec es = new ElementSpec(newAttrs,
                                     ElementSpec.ContentType, NEWLINE, 0,
                                     NEWLINE.length);
                        if (joinP) {
                            es.setDirection(ElementSpec.
                                            JoinPreviousDirection);
                        }
                        parseBuffer.addElement(es);
                    }
                } catch (BadLocationException ble) {}
            }
            // pops
            for (int counter = 0; counter < popDepth; counter++) {
                parseBuffer.addElement(new ElementSpec(null, ElementSpec.
                                                       EndTagType));
            }
            // pushes
            for (int counter = 0; counter < pushDepth; counter++) {
                ElementSpec es = new ElementSpec(null, ElementSpec.
                                                 StartTagType);
                es.setDirection(ElementSpec.JoinNextDirection);
                parseBuffer.addElement(es);
            }
            insertTagDepthDelta = depthTo(Math.max(0, offset - 1)) -
                                  popDepth + pushDepth - inBlock;
            if (isBlockTag) {
                // A start spec will be added (for this tag), so we account
                // for it here.
                insertTagDepthDelta++;
            }
            else {
                // An implied paragraph close (end spec) is going to be added,
                // so we account for it here.
                insertTagDepthDelta--;
                inParagraph = true;
                lastWasNewline = false;
            }
        }

        /**
         * This is set to true when and end is invoked for <html>.
         */
        private boolean receivedEndHTML;
        /** Number of times <code>flushBuffer</code> has been invoked. */
        private int flushCount;
        /** If true, behavior is similiar to insertTag, but instead of
         * waiting for insertTag will wait for first Element without
         * an 'implied' attribute and begin inserting then. */
        private boolean insertAfterImplied;
        /** This is only used if insertAfterImplied is true. If false, only
         * inserting content, and there is a trailing newline it is removed. */
        private boolean wantsTrailingNewline;
        int threshold;
        int offset;
        boolean inParagraph = false;
        boolean impliedP = false;
        boolean inPre = false;
        boolean inTextArea = false;
        TextAreaDocument textAreaDocument = null;
        boolean inTitle = false;
        boolean lastWasNewline = true;
        boolean emptyAnchor;
        /** True if (!emptyDocument && insertTag == null), this is used so
         * much it is cached. */
        boolean midInsert;
        /** True when the body has been encountered. */
        boolean inBody;
        /** If non null, gives parent Tag that insert is to happen at. */
        HTML.Tag insertTag;
        /** If true, the insertTag is inserted, otherwise elements after
         * the insertTag is found are inserted. */
        boolean insertInsertTag;
        /** Set to true when insertTag has been found. */
        boolean foundInsertTag;
        /** When foundInsertTag is set to true, this will be updated to
         * reflect the delta between the two structures. That is, it
         * will be the depth the inserts are happening at minus the
         * depth of the tags being passed in. A value of 0 (the common
         * case) indicates the structures match, a value greater than 0 indicates
         * the insert is happening at a deeper depth than the stream is
         * parsing, and a value less than 0 indicates the insert is happening earlier
         * in the tree that the parser thinks and that we will need to remove
         * EndTagType specs in the flushBuffer method.
         */
        int insertTagDepthDelta;
        /** How many parents to ascend before insert new elements. */
        int popDepth;
        /** How many parents to descend (relative to popDepth) before
         * inserting. */
        int pushDepth;
        /** Last Map that was encountered. */
        Map lastMap;
        /** Set to true when a style element is encountered. */
        boolean inStyle = false;
        /** Name of style to use. Obtained from Meta tag. */
        String defaultStyle;
        /** Vector describing styles that should be include. Will consist
         * of a bunch of HTML.Tags, which will either be:
         * <p>LINK: in which case it is followed by an AttributeSet
         * <p>STYLE: in which case the following element is a String
         * indicating the type (may be null), and the elements following
         * it until the next HTML.Tag are the rules as Strings.
         */
        Vector styles;
        /** True if inside the head tag. */
        boolean inHead = false;
        /** Set to true if the style language is text/css. Since this is
         * used alot, it is cached. */
        boolean isStyleCSS;
        /** True if inserting into an empty document. */
        boolean emptyDocument;
        /** Attributes from a style Attribute. */
        AttributeSet styleAttributes;

        /**
         * Current option, if in an option element (needed to
         * load the label.
         */
        Option option;

        protected Vector<ElementSpec> parseBuffer = new Vector();    // Vector<ElementSpec>
        protected MutableAttributeSet charAttr = new TaggedAttributeSet();
        Stack charAttrStack = new Stack();
        Hashtable tagMap;
        int inBlock = 0;

        /**
         * This attribute is sometimes used to refer to next tag
         * to be handled after p-implied when the latter is
         * the current tag which is being handled.
         */
        private HTML.Tag nextTagAfterPImplied = null;
    }


    /**
     * Used by StyleSheet to determine when to avoid removing HTML.Tags
     * matching StyleConstants.
     */
    static class TaggedAttributeSet extends SimpleAttributeSet {
        TaggedAttributeSet() {
            super();
        }
    }


    /**
     * An element that represents a chunk of text that has
     * a set of HTML character level attributes assigned to
     * it.
     */
    public class RunElement extends LeafElement {

        /**
         * Constructs an element that represents content within the
         * document (has no children).
         *
         * @param parent  the parent element
         * @param a       the element attributes
         * @param offs0   the start offset (must be at least 0)
         * @param offs1   the end offset (must be at least offs0)
         * @since 1.4
         */
        public RunElement(Element parent, AttributeSet a, int offs0, int offs1) {
            super(parent, a, offs0, offs1);
        }

        /**
         * Gets the name of the element.
         *
         * @return the name, null if none
         */
        public String getName() {
            Object o = getAttribute(StyleConstants.NameAttribute);
            if (o != null) {
                return o.toString();
            }
            return super.getName();
        }

        /**
         * Gets the resolving parent.  HTML attributes are not inherited
         * at the model level so we override this to return null.
         *
         * @return null, there are none
         * @see AttributeSet#getResolveParent
         */
        public AttributeSet getResolveParent() {
            return null;
        }
    }

    /**
     * An element that represents a structural <em>block</em> of
     * HTML.
     */
    public class BlockElement extends BranchElement {

        /**
         * Constructs a composite element that initially contains
         * no children.
         *
         * @param parent  the parent element
         * @param a       the attributes for the element
         * @since 1.4
         */
        public BlockElement(Element parent, AttributeSet a) {
            super(parent, a);
        }

        /**
         * Gets the name of the element.
         *
         * @return the name, null if none
         */
        public String getName() {
            Object o = getAttribute(StyleConstants.NameAttribute);
            if (o != null) {
                return o.toString();
            }
            return super.getName();
        }

        /**
         * Gets the resolving parent.  HTML attributes are not inherited
         * at the model level so we override this to return null.
         *
         * @return null, there are none
         * @see AttributeSet#getResolveParent
         */
        public AttributeSet getResolveParent() {
            return null;
        }

    }


    /**
     * Document that allows you to set the maximum length of the text.
     */
    private static class FixedLengthDocument extends PlainDocument {
        private int maxLength;

        public FixedLengthDocument(int maxLength) {
            this.maxLength = maxLength;
        }

        public void insertString(int offset, String str, AttributeSet a)
            throws BadLocationException {
            if (str != null && str.length() + getLength() <= maxLength) {
                super.insertString(offset, str, a);
            }
        }
    }
}
