/* HTMLWriter.java --
   Copyright (C) 2006 Free Software Foundation, Inc.

This file is part of GNU Classpath.

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

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

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

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

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

package javax.swing.text.html;

import gnu.java.lang.CPStringBuilder;

import java.io.IOException;
import java.io.Writer;

import java.util.Enumeration;
import java.util.HashSet;

import javax.swing.ComboBoxModel;

import javax.swing.text.AbstractWriter;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.StyleConstants;

import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.Option;

/**
 * HTMLWriter,
 * A Writer for HTMLDocuments.
 *
 * @author David Fu (fchoong at netbeans.jp)
 */

public class HTMLWriter
  extends AbstractWriter
{
  /**
   * We keep a reference of the writer passed by the construct.
   */
  private Writer outWriter = null;

  /**
   * We keep a reference of the HTMLDocument passed by the construct.
   */
  private HTMLDocument htmlDoc = null;

  /**
   * Used to keep track of which embedded has been written out.
   */
  private HashSet<HTML.Tag> openEmbeddedTagHashSet = null;

  private String new_line_str = "" + NEWLINE;

  private char[] html_entity_char_arr = {'<',    '>',    '&',     '"'};

  private String[] html_entity_escape_str_arr = {"&lt;", "&gt;", "&amp;",
                                                 "&quot;"};

  // variables used to output Html Fragment
  private int doc_pos = -1;
  private int doc_len = -1;
  private int doc_offset_remaining = -1;
  private int doc_len_remaining = -1;
  private HashSet<Element> htmlFragmentParentHashSet = null;
  private Element startElem = null;
  private Element endElem = null;
  private boolean fg_pass_start_elem = false;
  private boolean fg_pass_end_elem = false;

  /**
   * Constructs a HTMLWriter.
   *
   * @param writer writer to write output to
   * @param doc the HTMLDocument to output
   */
  public HTMLWriter(Writer writer, HTMLDocument doc)
  {
    super(writer, doc);
    outWriter = writer;
    htmlDoc = doc;
    openEmbeddedTagHashSet = new HashSet<HTML.Tag>();
  } // public HTMLWriter(Writer writer, HTMLDocument doc)

  /**
   * Constructs a HTMLWriter which outputs a Html Fragment.
   *
   * @param writer <code>Writer</code> to write output to
   * @param doc the <code>javax.swing.text.html.HTMLDocument</code>
   *        to output
   * @param pos position to start outputing the document
   * @param len amount to output the document
   */
  public HTMLWriter(Writer writer, HTMLDocument doc, int pos, int len)
  {
    super(writer, doc, pos, len);
    outWriter = writer;
    htmlDoc = doc;
    openEmbeddedTagHashSet = new HashSet<HTML.Tag>();

    doc_pos = pos;
    doc_offset_remaining = pos;
    doc_len = len;
    doc_len_remaining = len;
    htmlFragmentParentHashSet = new HashSet<Element>();
  } // public HTMLWriter(Writer writer, HTMLDocument doc, int pos, int len)

  /**
   * Call this method to start outputing HTML.
   *
   * @throws IOException on any I/O exceptions
   * @throws BadLocationException if a pos is not a valid position in the
   *                              html doc element
   */
  public void write()
    throws IOException, BadLocationException
  {
    Element rootElem = htmlDoc.getDefaultRootElement();

    if (doc_pos == -1 && doc_len == -1)
      {
        // Normal traversal.
        traverse(rootElem);
      } // if(doc_pos == -1 && doc_len == -1)
    else
      {
        // Html fragment traversal.
        if (doc_pos == -1 || doc_len == -1)
          throw new BadLocationException("Bad Location("
          + doc_pos + ", " + doc_len + ")", doc_pos);

        startElem = htmlDoc.getCharacterElement(doc_pos);

        int start_offset = startElem.getStartOffset();

        // Positions before start_offset will not be traversed, and thus
        // will not be counted.
        if (start_offset > 0)
          doc_offset_remaining = doc_offset_remaining - start_offset;

        Element tempParentElem = startElem;

        while ((tempParentElem = tempParentElem.getParentElement()) != null)
          {
            if (!htmlFragmentParentHashSet.contains(tempParentElem))
              htmlFragmentParentHashSet.add(tempParentElem);
          } // while((tempParentElem = tempParentElem.getParentElement())
            //   != null)

        // NOTE: 20061030 - fchoong - the last index should not be included.
        endElem = htmlDoc.getCharacterElement(doc_pos + doc_len - 1);

        tempParentElem = endElem;

        while ((tempParentElem = tempParentElem.getParentElement()) != null)
          {
            if (!htmlFragmentParentHashSet.contains(tempParentElem))
              htmlFragmentParentHashSet.add(tempParentElem);
          } // while((tempParentElem = tempParentElem.getParentElement())
            //   != null)

        traverseHtmlFragment(rootElem);

      } // else

    // NOTE: close out remaining open embeded tags.
    HTML.Tag[] tag_arr =
      openEmbeddedTagHashSet.toArray(new HTML.Tag[openEmbeddedTagHashSet.size()]);

    for (int i = 0; i < tag_arr.length; i++)
      {
        writeRaw("</" + tag_arr[i].toString() + ">");
      } // for(int i = 0; i < tag_arr.length; i++)

  } // public void write() throws IOException, BadLocationException

  /**
   * Writes all the attributes in the attrSet, except for attrbutes with
   * keys of <code>javax.swing.text.html.HTML.Tag</code>,
   * <code>javax.swing.text.StyleConstants</code> or
   * <code>javax.swing.text.html.HTML.Attribute.ENDTAG</code>.
   *
   * @param attrSet attrSet to write out
   *
   * @throws IOException on any I/O exceptions
   */
  protected void writeAttributes(AttributeSet attrSet)
    throws IOException
  {
    Enumeration<?> attrNameEnum = attrSet.getAttributeNames();

    while (attrNameEnum.hasMoreElements())
      {
        Object key = attrNameEnum.nextElement();
        Object value = attrSet.getAttribute(key);

        // HTML.Attribute.ENDTAG is an instance, not a class.
        if (!((key instanceof HTML.Tag) || (key instanceof StyleConstants)
          || (key == HTML.Attribute.ENDTAG)))
          {
            if (key == HTML.Attribute.SELECTED)
              writeRaw(" selected");
            else if (key == HTML.Attribute.CHECKED)
              writeRaw(" checked");
            else
              writeRaw(" " + key + "=\"" + value + "\"");
          } // if(!((key instanceof HTML.Tag) || (key instanceof
            //   StyleConstants) || (key == HTML.Attribute.ENDTAG)))
      } // while(attrNameEnum.hasMoreElements())

  } // protected void writeAttributes(AttributeSet attrSet) throws IOException

  /**
   * Writes out an empty tag. i.e. a tag without any child elements.
   *
   * @param paramElem the element to output as an empty tag
   *
   * @throws IOException on any I/O exceptions
   * @throws BadLocationException if a pos is not a valid position in the
   *                              html doc element
   */
  protected void emptyTag(Element paramElem)
    throws IOException, BadLocationException
  {
    String elem_name = paramElem.getName();
    AttributeSet attrSet = paramElem.getAttributes();

    writeRaw("<" + elem_name);
    writeAttributes(attrSet);
    writeRaw(">");

    if (isBlockTag(attrSet))
      {
        writeRaw("</" + elem_name + ">");
      } // if(isBlockTag(attrSet))

  } // protected void emptyTag(Element paramElem)
    //   throws IOException, BadLocationException

  /**
   * Determines if it is a block tag or not.
   *
   * @param attrSet the attrSet of the element
   *
   * @return <code>true</code> if it is a block tag
   *         <code>false</code> if it is a not block tag
   */
  protected boolean isBlockTag(AttributeSet attrSet)
  {
    return ((HTML.Tag)
      attrSet.getAttribute(StyleConstants.NameAttribute)).isBlock();
  } // protected boolean isBlockTag(AttributeSet attrSet)

  /**
   * Writes out a start tag. Synthesized elements are skipped.
   *
   * @param paramElem the element to output as a start tag
   * @throws IOException on any I/O exceptions
   * @throws BadLocationException if a pos is not a valid position in the
   *                              html doc element
   */
  protected void startTag(Element paramElem)
    throws IOException, BadLocationException
  {
    // NOTE: Sysnthesized elements do no call this method at all.
    String elem_name = paramElem.getName();
    AttributeSet attrSet = paramElem.getAttributes();

    indent();
    writeRaw("<" + elem_name);
    writeAttributes(attrSet);
    writeRaw(">");
    writeLineSeparator(); // Extra formatting to look more like the RI.
    incrIndent();

  } // protected void startTag(Element paramElem)
    //   throws IOException, BadLocationException

  /**
   * Writes out the contents of a textarea.
   *
   * @param attrSet the attrSet of the element to output as a text area
   * @throws IOException on any I/O exceptions
   * @throws BadLocationException if a pos is not a valid position in the
   *                              html doc element
   */
  protected void textAreaContent(AttributeSet attrSet)
    throws IOException, BadLocationException
  {
    writeLineSeparator(); // Extra formatting to look more like the RI.
    indent();
    writeRaw("<textarea");
    writeAttributes(attrSet);
    writeRaw(">");

    Document tempDocument =
      (Document) attrSet.getAttribute(StyleConstants.ModelAttribute);

    writeRaw(tempDocument.getText(0, tempDocument.getLength()));
    indent();
    writeRaw("</textarea>");

  } // protected void textAreaContent(AttributeSet attrSet)
    //   throws IOException, BadLocationException

  /**
   * Writes out text, within the appropriate range if it is specified.
   *
   * @param paramElem the element to output as a text
   * @throws IOException on any I/O exceptions
   * @throws BadLocationException if a pos is not a valid position in the
   *                              html doc element
   */
  protected void text(Element paramElem)
    throws IOException, BadLocationException
  {
    int offset =  paramElem.getStartOffset();
    int len =  paramElem.getEndOffset() -  paramElem.getStartOffset();
    String txt_value = htmlDoc.getText(offset, len);

    writeContent(txt_value);

  } // protected void text(Element paramElem)
    //   throws IOException, BadLocationException

  /**
   * Writes out the contents of a select element.
   *
   * @param attrSet the attrSet of the element to output as a select box
   *
   * @throws IOException on any I/O exceptions
   */
  protected void selectContent(AttributeSet attrSet)
    throws IOException
  {
    writeLineSeparator(); // Extra formatting to look more like the RI.
    indent();
    writeRaw("<select");
    writeAttributes(attrSet);
    writeRaw(">");
    incrIndent();
    writeLineSeparator(); // extra formatting to look more like the RI.

    ComboBoxModel comboBoxModel =
      (ComboBoxModel) attrSet.getAttribute(StyleConstants.ModelAttribute);

    for (int i = 0; i < comboBoxModel.getSize(); i++)
      {
        writeOption((Option) comboBoxModel.getElementAt(i));
      } // for(int i = 0; i < comboBoxModel.getSize(); i++)

    decrIndent();
    indent();
    writeRaw("</select>");

  } // protected void selectContent(AttributeSet attrSet) throws IOException

  /**
   * Writes out the contents of an option element.
   *
   * @param option the option object to output as a select option
   *
   * @throws IOException on any I/O exceptions
   */
  protected void writeOption(Option option)
    throws IOException
  {
    indent();
    writeRaw("<option");
    writeAttributes(option.getAttributes());
    writeRaw(">");

    writeContent(option.getLabel());

    writeRaw("</option>");
    writeLineSeparator(); // extra formatting to look more like the RI.

  } // protected void writeOption(Option option) throws IOException

  /**
   * Writes out an end tag.
   *
   * @param paramElem the element to output as an end tag
   *
   * @throws IOException on any I/O exceptions
   */
  protected void endTag(Element paramElem)
    throws IOException
  {
    String elem_name = paramElem.getName();

    //writeLineSeparator(); // Extra formatting to look more like the RI.
    decrIndent();
    indent();
    writeRaw("</" + elem_name + ">");
    writeLineSeparator(); // Extra formatting to look more like the RI.

  } // protected void endTag(Element paramElem) throws IOException

  /**
   * Writes out the comment.
   *
   * @param paramElem the element to output as a comment
   */
  protected void comment(Element paramElem)
    throws IOException, BadLocationException
  {
    AttributeSet attrSet = paramElem.getAttributes();

    String comment_str = (String) attrSet.getAttribute(HTML.Attribute.COMMENT);

    writeRaw("<!--" + comment_str + "-->");

  } // protected void comment(Element paramElem)
    //   throws IOException, BadLocationException

  /**
   * Determines if element is a synthesized
   * <code>javax.swing.text.Element</code> or not.
   *
   * @param element the element to test
   *
   * @return <code>true</code> if it is a synthesized element,
   *         <code>false</code> if it is a not synthesized element
   */
  protected boolean synthesizedElement(Element element)
  {
    AttributeSet attrSet = element.getAttributes();
    Object tagType = attrSet.getAttribute(StyleConstants.NameAttribute);

    if (tagType == HTML.Tag.CONTENT || tagType == HTML.Tag.COMMENT
        || tagType == HTML.Tag.IMPLIED)
      return true;
    else
      return false;
  } // protected boolean synthesizedElement(Element element)

  /**
   * Determines if
   * <code>javax.swing.text.StyleConstants.NameAttribute</code>
   * matches tag or not.
   *
   * @param attrSet the <code>javax.swing.text.AttributeSet</code> of
   *        element to be matched
   * @param tag the HTML.Tag to match
   *
   * @return <code>true</code> if it matches,
   *         <code>false</code> if it does not match
   */
  protected boolean matchNameAttribute(AttributeSet attrSet, HTML.Tag tag)
  {
    Object tagType = attrSet.getAttribute(StyleConstants.NameAttribute);

    if (tagType == tag)
      return true;
    else
      return false;
  } // protected boolean matchNameAttribute(AttributeSet attrSet,
    //   HTML.Tag tag)

  /**
   * Writes out an embedded tag. The tags not already in
   * openEmbededTagHashSet will written out.
   *
   * @param attrSet the <code>javax.swing.text.AttributeSet</code> of
   *        the element to write out
   *
   * @throws IOException on any I/O exceptions
   */
  protected void writeEmbeddedTags(AttributeSet attrSet)
    throws IOException
  {
    Enumeration<?> attrNameEnum = attrSet.getAttributeNames();

    while (attrNameEnum.hasMoreElements())
      {
        Object key = attrNameEnum.nextElement();
        Object value = attrSet.getAttribute(key);

        if (key instanceof HTML.Tag)
          {
            if (!openEmbeddedTagHashSet.contains(key))
              {
                writeRaw("<" + key);
                writeAttributes((AttributeSet) value);
                writeRaw(">");
                openEmbeddedTagHashSet.add((HTML.Tag) key);
              } // if(!openEmbededTagHashSet.contains(key))
          } // if(key instanceof HTML.Tag)
      } // while(attrNameEnum.hasMoreElements())

  } // protected void writeEmbeddedTags(AttributeSet attrSet)
    //   throws IOException

  /**
   * Closes out an unwanted embedded tag. The tags from the
   *  openEmbededTagHashSet not found in attrSet will be written out.
   *
   *  @param attrSet the AttributeSet of the element to write out
   *
   *  @throws IOException on any I/O exceptions
   */
  protected void closeOutUnwantedEmbeddedTags(AttributeSet attrSet)
    throws IOException
  {
    HTML.Tag[] tag_arr =
      openEmbeddedTagHashSet.toArray(new HTML.Tag[openEmbeddedTagHashSet.size()]);

    for (int i = 0; i < tag_arr.length; i++)
      {
        HTML.Tag key = tag_arr[i];

        if (!attrSet.isDefined(key))
          {
            writeRaw("</" + key.toString() + ">");
            openEmbeddedTagHashSet.remove(key);
          } // if(!attrSet.isDefined(key))
      } // for(int i = 0; i < tag_arr.length; i++)

  } // protected void closeOutUnwantedEmbeddedTags(AttributeSet attrSet)
    //   throws IOException

  /**
   * Writes out a line separator. Overwrites the parent to write out a new
   * line.
   *
   * @throws IOException on any I/O exceptions.
   */
  protected void writeLineSeparator()
    throws IOException
  {
    writeRaw(new_line_str);
  } // protected void writeLineSeparator() throws IOException

  /**
   * Write to the writer. Character entites such as &lt;, &gt;
   * are escaped appropriately.
   *
   * @param chars char array to write out
   * @param off offset
   * @param len length
   *
   * @throws IOException on any I/O exceptions
   */
  protected void output(char[] chars, int off, int len)
   throws IOException
  {
    CPStringBuilder strBuffer = new CPStringBuilder();

    for (int i = 0; i < chars.length; i++)
      {
        if (isCharHtmlEntity(chars[i]))
          strBuffer.append(escapeCharHtmlEntity(chars[i]));
        else
          strBuffer.append(chars[i]);
      } // for(int i = 0; i < chars.length; i++)

    writeRaw(strBuffer.toString());

  } // protected void output(char[] chars, int off, int len)
    //   throws IOException

  //-------------------------------------------------------------------------
  // private methods

  /**
   * The main method used to traverse through the elements.
   *
   * @param paramElem element to traverse
   *
   * @throws IOException on any I/O exceptions
   */
  private void traverse(Element paramElem)
    throws IOException, BadLocationException
  {
    Element currElem = paramElem;

    AttributeSet attrSet = currElem.getAttributes();

    closeOutUnwantedEmbeddedTags(attrSet);

    // handle the tag
    if (synthesizedElement(paramElem))
      {
        if (matchNameAttribute(attrSet, HTML.Tag.CONTENT))
          {
            writeEmbeddedTags(attrSet);
            text(currElem);
          } // if(matchNameAttribute(attrSet, HTML.Tag.CONTENT))
        else if (matchNameAttribute(attrSet, HTML.Tag.COMMENT))
          {
            comment(currElem);
          } // else if(matchNameAttribute(attrSet, HTML.Tag.COMMENT))
        else if (matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
          {
            int child_elem_count = currElem.getElementCount();

            if (child_elem_count > 0)
              {
                for (int i = 0; i < child_elem_count; i++)
                  {
                    Element childElem = paramElem.getElement(i);

                    traverse(childElem);

                  } // for(int i = 0; i < child_elem_count; i++)
              } // if(child_elem_count > 0)
          } // else if(matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
      } // if(synthesizedElement(paramElem))
    else
      {
        // NOTE: 20061030 - fchoong - title is treated specially here.
        // based on RI behavior.
        if (matchNameAttribute(attrSet, HTML.Tag.TITLE))
          {
            boolean fg_is_end_tag = false;
            Enumeration<?> attrNameEnum = attrSet.getAttributeNames();

            while (attrNameEnum.hasMoreElements())
              {
                Object key = attrNameEnum.nextElement();
                Object value = attrSet.getAttribute(key);

                if (key == HTML.Attribute.ENDTAG && value.equals("true"))
                  fg_is_end_tag = true;
              } // while(attrNameEnum.hasMoreElements())

            if (fg_is_end_tag)
              writeRaw("</title>");
            else
              {
                indent();
                writeRaw("<title>");

                String title_str =
                  (String) htmlDoc.getProperty(HTMLDocument.TitleProperty);

                if (title_str != null)
                  writeContent(title_str);

              } // else
          } // if(matchNameAttribute(attrSet, HTML.Tag.TITLE))
        else if (matchNameAttribute(attrSet, HTML.Tag.PRE))
          {
            // We pursue more stringent formating here.
            attrSet = paramElem.getAttributes();

            indent();
            writeRaw("<pre");
            writeAttributes(attrSet);
            writeRaw(">");

            int child_elem_count = currElem.getElementCount();

            for (int i = 0; i < child_elem_count; i++)
              {
                Element childElem = paramElem.getElement(i);

                traverse(childElem);

              } // for(int i = 0; i < child_elem_count; i++)

            writeRaw("</pre>");

          } // else if(matchNameAttribute(attrSet, HTML.Tag.PRE))
        else if (matchNameAttribute(attrSet, HTML.Tag.SELECT))
          {
            selectContent(attrSet);
          } // else if(matchNameAttribute(attrSet, HTML.Tag.SELECT))
        else if (matchNameAttribute(attrSet, HTML.Tag.TEXTAREA))
          {
            textAreaContent(attrSet);
          } // else if(matchNameAttribute(attrSet, HTML.Tag.TEXTAREA))
        else
          {
            int child_elem_count = currElem.getElementCount();

            if (child_elem_count > 0)
              {
                startTag(currElem);

                for (int i = 0; i < child_elem_count; i++)
                  {
                    Element childElem = paramElem.getElement(i);

                    traverse(childElem);

                  } // for(int i = 0; i < child_elem_count; i++)

                  endTag(currElem);

              } // if(child_elem_count > 0)
            else
              {
                emptyTag(currElem);
              } // else
            } // else
          } // else

  } // private void traverse(Element paramElem)
    //   throws IOException, BadLocationException

  /**
   * The method used to traverse through a html fragment.
   *
   * @param paramElem element to traverse
   *
   * @throws IOException on any I/O exceptions
   */
  private void traverseHtmlFragment(Element paramElem)
    throws IOException, BadLocationException
  {
    // NOTE: This method is similar to traverse(Element paramElem)
    Element currElem = paramElem;

    boolean fg_is_fragment_parent_elem = false;
    boolean fg_is_start_and_end_elem = false;

    if (htmlFragmentParentHashSet.contains(paramElem))
      fg_is_fragment_parent_elem = true;

    if (paramElem == startElem)
      fg_pass_start_elem = true;

    if (paramElem == startElem && paramElem == endElem)
      fg_is_start_and_end_elem = true;

    AttributeSet attrSet = currElem.getAttributes();

    closeOutUnwantedEmbeddedTags(attrSet);

    if (fg_is_fragment_parent_elem || (fg_pass_start_elem
        && fg_pass_end_elem == false) || fg_is_start_and_end_elem)
    {
      // handle the tag
      if (synthesizedElement(paramElem))
        {
          if (matchNameAttribute(attrSet, HTML.Tag.CONTENT))
            {
              writeEmbeddedTags(attrSet);

              int content_offset =  paramElem.getStartOffset();
              int content_length = currElem.getEndOffset() - content_offset;

              if (doc_offset_remaining > 0)
                {
                  if (content_length > doc_offset_remaining)
                    {
                      int split_len = content_length;

                      split_len = split_len - doc_offset_remaining;

                      if (split_len > doc_len_remaining)
                        split_len = doc_len_remaining;

                      // we need to split it.
                      String txt_value = htmlDoc.getText(content_offset
                        + doc_offset_remaining, split_len);

                      writeContent(txt_value);

                      doc_offset_remaining = 0; // the offset is used up.
                      doc_len_remaining = doc_len_remaining - split_len;
                    } // if(content_length > doc_offset_remaining)
                  else
                    {
                      // doc_offset_remaining is greater than the entire
                      //   length of content
                      doc_offset_remaining = doc_offset_remaining
                        - content_length;
                    }  // else
                } // if(doc_offset_remaining > 0)
              else if (content_length <= doc_len_remaining)
                {
                  // we can fit the entire content.
                  text(currElem);
                  doc_len_remaining = doc_len_remaining - content_length;
                } // else if(content_length <= doc_len_remaining)
              else
                {
                  // we need to split it.
                  String txt_value = htmlDoc.getText(content_offset,
                    doc_len_remaining);

                  writeContent(txt_value);

                  doc_len_remaining = 0;
                } // else

            } // if(matchNameAttribute(attrSet, HTML.Tag.CONTENT))
          else if (matchNameAttribute(attrSet, HTML.Tag.COMMENT))
            {
              comment(currElem);
            } // else if(matchNameAttribute(attrSet, HTML.Tag.COMMENT))
          else if (matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
            {
              int child_elem_count = currElem.getElementCount();

              if (child_elem_count > 0)
                {
                  for (int i = 0; i < child_elem_count; i++)
                    {
                      Element childElem = paramElem.getElement(i);

                      traverseHtmlFragment(childElem);

                    } // for(int i = 0; i < child_elem_count; i++)
                } // if(child_elem_count > 0)
            } // else if(matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
        } // if(synthesizedElement(paramElem))
      else
        {
            // NOTE: 20061030 - fchoong - the isLeaf() condition seems to
            // generate the closest behavior to the RI.
            if (paramElem.isLeaf())
              {
                if (doc_offset_remaining > 0)
                  {
                    doc_offset_remaining--;
                  } // if(doc_offset_remaining > 0)
                else if (doc_len_remaining > 0)
                  {
                    doc_len_remaining--;
                  } // else if(doc_len_remaining > 0)
              } // if(paramElem.isLeaf())

          // NOTE: 20061030 - fchoong - title is treated specially here.
          // based on RI behavior.
          if (matchNameAttribute(attrSet, HTML.Tag.TITLE))
            {
              boolean fg_is_end_tag = false;
              Enumeration<?> attrNameEnum = attrSet.getAttributeNames();

              while (attrNameEnum.hasMoreElements())
                {
                  Object key = attrNameEnum.nextElement();
                  Object value = attrSet.getAttribute(key);

                  if (key == HTML.Attribute.ENDTAG && value.equals("true"))
                    fg_is_end_tag = true;
                } // while(attrNameEnum.hasMoreElements())

              if (fg_is_end_tag)
                writeRaw("</title>");
              else
                {
                  indent();
                  writeRaw("<title>");

                  String title_str =
                    (String) htmlDoc.getProperty(HTMLDocument.TitleProperty);

                  if (title_str != null)
                    writeContent(title_str);

                } // else
            } // if(matchNameAttribute(attrSet, HTML.Tag.TITLE))
          else if (matchNameAttribute(attrSet, HTML.Tag.PRE))
            {
              // We pursue more stringent formating here.
              attrSet = paramElem.getAttributes();

              indent();
              writeRaw("<pre");
              writeAttributes(attrSet);
              writeRaw(">");

              int child_elem_count = currElem.getElementCount();

              for (int i = 0; i < child_elem_count; i++)
                {
                  Element childElem = paramElem.getElement(i);

                  traverseHtmlFragment(childElem);

                } // for(int i = 0; i < child_elem_count; i++)

              writeRaw("</pre>");

            } // else if(matchNameAttribute(attrSet, HTML.Tag.PRE))
          else if (matchNameAttribute(attrSet, HTML.Tag.SELECT))
            {
              selectContent(attrSet);
            } // else if(matchNameAttribute(attrSet, HTML.Tag.SELECT))
          else if (matchNameAttribute(attrSet, HTML.Tag.TEXTAREA))
            {
              textAreaContent(attrSet);
            } // else if(matchNameAttribute(attrSet, HTML.Tag.TEXTAREA))
          else
            {
              int child_elem_count = currElem.getElementCount();

              if (child_elem_count > 0)
                {
                  startTag(currElem);

                  for (int i = 0; i < child_elem_count; i++)
                    {
                      Element childElem = paramElem.getElement(i);

                      traverseHtmlFragment(childElem);

                    } // for(int i = 0; i < child_elem_count; i++)

                    endTag(currElem);

                } // if(child_elem_count > 0)
              else
                {
                  emptyTag(currElem);
                } // else
            } // else
        } // else

    } // if(fg_is_fragment_parent_elem || (fg_pass_start_elem
      //   && fg_pass_end_elem == false) || fg_is_start_and_end_elem)

    if (paramElem == endElem)
      fg_pass_end_elem = true;

  } // private void traverseHtmlFragment(Element paramElem)
    //   throws IOException, BadLocationException

  /**
   * Write to the writer without any modifications.
   *
   * @param param_str the str to write out
   *
   * @throws IOException on any I/O exceptions
   */
  private void writeRaw(String param_str)
    throws IOException
  {
    super.output(param_str.toCharArray(), 0, param_str.length());
  } // private void writeRaw(char[] chars, int off, int len)
    //   throws IOException

  /**
   * Write to the writer, escaping HTML character entitie where neccessary.
   *
   * @param param_str the str to write out
   *
   * @throws IOException on any I/O exceptions
   */
  private void writeContent(String param_str)
    throws IOException
  {
    char[] str_char_arr = param_str.toCharArray();

    if (hasHtmlEntity(param_str))
      output(str_char_arr, 0, str_char_arr.length);
    else
      super.output(str_char_arr, 0, str_char_arr.length);

  } // private void writeContent(String param_str) throws IOException

  /**
   * Use this for debugging. Writes out all attributes regardless of type.
   *
   * @param attrSet the <code>javax.swing.text.AttributeSet</code> to
   *        write out
   *
   * @throws IOException on any I/O exceptions
   */
  private void writeAllAttributes(AttributeSet attrSet)
    throws IOException
  {
    Enumeration<?> attrNameEnum = attrSet.getAttributeNames();

    while (attrNameEnum.hasMoreElements())
      {
        Object key = attrNameEnum.nextElement();
        Object value = attrSet.getAttribute(key);

        writeRaw(" " + key + "=\"" + value + "\"");
        writeRaw(" " + key.getClass().toString() + "=\""
          + value.getClass().toString() + "\"");
      } // while(attrNameEnum.hasMoreElements())

  } // private void writeAllAttributes(AttributeSet attrSet)
    //   throws IOException

  /**
   * Tests if the str contains any html entities.
   *
   * @param param_str the str to test
   *
   * @return <code>true</code> if it has a html entity
   *         <code>false</code> if it does not have a html entity
   */
  private boolean hasHtmlEntity(String param_str)
  {
    boolean ret_bool = false;

    for (int i = 0; i < html_entity_char_arr.length; i++)
      {
        if (param_str.indexOf(html_entity_char_arr[i]) != -1)
          {
            ret_bool = true;
            break;
          } // if(param_str.indexOf(html_entity_char_arr[i]) != -1)
      } // for(int i = 0; i < html_entity_char_arr.length; i++)

    return ret_bool;
  } // private boolean hasHtmlEntity(String param_str)

  /**
   * Tests if the char is a html entities.
   *
   * @param param_char the char to test
   *
   * @return <code>true</code> if it is a html entity
   *         <code>false</code> if it is not a html entity.
   */
  private boolean isCharHtmlEntity(char param_char)
  {
    boolean ret_bool = false;

    for (int i = 0; i < html_entity_char_arr.length; i++)
      {
        if (param_char == html_entity_char_arr[i])
          {
            ret_bool = true;
            break;
          } // if(param_char == html_entity_char_arr[i])
      } // for(int i = 0; i < html_entity_char_arr.length; i++)

      return ret_bool;
  } // private boolean hasHtmlEntity(String param_str)

  /**
   * Escape html entities.
   *
   * @param param_char the char to escape
   *
   * @return escaped html entity. Original char is returned as a str if is
   *         is not a html entity
   */
  private String escapeCharHtmlEntity(char param_char)
  {
    String ret_str = "" + param_char;

    for (int i = 0; i < html_entity_char_arr.length; i++)
      {
        if (param_char == html_entity_char_arr[i])
          {
            ret_str = html_entity_escape_str_arr[i];
            break;
          } // if(param_char == html_entity_char_arr[i])
      } // for(int i = 0; i < html_entity_char_arr.length; i++)

      return ret_str;
  } // private String escapeCharHtmlEntity(char param_char)

} // public class HTMLWriter extends AbstractWriter
