This fixes the handling if implied paragraph tags in HTMLDocument. The
problem is that (in Swing) content is not allowed to be directly in
block-like tags (like body or td), but instead must be embedded in a
p-implied tag. Audrius tried something similar by creating a
HTML_401Swing DTD, but that was not really a solution as it only applied
for the body tag. I pulled that handling into the HTMLDocument class and
removed that special DTD. That's good because so the parser doesn't need
to care about Swing's special requirements.

I also removed one big performance hole in HTMLDocument, which was the
printBuffer() and print() debug methods. These methods created loads and
loads of strings, only to discard them right away. I scrabbed them.

2006-11-08  Roman Kennke  <[EMAIL PROTECTED]>

        * javax/swing/text/html/HTMLEditorKit.java
        (getParser): Use plain HTML_401F DTD.
        * javax/swing/text/html/HTMLDocument.java
        (HTMLReader.print): Removed method and all calls to it.
        (HTMLReader.printBuffer): Removed method and all calls to it.
        (HTMLReader.inImpliedParagraph): New field.
        (HTMLReader.inParagraph): New field.
        (HTMLReader.addContent): Create implied p-tag if necessary.
        (HTMLReader.addSpecialElement): Create implied p-tag if necessary.
        (HTMLReader.blockClose): Close implied p-tag if necessary.
        (HTMLReader.blockOpen): Close implied p-tag if necessary.
        * gnu/javax/swing/text/html/parser/HTML_401Swing.java: Removed.

/Roman

Index: gnu/javax/swing/text/html/parser/HTML_401Swing.java
===================================================================
RCS file: gnu/javax/swing/text/html/parser/HTML_401Swing.java
diff -N gnu/javax/swing/text/html/parser/HTML_401Swing.java
--- gnu/javax/swing/text/html/parser/HTML_401Swing.java	16 Jul 2006 18:25:53 -0000	1.2
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,91 +0,0 @@
-/* HTML_401Swing.java -- The HTML 4.01 DTD, adapted for HTML rendering in Swing
-   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 gnu.javax.swing.text.html.parser;
-
-import javax.swing.text.html.parser.DTD;
-
-/**
- * This class is necessary because the current implementation of the GNU
- * Classpath Swing requires always enclose the text into paragraphs.
- * 
- * @author Audrius Meskauskas ([EMAIL PROTECTED])
- */
-public class HTML_401Swing extends HTML_401F
-{
-  /**
-   * The singleton instance;
-   */
-  final static HTML_401Swing singleton = new HTML_401Swing();
-  
-  /**
-   * Either takes the document (by name) from DTD table, or
-   * creates a new instance and registers it in the tabe.
-   * The document is registerd under name "-//W3C//DTD HTML 4.01 Frameset//EN".
-   * @return The new or existing DTD for parsing HTML 4.01 Frameset.
-   */
-  public static DTD getInstance()
-  {
-    return singleton;
-  }  
-  
-  /**
-   * Get elements that are allowed in the document body, at the zero level.
-   * This list disallows the text at this level (the implied P tag will be
-   * generated). It also disallows A, B, I, U, CITE and other similar
-   * elements that have the plain text inside. They will also be placed
-   * inside the generated implied P tags.
-   */
-  protected String[] getBodyElements()
-  {
-    return new String[] {
-        APPLET, BASEFONT,
-        BR, BUTTON, 
-        IFRAME, IMG,
-        INPUT, LABEL, MAP, OBJECT,
-        SCRIPT, SELECT,
-        TEXTAREA, 
-        BLOCKQUOTE, CENTER, DEL, DIR,
-        DIV, DL, FIELDSET, FORM, H1,
-        H2, H3, H4, H5, H6,
-        HR, INS, ISINDEX, MENU, NOFRAMES,
-        NOSCRIPT, OL, P, PRE, TABLE,
-        UL
-      };
-  }
-}
Index: javax/swing/text/html/HTMLDocument.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/HTMLDocument.java,v
retrieving revision 1.47
diff -u -1 -5 -r1.47 HTMLDocument.java
--- javax/swing/text/html/HTMLDocument.java	6 Nov 2006 20:28:55 -0000	1.47
+++ javax/swing/text/html/HTMLDocument.java	8 Nov 2006 11:20:45 -0000
@@ -558,65 +558,69 @@
     /**
      * This variable becomes true after the insert tag has been encountered.
      */
     boolean insertTagEncountered;
 
     
     /** A temporary variable that helps with the printing out of debug information **/
     boolean debug = false;
 
     /**
      * This is true when we are inside a pre tag.
      */
     boolean inPreTag = false;
 
     /**
+     * True when we are inside a paragraph (P, H1-H6, P-IMPLIED).
+     */
+    boolean inParagraph = false;
+
+    /**
+     * True when we are currently inside an implied paragraph.
+     */
+    boolean inImpliedParagraph = false;
+
+    /**
      * This is true when we are inside a style tag. This will add text
      * content inside this style tag beeing parsed as CSS.
      *
      * This is package private to avoid accessor methods.
      */
     boolean inStyleTag = false;
 
     /**
      * This is true when we are inside a &lt;textarea&gt; tag. Any text
      * content will then be added to the text area.
      *
      * This is package private to avoid accessor methods.
      */
     boolean inTextArea = false;
 
     /**
      * This contains all stylesheets that are somehow read, either
      * via embedded style tags, or via linked stylesheets. The
      * elements will be String objects containing a stylesheet each.
      */
     ArrayList styles;
 
     /**
      * The document model for a textarea.
      *
      * This is package private to avoid accessor methods.
      */
     Document textAreaDocument;
 
-    void print (String line)
-    {
-      if (debug)
-        System.out.println (line);
-    }
-    
     public class TagAction
     {
       /**
        * This method is called when a start tag is seen for one of the types
        * of tags associated with this Action.  By default this does nothing.
        */
       public void start(HTML.Tag t, MutableAttributeSet a)
       {
         // Nothing to do here.
       }
       
       /**
        * Called when an end tag is seen for one of the types of tags associated
        * with this Action.  By default does nothing.
        */
@@ -800,39 +804,41 @@
         blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
         addSpecialElement(t, a);
         blockClose(HTML.Tag.IMPLIED);
       }
     }
     
     public class ParagraphAction extends BlockAction
     {
       /**
        * This method is called when a start tag is seen for one of the types
        * of tags associated with this Action.
        */
       public void start(HTML.Tag t, MutableAttributeSet a)
       {
         blockOpen(t, a);
+        inParagraph = true;
       }
       
       /**
        * Called when an end tag is seen for one of the types of tags associated
        * with this Action.
        */
       public void end(HTML.Tag t)
       {
         blockClose(t);
+        inParagraph = false;
       } 
     }
 
     /**
      * This action is performed when a &lt;pre&gt; tag is parsed.
      */
     public class PreAction extends BlockAction
     {
       /**
        * This method is called when a start tag is seen for one of the types
        * of tags associated with this Action.
        */
       public void start(HTML.Tag t, MutableAttributeSet a)
       {
         inPreTag = true;
@@ -869,42 +875,40 @@
       {
         addSpecialElement(t, a);
       }
     }
     
     class AreaAction extends TagAction
     {
       /**
        * This method is called when a start tag is seen for one of the types
        * of tags associated with this Action.
        */
       public void start(HTML.Tag t, MutableAttributeSet a)
         throws NotImplementedException
       {
         // FIXME: Implement.
-        print ("AreaAction.start not implemented");
       }
       
       /**
        * Called when an end tag is seen for one of the types of tags associated
        * with this Action.
        */
       public void end(HTML.Tag t)
         throws NotImplementedException
       {
         // FIXME: Implement.
-        print ("AreaAction.end not implemented");
       } 
     }
 
     /**
      * Converts HTML tags to CSS attributes.
      */
     class ConvertAction
       extends TagAction
     {
 
       public void start(HTML.Tag tag, MutableAttributeSet atts)
       {
         pushCharacterStyle();
         charAttr.addAttribute(tag, atts.copyAttributes());
         StyleSheet styleSheet = getStyleSheet();
@@ -929,56 +933,53 @@
       {
         popCharacterStyle();
       }
     }
 
     class BaseAction extends TagAction
     {
       /**
        * This method is called when a start tag is seen for one of the types
        * of tags associated with this Action.
        */
       public void start(HTML.Tag t, MutableAttributeSet a)
         throws NotImplementedException
       {
         // FIXME: Implement.
-        print ("BaseAction.start not implemented");
       }
       
       /**
        * Called when an end tag is seen for one of the types of tags associated
        * with this Action.
        */
       public void end(HTML.Tag t)
         throws NotImplementedException
       {
         // FIXME: Implement.
-        print ("BaseAction.end not implemented");
       } 
     }
     
     class HeadAction extends BlockAction
     {
       /**
        * This method is called when a start tag is seen for one of the types
        * of tags associated with this Action.
        */
       public void start(HTML.Tag t, MutableAttributeSet a)
         throws NotImplementedException
       {
         // FIXME: Implement.
-        print ("HeadAction.start not implemented: "+t);
         super.start(t, a);
       }
       
       /**
        * Called when an end tag is seen for one of the types of tags associated
        * with this Action.
        */
       public void end(HTML.Tag t)
       {
         // We read in all the stylesheets that are embedded or referenced
         // inside the header.
         if (styles != null)
           {
             int numStyles = styles.size();
             for (int i = 0; i < numStyles; i++)
@@ -989,92 +990,86 @@
           }
         super.end(t);
       }
     }
     
     class LinkAction extends TagAction
     {
       /**
        * This method is called when a start tag is seen for one of the types
        * of tags associated with this Action.
        */
       public void start(HTML.Tag t, MutableAttributeSet a)
         throws NotImplementedException
       {
         // FIXME: Implement.
-        print ("LinkAction.start not implemented");
       }
       
       /**
        * Called when an end tag is seen for one of the types of tags associated
        * with this Action.
        */
       public void end(HTML.Tag t)
         throws NotImplementedException
       {
         // FIXME: Implement.
-        print ("LinkAction.end not implemented");
       } 
     }
     
     class MapAction extends TagAction
     {
       /**
        * This method is called when a start tag is seen for one of the types
        * of tags associated with this Action.
        */
       public void start(HTML.Tag t, MutableAttributeSet a)
         throws NotImplementedException
       {
         // FIXME: Implement.
-        print ("MapAction.start not implemented");
       }
       
       /**
        * Called when an end tag is seen for one of the types of tags associated
        * with this Action.
        */
       public void end(HTML.Tag t)
         throws NotImplementedException
       {
         // FIXME: Implement.
-        print ("MapAction.end not implemented");
       } 
     }
     
     class MetaAction extends TagAction
     {
       /**
        * This method is called when a start tag is seen for one of the types
        * of tags associated with this Action.
        */
       public void start(HTML.Tag t, MutableAttributeSet a)
         throws NotImplementedException
       {
         // FIXME: Implement.
-        print ("MetaAction.start not implemented");
       }
       
       /**
        * Called when an end tag is seen for one of the types of tags associated
        * with this Action.
        */
       public void end(HTML.Tag t)
         throws NotImplementedException
       {
         // FIXME: Implement.
-        print ("MetaAction.end not implemented");
       } 
     }
 
     class StyleAction extends TagAction
     {
       /**
        * This method is called when a start tag is seen for one of the types
        * of tags associated with this Action.
        */
       public void start(HTML.Tag t, MutableAttributeSet a)
       {
         inStyleTag = true;
       }
       
       /**
@@ -1085,56 +1080,51 @@
       {
         inStyleTag = false;
       } 
     }
     
     class TitleAction extends TagAction
     {
       /**
        * This method is called when a start tag is seen for one of the types
        * of tags associated with this Action.
        */
       public void start(HTML.Tag t, MutableAttributeSet a)
         throws NotImplementedException
       {
         // FIXME: Implement.
-        print ("TitleAction.start not implemented");
       }
       
       /**
        * Called when an end tag is seen for one of the types of tags associated
        * with this Action.
        */
       public void end(HTML.Tag t)
         throws NotImplementedException
       {
         // FIXME: Implement.
-        print ("TitleAction.end not implemented");
       } 
     }    
     
     public HTMLReader(int offset)
     {
       this (offset, 0, 0, null);
     }
     
     public HTMLReader(int offset, int popDepth, int pushDepth,
                       HTML.Tag insertTag)
     {
-      print ("HTMLReader created with pop: "+popDepth
-                          + " push: "+pushDepth + " offset: "+offset
-                          + " tag: "+insertTag);
       this.insertTag = insertTag;
       this.offset = offset;
       this.popDepth = popDepth;
       this.pushDepth = pushDepth;
       initTags();
     }
     
     void initTags()
     {
       tagToAction = new HashMap(72);
       CharacterAction characterAction = new CharacterAction();
       HiddenAction hiddenAction = new HiddenAction();
       AreaAction areaAction = new AreaAction();
       BaseAction baseAction = new BaseAction();
       BlockAction blockAction = new BlockAction();
@@ -1400,31 +1390,30 @@
             }
         }
     }
     
     /**
      * This is invoked after the stream has been parsed but before it has been
      * flushed.
      * 
      * @param eol one of \n, \r, or \r\n, whichever was encountered the most in 
      * parsing the stream
      * @since 1.3
      */
     public void handleEndOfLineString(String eol)
     {
       // FIXME: Implement.
-      print ("HTMLReader.handleEndOfLineString not implemented yet");
     }
     
     /**
      * Adds the given text to the textarea document.  Called only when we are
      * within a textarea.  
      * 
      * @param data the text to add to the textarea
      */
     protected void textAreaContent(char[] data)
     {
       try
         {
           int offset = textAreaDocument.getLength();
           textAreaDocument.insertString(offset, new String(data), null);
         }
@@ -1461,166 +1450,178 @@
         {
           // Add remaining last line.
           addContent(data, start, data.length - start);
         }
     }
     
     /**
      * Instructs the parse buffer to create a block element with the given 
      * attributes.
      * 
      * @param t the tag that requires opening a new block
      * @param attr the attribute set for the new block
      */
     protected void blockOpen(HTML.Tag t, MutableAttributeSet attr)
     {
-      printBuffer();
+      if (inImpliedParagraph)
+        blockClose(HTML.Tag.IMPLIED);
+
       DefaultStyledDocument.ElementSpec element;
 
       parseStack.push(t);
       AbstractDocument.AttributeContext ctx = getAttributeContext();
       AttributeSet copy = attr.copyAttributes();
       copy = ctx.addAttribute(copy, StyleConstants.NameAttribute, t);
       element = new DefaultStyledDocument.ElementSpec(copy,
                                DefaultStyledDocument.ElementSpec.StartTagType);
       parseBuffer.addElement(element);
-      printBuffer();
     }
 
     /**
      * Instructs the parse buffer to close the block element associated with 
      * the given HTML.Tag
      * 
      * @param t the HTML.Tag that is closing its block
      */
     protected void blockClose(HTML.Tag t)
     {
-      printBuffer();
       DefaultStyledDocument.ElementSpec element;
 
+      if (inImpliedParagraph)
+        {
+          inImpliedParagraph = false;
+          inParagraph = false;
+          if (t != HTML.Tag.IMPLIED)
+            blockClose(HTML.Tag.IMPLIED);
+        }
+
       // If the previous tag is a start tag then we insert a synthetic
       // content tag.
       DefaultStyledDocument.ElementSpec prev;
       prev = (DefaultStyledDocument.ElementSpec)
 	      parseBuffer.get(parseBuffer.size() - 1);
       if (prev.getType() == DefaultStyledDocument.ElementSpec.StartTagType)
         {
           AbstractDocument.AttributeContext ctx = getAttributeContext();
           AttributeSet attributes = ctx.getEmptySet();
           attributes = ctx.addAttribute(attributes, StyleConstants.NameAttribute,
                                         HTML.Tag.CONTENT);
           element = new DefaultStyledDocument.ElementSpec(attributes,
 			  DefaultStyledDocument.ElementSpec.ContentType,
                                     new char[0], 0, 0);
           parseBuffer.add(element);
         }
 
       element = new DefaultStyledDocument.ElementSpec(null,
 				DefaultStyledDocument.ElementSpec.EndTagType);
       parseBuffer.addElement(element);
-      printBuffer();
       if (parseStack.size() > 0)
         parseStack.pop();
     }
     
     /**
      * Adds text to the appropriate context using the current character
      * attribute set.
      * 
      * @param data the text to add
      * @param offs the offset at which to add it
      * @param length the length of the text to add
      */
     protected void addContent(char[] data, int offs, int length)
     {
       addContent(data, offs, length, true);
     }
     
     /**
      * Adds text to the appropriate context using the current character
      * attribute set, and possibly generating an IMPLIED Tag if necessary.
      * 
      * @param data the text to add
      * @param offs the offset at which to add it
      * @param length the length of the text to add
      * @param generateImpliedPIfNecessary whether or not we should generate
      * an HTML.Tag.IMPLIED tag if necessary
      */
     protected void addContent(char[] data, int offs, int length,
                               boolean generateImpliedPIfNecessary)
     {
+      if (generateImpliedPIfNecessary && (! inParagraph) && (! inPreTag))
+        {
+          blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
+          inParagraph = true;
+          inImpliedParagraph = true;
+        }
+
       AbstractDocument.AttributeContext ctx = getAttributeContext();
       DefaultStyledDocument.ElementSpec element;
       AttributeSet attributes = null;
 
       // Copy the attribute set, don't use the same object because 
       // it may change
       if (charAttr != null)
         attributes = charAttr.copyAttributes();
       else
         attributes = ctx.getEmptySet();
       attributes = ctx.addAttribute(attributes, StyleConstants.NameAttribute,
                                     HTML.Tag.CONTENT);
       element = new DefaultStyledDocument.ElementSpec(attributes,
                                 DefaultStyledDocument.ElementSpec.ContentType,
                                 data, offs, length);
       
-      printBuffer();
       // Add the element to the buffer
       parseBuffer.addElement(element);
-      printBuffer();
 
       if (parseBuffer.size() > HTMLDocument.this.getTokenThreshold())
         {
           try
             {
               flush();
             }
           catch (BadLocationException ble)
             {
               // TODO: what to do here?
             }
         }
     }
     
     /**
      * Adds content that is specified in the attribute set.
      * 
      * @param t the HTML.Tag
      * @param a the attribute set specifying the special content
      */
     protected void addSpecialElement(HTML.Tag t, MutableAttributeSet a)
     {
+      if (t != HTML.Tag.FRAME && ! inParagraph && ! inImpliedParagraph)
+        {
+          blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
+          inParagraph = true;
+          inImpliedParagraph = true;
+        }
+
       a.addAttribute(StyleConstants.NameAttribute, t);
       
       // The two spaces are required because some special elements like HR
       // must be broken. At least two characters are needed to break into the
       // two parts.
       DefaultStyledDocument.ElementSpec spec =
         new DefaultStyledDocument.ElementSpec(a.copyAttributes(),
 	  DefaultStyledDocument.ElementSpec.ContentType, 
           new char[] {' ', ' '}, 0, 2 );
       parseBuffer.add(spec);
     }
     
-    void printBuffer()
-    {      
-      print ("\n*********BUFFER**********");
-      for (int i = 0; i < parseBuffer.size(); i ++)
-        print ("  "+parseBuffer.get(i));
-      print ("***************************");
-    }
   }
   
   /**
    * Gets the reader for the parser to use when loading the document with HTML. 
    * 
    * @param pos - the starting position
    * @return - the reader
    */
   public HTMLEditorKit.ParserCallback getReader(int pos)
   {
     return new HTMLReader(pos);
   }  
   
   /**
    * Gets the reader for the parser to use when loading the document with HTML. 
Index: javax/swing/text/html/HTMLEditorKit.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/HTMLEditorKit.java,v
retrieving revision 1.39
diff -u -1 -5 -r1.39 HTMLEditorKit.java
--- javax/swing/text/html/HTMLEditorKit.java	8 Nov 2006 11:09:31 -0000	1.39
+++ javax/swing/text/html/HTMLEditorKit.java	8 Nov 2006 11:20:45 -0000
@@ -70,31 +70,31 @@
 import javax.swing.text.Document;
 import javax.swing.text.EditorKit;
 import javax.swing.text.Element;
 import javax.swing.text.MutableAttributeSet;
 import javax.swing.text.StyleConstants;
 import javax.swing.text.StyledDocument;
 import javax.swing.text.StyledEditorKit;
 import javax.swing.text.TextAction;
 import javax.swing.text.View;
 import javax.swing.text.ViewFactory;
 import javax.swing.text.html.parser.ParserDelegator;
 
 /* Move these imports here after javax.swing.text.html to make it compile
    with jikes.  */
 import gnu.javax.swing.text.html.parser.GnuParserDelegator;
-import gnu.javax.swing.text.html.parser.HTML_401Swing;
+import gnu.javax.swing.text.html.parser.HTML_401F;
 
 /**
  * @author Lillian Angel (langel at redhat dot com)
  */
 public class HTMLEditorKit
   extends StyledEditorKit
   implements Serializable, Cloneable, Accessible
 {
   
   /**
    * Fires the hyperlink events on the associated component
    * when needed.
    */
   public static class LinkController
     extends MouseAdapter
@@ -959,31 +959,31 @@
     HTMLDocument document = new HTMLDocument(getStyleSheet());
     document.setParser(getParser());
     return document;
   }
 
   /**
    * Get the parser that this editor kit uses for reading HTML streams. This
    * method can be overridden to use the alternative parser.
    * 
    * @return the HTML parser (by default, [EMAIL PROTECTED] ParserDelegator}).
    */
   protected Parser getParser()
   {
     if (parser == null)
       {
-        parser = new GnuParserDelegator(HTML_401Swing.getInstance());
+        parser = new GnuParserDelegator(HTML_401F.getInstance());
       }
     return parser;
   }
   
   /**
    * Inserts HTML into an existing document.
    * 
    * @param doc - the Document to insert the HTML into.
    * @param offset - where to begin inserting the HTML.
    * @param html - the String to insert
    * @param popDepth - the number of ElementSpec.EndTagTypes 
    * to generate before inserting
    * @param pushDepth - the number of ElementSpec.StartTagTypes 
    * with a direction of ElementSpec.JoinNextDirection that 
    * should be generated before

Reply via email to