1 /* HTMLDocument.java --
2 Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax
.swing
.text
.html
;
43 import java
.io
.IOException
;
45 import java
.util
.HashMap
;
46 import java
.util
.Stack
;
47 import java
.util
.Vector
;
49 import javax
.swing
.event
.DocumentEvent
;
50 import javax
.swing
.event
.UndoableEditEvent
;
51 import javax
.swing
.text
.AbstractDocument
;
52 import javax
.swing
.text
.AttributeSet
;
53 import javax
.swing
.text
.BadLocationException
;
54 import javax
.swing
.text
.DefaultStyledDocument
;
55 import javax
.swing
.text
.Element
;
56 import javax
.swing
.text
.ElementIterator
;
57 import javax
.swing
.text
.GapContent
;
58 import javax
.swing
.text
.MutableAttributeSet
;
59 import javax
.swing
.text
.SimpleAttributeSet
;
60 import javax
.swing
.text
.StyleConstants
;
61 import javax
.swing
.text
.html
.HTML
.Tag
;
64 * TODO: Add more comments here
66 * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
67 * @author Anthony Balkissoon (abalkiss@redhat.com)
68 * @author Lillian Angel (langel@redhat.com)
70 public class HTMLDocument
extends DefaultStyledDocument
72 /** A key for document properies. The value for the key is
73 * a Vector of Strings of comments not found in the body.
75 public static final String AdditionalComments
= "AdditionalComments";
77 boolean preservesUnknownTags
= true;
78 int tokenThreshold
= Integer
.MAX_VALUE
;
79 HTMLEditorKit
.Parser parser
;
80 StyleSheet styleSheet
;
81 AbstractDocument
.Content content
;
84 * Constructs an HTML document using the default buffer size and a default
93 * Constructs an HTML document with the default content storage
94 * implementation and the specified style/attribute storage mechanism.
96 * @param styles - the style sheet
98 public HTMLDocument(StyleSheet styles
)
100 this(new GapContent(BUFFER_SIZE_DEFAULT
), styles
);
104 * Constructs an HTML document with the given content storage implementation
105 * and the given style/attribute storage mechanism.
107 * @param c - the document's content
108 * @param styles - the style sheet
110 public HTMLDocument(AbstractDocument
.Content c
, StyleSheet styles
)
115 styles
= new StyleSheet();
116 styles
.importStyleSheet(getClass().getResource(HTMLEditorKit
.
119 this.styleSheet
= styles
;
123 * Gets the style sheet with the document display rules (CSS) that were specified
124 * in the HTML document.
126 * @return - the style sheet
128 public StyleSheet
getStyleSheet()
134 * Replaces the contents of the document with the given element specifications.
135 * This is called before insert if the loading is done in bursts. This is the
136 * only method called if loading the document entirely in one burst.
138 * @param data - the date that replaces the content of the document
140 protected void create(DefaultStyledDocument
.ElementSpec
[] data
)
142 // FIXME: Not implemented
143 System
.out
.println("create not implemented");
148 * This method creates a root element for the new document.
150 * @return the new default root
152 protected AbstractDocument
.AbstractElement
createDefaultRoot()
154 // FIXME: Not implemented
155 System
.out
.println("createDefaultRoot not implemented");
156 return super.createDefaultRoot();
160 * This method returns an HTMLDocument.RunElement object attached to
161 * parent representing a run of text from p0 to p1. The run has
162 * attributes described by a.
164 * @param parent - the parent element
165 * @param a - the attributes for the element
166 * @param p0 - the beginning of the range >= 0
167 * @param p1 - the end of the range >= p0
168 * @return the new element
170 protected Element
createLeafElement(Element parent
, AttributeSet a
, int p0
,
173 // FIXME: Not implemented
174 System
.out
.println("createLeafElement not implemented");
175 return super.createLeafElement(parent
, a
, p0
, p1
);
178 /** This method returns an HTMLDocument.BlockElement object representing the
179 * attribute set a and attached to parent.
181 * @param parent - the parent element
182 * @param a - the attributes for the element
183 * @return the new element
185 protected Element
createBranchElement(Element parent
, AttributeSet a
)
187 // FIXME: Not implemented
188 System
.out
.println("createBranchElement not implemented");
189 return super.createBranchElement(parent
, a
);
193 * Inserts new elements in bulk. This is how elements get created in the
194 * document. The parsing determines what structure is needed and creates the
195 * specification as a set of tokens that describe the edit while leaving the
196 * document free of a write-lock. This method can then be called in bursts by
197 * the reader to acquire a write-lock for a shorter duration (i.e. while the
198 * document is actually being altered).
200 * @param offset - the starting offset
201 * @param data - the element data
202 * @throws BadLocationException - if the given position does not
203 * represent a valid location in the associated document.
205 protected void insert(int offset
, DefaultStyledDocument
.ElementSpec
[] data
)
206 throws BadLocationException
208 super.insert(offset
, data
);
212 * Updates document structure as a result of text insertion. This will happen
213 * within a write lock. This implementation simply parses the inserted content
214 * for line breaks and builds up a set of instructions for the element buffer.
216 * @param chng - a description of the document change
217 * @param attr - the attributes
219 protected void insertUpdate(AbstractDocument
.DefaultDocumentEvent chng
,
222 // FIXME: Not implemented
223 System
.out
.println("insertUpdate not implemented");
224 super.insertUpdate(chng
, attr
);
228 * Returns the parser used by this HTMLDocument to insert HTML.
230 * @return the parser used by this HTMLDocument to insert HTML.
232 public HTMLEditorKit
.Parser
getParser()
238 * Sets the parser used by this HTMLDocument to insert HTML.
240 * @param p the parser to use
242 public void setParser (HTMLEditorKit
.Parser p
)
247 * Sets the number of tokens to buffer before trying to display the
250 * @param n the number of tokens to buffer
252 public void setTokenThreshold (int n
)
258 * Returns the number of tokens that are buffered before the document
261 * @return the number of tokens buffered
263 public int getTokenThreshold ()
265 return tokenThreshold
;
269 * Returns the location against which to resolve relative URLs.
270 * This is the document's URL if the document was loaded from a URL.
271 * If a <code>base</code> tag is found, it will be used.
272 * @return the base URL
280 * Sets the location against which to resolve relative URLs.
281 * @param u the new base URL
283 public void setBase(URL u
)
286 styleSheet
.setBase(u
);
290 * Returns whether or not the parser preserves unknown HTML tags.
291 * @return true if the parser preserves unknown tags
293 public boolean getPreservesUnknownTags()
295 return preservesUnknownTags
;
299 * Sets the behaviour of the parser when it encounters unknown HTML tags.
300 * @param preservesTags true if the parser should preserve unknown tags.
302 public void setPreservesUnknownTags(boolean preservesTags
)
304 preservesUnknownTags
= preservesTags
;
308 * An iterator to iterate through LeafElements in the document.
310 class LeafIterator
extends Iterator
316 public LeafIterator (HTML
.Tag t
, HTMLDocument d
)
320 it
= new ElementIterator(doc
);
324 * Return the attributes for the tag associated with this iteartor
325 * @return the AttributeSet
327 public AttributeSet
getAttributes()
329 if (it
.current() != null)
330 return it
.current().getAttributes();
335 * Get the end of the range for the current occurrence of the tag
336 * being defined and having the same attributes.
337 * @return the end of the range
339 public int getEndOffset()
341 if (it
.current() != null)
342 return it
.current().getEndOffset();
347 * Get the start of the range for the current occurrence of the tag
348 * being defined and having the same attributes.
349 * @return the start of the range (-1 if it can't be found).
352 public int getStartOffset()
354 if (it
.current() != null)
355 return it
.current().getStartOffset();
360 * Advance the iterator to the next LeafElement .
365 while (it
.current()!= null && !it
.current().isLeaf())
370 * Indicates whether or not the iterator currently represents an occurrence
372 * @return true if the iterator currently represents an occurrence of the
375 public boolean isValid()
377 return it
.current() != null;
381 * Type of tag for this iterator.
390 public void processHTMLFrameHyperlinkEvent(HTMLFrameHyperlinkEvent event
)
392 // TODO: Implement this properly.
396 * Gets an iterator for the given HTML.Tag.
397 * @param t the requested HTML.Tag
398 * @return the Iterator
400 public HTMLDocument
.Iterator
getIterator (HTML
.Tag t
)
402 return new HTMLDocument
.LeafIterator(t
, this);
406 * An iterator over a particular type of tag.
408 public abstract static class Iterator
411 * Return the attribute set for this tag.
412 * @return the <code>AttributeSet</code> (null if none found).
414 public abstract AttributeSet
getAttributes();
417 * Get the end of the range for the current occurrence of the tag
418 * being defined and having the same attributes.
419 * @return the end of the range
421 public abstract int getEndOffset();
424 * Get the start of the range for the current occurrence of the tag
425 * being defined and having the same attributes.
426 * @return the start of the range (-1 if it can't be found).
428 public abstract int getStartOffset();
431 * Move the iterator forward.
433 public abstract void next();
436 * Indicates whether or not the iterator currently represents an occurrence
438 * @return true if the iterator currently represents an occurrence of the
441 public abstract boolean isValid();
444 * Type of tag this iterator represents.
447 public abstract HTML
.Tag
getTag();
450 public class BlockElement
extends AbstractDocument
.BranchElement
452 public BlockElement (Element parent
, AttributeSet a
)
458 * Gets the resolving parent. Since HTML attributes are not
459 * inherited at the model level, this returns null.
461 public AttributeSet
getResolveParent()
467 * Gets the name of the element.
469 * @return the name of the element if it exists, null otherwise.
471 public String
getName()
473 return (String
) getAttribute(StyleConstants
.NameAttribute
);
478 * RunElement represents a section of text that has a set of
479 * HTML character level attributes assigned to it.
481 public class RunElement
extends AbstractDocument
.LeafElement
485 * Constructs an element that has no children. It represents content
486 * within the document.
488 * @param parent - parent of this
489 * @param a - elements attributes
490 * @param start - the start offset >= 0
491 * @param end - the end offset
493 public RunElement(Element parent
, AttributeSet a
, int start
, int end
)
495 super(parent
, a
, start
, end
);
499 * Gets the name of the element.
501 * @return the name of the element if it exists, null otherwise.
503 public String
getName()
505 return (String
) getAttribute(StyleConstants
.NameAttribute
);
509 * Gets the resolving parent. HTML attributes do not inherit at the
510 * model level, so this method returns null.
514 public AttributeSet
getResolveParent()
521 * A reader to load an HTMLDocument with HTML structure.
523 * @author Anthony Balkissoon abalkiss at redhat dot com
525 public class HTMLReader
extends HTMLEditorKit
.ParserCallback
527 /** Holds the current character attribute set **/
528 protected MutableAttributeSet charAttr
= new SimpleAttributeSet();
530 protected Vector parseBuffer
= new Vector();
532 /** A stack for character attribute sets **/
533 Stack charAttrStack
= new Stack();
535 /** A mapping between HTML.Tag objects and the actions that handle them **/
538 /** Tells us whether we've received the '</html>' tag yet **/
539 boolean endHTMLEncountered
= false;
541 /** Variables related to the constructor with explicit insertTag **/
542 int popDepth
, pushDepth
, offset
;
544 boolean insertTagEncountered
= false;
546 /** A temporary variable that helps with the printing out of debug information **/
547 boolean debug
= false;
549 void print (String line
)
552 System
.out
.println (line
);
555 public class TagAction
558 * This method is called when a start tag is seen for one of the types
559 * of tags associated with this Action. By default this does nothing.
561 public void start(HTML
.Tag t
, MutableAttributeSet a
)
563 // Nothing to do here.
567 * Called when an end tag is seen for one of the types of tags associated
568 * with this Action. By default does nothing.
570 public void end(HTML
.Tag t
)
572 // Nothing to do here.
576 public class BlockAction
extends TagAction
579 * This method is called when a start tag is seen for one of the types
580 * of tags associated with this Action.
582 public void start(HTML
.Tag t
, MutableAttributeSet a
)
584 // Tell the parse buffer to open a new block for this tag.
589 * Called when an end tag is seen for one of the types of tags associated
592 public void end(HTML
.Tag t
)
594 // Tell the parse buffer to close this block.
599 public class CharacterAction
extends TagAction
602 * This method is called when a start tag is seen for one of the types
603 * of tags associated with this Action.
605 public void start(HTML
.Tag t
, MutableAttributeSet a
)
607 // Put the old attribute set on the stack.
608 pushCharacterStyle();
610 // And create the new one by adding the attributes in <code>a</code>.
612 charAttr
.addAttribute(t
, a
.copyAttributes());
616 * Called when an end tag is seen for one of the types of tags associated
619 public void end(HTML
.Tag t
)
625 public class FormAction
extends SpecialAction
628 * This method is called when a start tag is seen for one of the types
629 * of tags associated with this Action.
631 public void start(HTML
.Tag t
, MutableAttributeSet a
)
634 print ("FormAction.start not implemented");
638 * Called when an end tag is seen for one of the types of tags associated
641 public void end(HTML
.Tag t
)
644 print ("FormAction.end not implemented");
648 public class HiddenAction
extends TagAction
651 * This method is called when a start tag is seen for one of the types
652 * of tags associated with this Action.
654 public void start(HTML
.Tag t
, MutableAttributeSet a
)
657 print ("HiddenAction.start not implemented");
661 * Called when an end tag is seen for one of the types of tags associated
664 public void end(HTML
.Tag t
)
667 print ("HiddenAction.end not implemented");
671 public class IsindexAction
extends TagAction
674 * This method is called when a start tag is seen for one of the types
675 * of tags associated with this Action.
677 public void start(HTML
.Tag t
, MutableAttributeSet a
)
680 print ("IsindexAction.start not implemented");
684 * Called when an end tag is seen for one of the types of tags associated
687 public void end(HTML
.Tag t
)
690 print ("IsindexAction.end not implemented");
694 public class ParagraphAction
extends BlockAction
697 * This method is called when a start tag is seen for one of the types
698 * of tags associated with this Action.
700 public void start(HTML
.Tag t
, MutableAttributeSet a
)
703 print ("ParagraphAction.start not implemented");
707 * Called when an end tag is seen for one of the types of tags associated
710 public void end(HTML
.Tag t
)
713 print ("ParagraphAction.end not implemented");
717 public class PreAction
extends BlockAction
720 * This method is called when a start tag is seen for one of the types
721 * of tags associated with this Action.
723 public void start(HTML
.Tag t
, MutableAttributeSet a
)
726 print ("PreAction.start not implemented");
730 * Called when an end tag is seen for one of the types of tags associated
733 public void end(HTML
.Tag t
)
736 print ("PreAction.end not implemented");
740 public class SpecialAction
extends TagAction
743 * This method is called when a start tag is seen for one of the types
744 * of tags associated with this Action.
746 public void start(HTML
.Tag t
, MutableAttributeSet a
)
749 print ("SpecialAction.start not implemented");
753 * Called when an end tag is seen for one of the types of tags associated
756 public void end(HTML
.Tag t
)
759 print ("SpecialAction.end not implemented");
763 class AreaAction
extends TagAction
766 * This method is called when a start tag is seen for one of the types
767 * of tags associated with this Action.
769 public void start(HTML
.Tag t
, MutableAttributeSet a
)
772 print ("AreaAction.start not implemented");
776 * Called when an end tag is seen for one of the types of tags associated
779 public void end(HTML
.Tag t
)
782 print ("AreaAction.end not implemented");
786 class BaseAction
extends TagAction
789 * This method is called when a start tag is seen for one of the types
790 * of tags associated with this Action.
792 public void start(HTML
.Tag t
, MutableAttributeSet a
)
795 print ("BaseAction.start not implemented");
799 * Called when an end tag is seen for one of the types of tags associated
802 public void end(HTML
.Tag t
)
805 print ("BaseAction.end not implemented");
809 class HeadAction
extends BlockAction
812 * This method is called when a start tag is seen for one of the types
813 * of tags associated with this Action.
815 public void start(HTML
.Tag t
, MutableAttributeSet a
)
818 print ("HeadAction.start not implemented: "+t
);
823 * Called when an end tag is seen for one of the types of tags associated
826 public void end(HTML
.Tag t
)
829 print ("HeadAction.end not implemented: "+t
);
834 class LinkAction
extends TagAction
837 * This method is called when a start tag is seen for one of the types
838 * of tags associated with this Action.
840 public void start(HTML
.Tag t
, MutableAttributeSet a
)
843 print ("LinkAction.start not implemented");
847 * Called when an end tag is seen for one of the types of tags associated
850 public void end(HTML
.Tag t
)
853 print ("LinkAction.end not implemented");
857 class MapAction
extends TagAction
860 * This method is called when a start tag is seen for one of the types
861 * of tags associated with this Action.
863 public void start(HTML
.Tag t
, MutableAttributeSet a
)
866 print ("MapAction.start not implemented");
870 * Called when an end tag is seen for one of the types of tags associated
873 public void end(HTML
.Tag t
)
876 print ("MapAction.end not implemented");
880 class MetaAction
extends TagAction
883 * This method is called when a start tag is seen for one of the types
884 * of tags associated with this Action.
886 public void start(HTML
.Tag t
, MutableAttributeSet a
)
889 print ("MetaAction.start not implemented");
893 * Called when an end tag is seen for one of the types of tags associated
896 public void end(HTML
.Tag t
)
899 print ("MetaAction.end not implemented");
903 class StyleAction
extends TagAction
906 * This method is called when a start tag is seen for one of the types
907 * of tags associated with this Action.
909 public void start(HTML
.Tag t
, MutableAttributeSet a
)
912 print ("StyleAction.start not implemented");
916 * Called when an end tag is seen for one of the types of tags associated
919 public void end(HTML
.Tag t
)
922 print ("StyleAction.end not implemented");
926 class TitleAction
extends TagAction
929 * This method is called when a start tag is seen for one of the types
930 * of tags associated with this Action.
932 public void start(HTML
.Tag t
, MutableAttributeSet a
)
935 print ("TitleAction.start not implemented");
939 * Called when an end tag is seen for one of the types of tags associated
942 public void end(HTML
.Tag t
)
945 print ("TitleAction.end not implemented");
949 public HTMLReader(int offset
)
951 this (offset
, 0, 0, null);
954 public HTMLReader(int offset
, int popDepth
, int pushDepth
,
957 print ("HTMLReader created with pop: "+popDepth
958 + " push: "+pushDepth
+ " offset: "+offset
959 + " tag: "+insertTag
);
960 this.insertTag
= insertTag
;
961 this.offset
= offset
;
962 this.popDepth
= popDepth
;
963 this.pushDepth
= pushDepth
;
969 tagToAction
= new HashMap(72);
970 CharacterAction characterAction
= new CharacterAction();
971 HiddenAction hiddenAction
= new HiddenAction();
972 AreaAction areaAction
= new AreaAction();
973 BaseAction baseAction
= new BaseAction();
974 BlockAction blockAction
= new BlockAction();
975 SpecialAction specialAction
= new SpecialAction();
976 ParagraphAction paragraphAction
= new ParagraphAction();
977 HeadAction headAction
= new HeadAction();
978 FormAction formAction
= new FormAction();
979 IsindexAction isindexAction
= new IsindexAction();
980 LinkAction linkAction
= new LinkAction();
981 MapAction mapAction
= new MapAction();
982 PreAction preAction
= new PreAction();
983 MetaAction metaAction
= new MetaAction();
984 StyleAction styleAction
= new StyleAction();
985 TitleAction titleAction
= new TitleAction();
988 tagToAction
.put(HTML
.Tag
.A
, characterAction
);
989 tagToAction
.put(HTML
.Tag
.ADDRESS
, characterAction
);
990 tagToAction
.put(HTML
.Tag
.APPLET
, hiddenAction
);
991 tagToAction
.put(HTML
.Tag
.AREA
, areaAction
);
992 tagToAction
.put(HTML
.Tag
.B
, characterAction
);
993 tagToAction
.put(HTML
.Tag
.BASE
, baseAction
);
994 tagToAction
.put(HTML
.Tag
.BASEFONT
, characterAction
);
995 tagToAction
.put(HTML
.Tag
.BIG
, characterAction
);
996 tagToAction
.put(HTML
.Tag
.BLOCKQUOTE
, blockAction
);
997 tagToAction
.put(HTML
.Tag
.BODY
, blockAction
);
998 tagToAction
.put(HTML
.Tag
.BR
, specialAction
);
999 tagToAction
.put(HTML
.Tag
.CAPTION
, blockAction
);
1000 tagToAction
.put(HTML
.Tag
.CENTER
, blockAction
);
1001 tagToAction
.put(HTML
.Tag
.CITE
, characterAction
);
1002 tagToAction
.put(HTML
.Tag
.CODE
, characterAction
);
1003 tagToAction
.put(HTML
.Tag
.DD
, blockAction
);
1004 tagToAction
.put(HTML
.Tag
.DFN
, characterAction
);
1005 tagToAction
.put(HTML
.Tag
.DIR
, blockAction
);
1006 tagToAction
.put(HTML
.Tag
.DIV
, blockAction
);
1007 tagToAction
.put(HTML
.Tag
.DL
, blockAction
);
1008 tagToAction
.put(HTML
.Tag
.DT
, paragraphAction
);
1009 tagToAction
.put(HTML
.Tag
.EM
, characterAction
);
1010 tagToAction
.put(HTML
.Tag
.FONT
, characterAction
);
1011 tagToAction
.put(HTML
.Tag
.FORM
, blockAction
);
1012 tagToAction
.put(HTML
.Tag
.FRAME
, specialAction
);
1013 tagToAction
.put(HTML
.Tag
.FRAMESET
, blockAction
);
1014 tagToAction
.put(HTML
.Tag
.H1
, paragraphAction
);
1015 tagToAction
.put(HTML
.Tag
.H2
, paragraphAction
);
1016 tagToAction
.put(HTML
.Tag
.H3
, paragraphAction
);
1017 tagToAction
.put(HTML
.Tag
.H4
, paragraphAction
);
1018 tagToAction
.put(HTML
.Tag
.H5
, paragraphAction
);
1019 tagToAction
.put(HTML
.Tag
.H6
, paragraphAction
);
1020 tagToAction
.put(HTML
.Tag
.HEAD
, headAction
);
1021 tagToAction
.put(HTML
.Tag
.HR
, specialAction
);
1022 tagToAction
.put(HTML
.Tag
.HTML
, blockAction
);
1023 tagToAction
.put(HTML
.Tag
.I
, characterAction
);
1024 tagToAction
.put(HTML
.Tag
.IMG
, specialAction
);
1025 tagToAction
.put(HTML
.Tag
.INPUT
, formAction
);
1026 tagToAction
.put(HTML
.Tag
.ISINDEX
, isindexAction
);
1027 tagToAction
.put(HTML
.Tag
.KBD
, characterAction
);
1028 tagToAction
.put(HTML
.Tag
.LI
, blockAction
);
1029 tagToAction
.put(HTML
.Tag
.LINK
, linkAction
);
1030 tagToAction
.put(HTML
.Tag
.MAP
, mapAction
);
1031 tagToAction
.put(HTML
.Tag
.MENU
, blockAction
);
1032 tagToAction
.put(HTML
.Tag
.META
, metaAction
);
1033 tagToAction
.put(HTML
.Tag
.NOFRAMES
, blockAction
);
1034 tagToAction
.put(HTML
.Tag
.OBJECT
, specialAction
);
1035 tagToAction
.put(HTML
.Tag
.OL
, blockAction
);
1036 tagToAction
.put(HTML
.Tag
.OPTION
, formAction
);
1037 tagToAction
.put(HTML
.Tag
.P
, paragraphAction
);
1038 tagToAction
.put(HTML
.Tag
.PARAM
, hiddenAction
);
1039 tagToAction
.put(HTML
.Tag
.PRE
, preAction
);
1040 tagToAction
.put(HTML
.Tag
.SAMP
, characterAction
);
1041 tagToAction
.put(HTML
.Tag
.SCRIPT
, hiddenAction
);
1042 tagToAction
.put(HTML
.Tag
.SELECT
, formAction
);
1043 tagToAction
.put(HTML
.Tag
.SMALL
, characterAction
);
1044 tagToAction
.put(HTML
.Tag
.STRIKE
, characterAction
);
1045 tagToAction
.put(HTML
.Tag
.S
, characterAction
);
1046 tagToAction
.put(HTML
.Tag
.STRONG
, characterAction
);
1047 tagToAction
.put(HTML
.Tag
.STYLE
, styleAction
);
1048 tagToAction
.put(HTML
.Tag
.SUB
, characterAction
);
1049 tagToAction
.put(HTML
.Tag
.SUP
, characterAction
);
1050 tagToAction
.put(HTML
.Tag
.TABLE
, blockAction
);
1051 tagToAction
.put(HTML
.Tag
.TD
, blockAction
);
1052 tagToAction
.put(HTML
.Tag
.TEXTAREA
, formAction
);
1053 tagToAction
.put(HTML
.Tag
.TH
, blockAction
);
1054 tagToAction
.put(HTML
.Tag
.TITLE
, titleAction
);
1055 tagToAction
.put(HTML
.Tag
.TR
, blockAction
);
1056 tagToAction
.put(HTML
.Tag
.TT
, characterAction
);
1057 tagToAction
.put(HTML
.Tag
.U
, characterAction
);
1058 tagToAction
.put(HTML
.Tag
.UL
, blockAction
);
1059 tagToAction
.put(HTML
.Tag
.VAR
, characterAction
);
1063 * Pushes the current character style onto the stack.
1066 protected void pushCharacterStyle()
1068 charAttrStack
.push(charAttr
);
1072 * Pops a character style off of the stack and uses it as the
1073 * current character style.
1076 protected void popCharacterStyle()
1078 if (!charAttrStack
.isEmpty())
1079 charAttr
= (MutableAttributeSet
) charAttrStack
.pop();
1083 * Registers a given tag with a given Action. All of the well-known tags
1084 * are registered by default, but this method can change their behaviour
1085 * or add support for custom or currently unsupported tags.
1087 * @param t the Tag to register
1088 * @param a the Action for the Tag
1090 protected void registerTag(HTML
.Tag t
, HTMLDocument
.HTMLReader
.TagAction a
)
1092 tagToAction
.put (t
, a
);
1096 * This is the last method called on the HTMLReader, allowing any pending
1097 * changes to be flushed to the HTMLDocument.
1099 public void flush() throws BadLocationException
1101 DefaultStyledDocument
.ElementSpec
[] elements
;
1102 elements
= new DefaultStyledDocument
.ElementSpec
[parseBuffer
.size()];
1103 parseBuffer
.copyInto(elements
);
1104 parseBuffer
.removeAllElements();
1105 insert(offset
, elements
);
1106 offset
+= HTMLDocument
.this.getLength() - offset
;
1110 * This method is called by the parser to indicate a block of
1111 * text was encountered. Should insert the text appropriately.
1113 * @param data the text that was inserted
1114 * @param pos the position at which the text was inserted
1116 public void handleText(char[] data
, int pos
)
1118 if (data
!= null && data
.length
> 0)
1119 addContent(data
, 0, data
.length
);
1123 * This method is called by the parser and should route the call to
1124 * the proper handler for the tag.
1126 * @param t the HTML.Tag
1127 * @param a the attribute set
1128 * @param pos the position at which the tag was encountered
1130 public void handleStartTag(HTML
.Tag t
, MutableAttributeSet a
, int pos
)
1132 // Don't call the Action if we've already seen </html>.
1133 if (endHTMLEncountered
)
1136 TagAction action
= (TagAction
) tagToAction
.get(t
);
1142 * This method called by parser to handle a comment block.
1144 * @param data the comment
1145 * @param pos the position at which the comment was encountered
1147 public void handleComment(char[] data
, int pos
)
1149 // Don't call the Action if we've already seen </html>.
1150 if (endHTMLEncountered
)
1153 TagAction action
= (TagAction
) tagToAction
.get(HTML
.Tag
.COMMENT
);
1156 action
.start(HTML
.Tag
.COMMENT
, new SimpleAttributeSet());
1157 action
.end (HTML
.Tag
.COMMENT
);
1162 * This method is called by the parser and should route the call to
1163 * the proper handler for the tag.
1165 * @param t the HTML.Tag
1166 * @param pos the position at which the tag was encountered
1168 public void handleEndTag(HTML
.Tag t
, int pos
)
1170 // Don't call the Action if we've already seen </html>.
1171 if (endHTMLEncountered
)
1174 // If this is the </html> tag we need to stop calling the Actions
1175 if (t
== HTML
.Tag
.HTML
)
1176 endHTMLEncountered
= true;
1178 TagAction action
= (TagAction
) tagToAction
.get(t
);
1184 * This is a callback from the parser that should be routed to the
1185 * appropriate handler for the tag.
1187 * @param t the HTML.Tag that was encountered
1188 * @param a the attribute set
1189 * @param pos the position at which the tag was encountered
1191 public void handleSimpleTag(HTML
.Tag t
, MutableAttributeSet a
, int pos
)
1193 // Don't call the Action if we've already seen </html>.
1194 if (endHTMLEncountered
)
1197 TagAction action
= (TagAction
) tagToAction
.get (t
);
1206 * This is invoked after the stream has been parsed but before it has been
1209 * @param eol one of \n, \r, or \r\n, whichever was encountered the most in
1210 * parsing the stream
1213 public void handleEndOfLineString(String eol
)
1215 // FIXME: Implement.
1216 print ("HTMLReader.handleEndOfLineString not implemented yet");
1220 * Adds the given text to the textarea document. Called only when we are
1221 * within a textarea.
1223 * @param data the text to add to the textarea
1225 protected void textAreaContent(char[] data
)
1227 // FIXME: Implement.
1228 print ("HTMLReader.textAreaContent not implemented yet");
1232 * Adds the given text that was encountered in a <PRE> element.
1234 * @param data the text
1236 protected void preContent(char[] data
)
1239 print ("HTMLReader.preContent not implemented yet");
1243 * Instructs the parse buffer to create a block element with the given
1246 * @param t the tag that requires opening a new block
1247 * @param attr the attribute set for the new block
1249 protected void blockOpen(HTML
.Tag t
, MutableAttributeSet attr
)
1252 DefaultStyledDocument
.ElementSpec element
;
1253 element
= new DefaultStyledDocument
.ElementSpec(attr
.copyAttributes(),
1254 DefaultStyledDocument
.ElementSpec
.StartTagType
);
1255 parseBuffer
.addElement(element
);
1260 * Instructs the parse buffer to close the block element associated with
1261 * the given HTML.Tag
1263 * @param t the HTML.Tag that is closing its block
1265 protected void blockClose(HTML
.Tag t
)
1268 DefaultStyledDocument
.ElementSpec element
;
1269 element
= new DefaultStyledDocument
.ElementSpec(null,
1270 DefaultStyledDocument
.ElementSpec
.EndTagType
);
1271 parseBuffer
.addElement(element
);
1276 * Adds text to the appropriate context using the current character
1279 * @param data the text to add
1280 * @param offs the offset at which to add it
1281 * @param length the length of the text to add
1283 protected void addContent(char[] data
, int offs
, int length
)
1285 addContent(data
, offs
, length
, true);
1289 * Adds text to the appropriate context using the current character
1290 * attribute set, and possibly generating an IMPLIED Tag if necessary.
1292 * @param data the text to add
1293 * @param offs the offset at which to add it
1294 * @param length the length of the text to add
1295 * @param generateImpliedPIfNecessary whether or not we should generate
1296 * an HTML.Tag.IMPLIED tag if necessary
1298 protected void addContent(char[] data
, int offs
, int length
,
1299 boolean generateImpliedPIfNecessary
)
1301 // Copy the attribute set, don't use the same object because
1303 AttributeSet attributes
= null;
1304 if (charAttr
!= null)
1305 attributes
= charAttr
.copyAttributes();
1307 DefaultStyledDocument
.ElementSpec element
;
1308 element
= new DefaultStyledDocument
.ElementSpec(attributes
,
1309 DefaultStyledDocument
.ElementSpec
.ContentType
,
1310 data
, offs
, length
);
1313 // Add the element to the buffer
1314 parseBuffer
.addElement(element
);
1317 if (parseBuffer
.size() > HTMLDocument
.this.getTokenThreshold())
1323 catch (BadLocationException ble
)
1325 // TODO: what to do here?
1331 * Adds content that is specified in the attribute set.
1333 * @param t the HTML.Tag
1334 * @param a the attribute set specifying the special content
1336 protected void addSpecialElement(HTML
.Tag t
, MutableAttributeSet a
)
1339 print ("HTMLReader.addSpecialElement not implemented yet");
1344 print ("\n*********BUFFER**********");
1345 for (int i
= 0; i
< parseBuffer
.size(); i
++)
1346 print (" "+parseBuffer
.get(i
));
1347 print ("***************************");
1352 * Gets the reader for the parser to use when loading the document with HTML.
1354 * @param pos - the starting position
1355 * @return - the reader
1357 public HTMLEditorKit
.ParserCallback
getReader(int pos
)
1359 return new HTMLReader(pos
);
1363 * Gets the reader for the parser to use when loading the document with HTML.
1365 * @param pos - the starting position
1366 * @param popDepth - the number of EndTagTypes to generate before inserting
1367 * @param pushDepth - the number of StartTagTypes with a direction
1368 * of JoinNextDirection that should be generated before inserting,
1369 * but after the end tags have been generated.
1370 * @param insertTag - the first tag to start inserting into document
1371 * @return - the reader
1373 public HTMLEditorKit
.ParserCallback
getReader(int pos
,
1378 return new HTMLReader(pos
, popDepth
, pushDepth
, insertTag
);
1382 * Gets the child element that contains the attribute with the value or null.
1385 * @param e - the element to begin search at
1386 * @param attribute - the desired attribute
1387 * @param value - the desired value
1388 * @return the element found with the attribute and value specified or null
1389 * if it is not found.
1391 public Element
getElement(Element e
, Object attribute
, Object value
)
1395 if (e
.getAttributes().containsAttribute(attribute
, value
))
1398 int count
= e
.getElementCount();
1399 for (int j
= 0; j
< count
; j
++)
1401 Element child
= e
.getElement(j
);
1402 if (child
.getAttributes().containsAttribute(attribute
, value
))
1405 Element grandChild
= getElement(child
, attribute
, value
);
1406 if (grandChild
!= null)
1414 * Returns the element that has the given id Attribute. If it is not found,
1415 * null is returned. This method works on an Attribute, not a character tag.
1416 * This is not thread-safe.
1418 * @param attrId - the Attribute id to look for
1419 * @return the element that has the given id.
1421 public Element
getElement(String attrId
)
1423 Element root
= getDefaultRootElement();
1424 return getElement(root
, HTML
.getAttributeKey(attrId
) , attrId
);
1428 * Replaces the children of the given element with the contents of
1429 * the string. The document must have an HTMLEditorKit.Parser set.
1430 * This will be seen as at least two events, n inserts followed by a remove.
1432 * @param elem - the brance element whose children will be replaced
1433 * @param htmlText - the string to be parsed and assigned to element.
1434 * @throws BadLocationException
1435 * @throws IOException
1436 * @throws IllegalArgumentException - if elem is a leaf
1437 * @throws IllegalStateException - if an HTMLEditorKit.Parser has not been set
1439 public void setInnerHTML(Element elem
, String htmlText
)
1440 throws BadLocationException
, IOException
1443 throw new IllegalArgumentException("Element is a leaf");
1445 throw new IllegalStateException("Parser has not been set");
1446 // FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
1447 System
.out
.println("setInnerHTML not implemented");
1451 * Replaces the given element in the parent with the string. When replacing
1452 * a leaf, this will attempt to make sure there is a newline present if one is
1453 * needed. This may result in an additional element being inserted.
1454 * This will be seen as at least two events, n inserts followed by a remove.
1455 * The HTMLEditorKit.Parser must be set.
1457 * @param elem - the branch element whose parent will be replaced
1458 * @param htmlText - the string to be parsed and assigned to elem
1459 * @throws BadLocationException
1460 * @throws IOException
1461 * @throws IllegalStateException - if parser is not set
1463 public void setOuterHTML(Element elem
, String htmlText
)
1464 throws BadLocationException
, IOException
1467 throw new IllegalStateException("Parser has not been set");
1468 // FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
1469 System
.out
.println("setOuterHTML not implemented");
1473 * Inserts the string before the start of the given element.
1474 * The parser must be set.
1476 * @param elem - the element to be the root for the new text.
1477 * @param htmlText - the string to be parsed and assigned to elem
1478 * @throws BadLocationException
1479 * @throws IOException
1480 * @throws IllegalStateException - if parser has not been set
1482 public void insertBeforeStart(Element elem
, String htmlText
)
1483 throws BadLocationException
, IOException
1486 throw new IllegalStateException("Parser has not been set");
1487 // FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
1488 System
.out
.println("insertBeforeStart not implemented");
1492 * Inserts the string at the end of the element. If elem's children
1493 * are leaves, and the character at elem.getEndOffset() - 1 is a newline,
1494 * then it will be inserted before the newline. The parser must be set.
1496 * @param elem - the element to be the root for the new text
1497 * @param htmlText - the text to insert
1498 * @throws BadLocationException
1499 * @throws IOException
1500 * @throws IllegalStateException - if parser is not set
1502 public void insertBeforeEnd(Element elem
, String htmlText
)
1503 throws BadLocationException
, IOException
1506 throw new IllegalStateException("Parser has not been set");
1507 // FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
1508 System
.out
.println("insertBeforeEnd not implemented");
1512 * Inserts the string after the end of the given element.
1513 * The parser must be set.
1515 * @param elem - the element to be the root for the new text
1516 * @param htmlText - the text to insert
1517 * @throws BadLocationException
1518 * @throws IOException
1519 * @throws IllegalStateException - if parser is not set
1521 public void insertAfterEnd(Element elem
, String htmlText
)
1522 throws BadLocationException
, IOException
1525 throw new IllegalStateException("Parser has not been set");
1526 // FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
1527 System
.out
.println("insertAfterEnd not implemented");
1531 * Inserts the string at the start of the element.
1532 * The parser must be set.
1534 * @param elem - the element to be the root for the new text
1535 * @param htmlText - the text to insert
1536 * @throws BadLocationException
1537 * @throws IOException
1538 * @throws IllegalStateException - if parser is not set
1540 public void insertAfterStart(Element elem
, String htmlText
)
1541 throws BadLocationException
, IOException
1544 throw new IllegalStateException("Parser has not been set");
1545 // FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
1546 System
.out
.println("insertAfterStart not implemented");
1550 * This method sets the attributes associated with the paragraph containing
1551 * offset. If replace is false, s is merged with existing attributes. The
1552 * length argument determines how many characters are affected by the new
1553 * attributes. This is often the entire paragraph.
1556 * the offset into the paragraph (must be at least 0)
1558 * the number of characters affected (must be at least 0)
1562 * whether to replace existing attributes, or merge them
1564 public void setParagraphAttributes(int offset
, int length
, AttributeSet s
,
1567 // FIXME: Not implemented.
1568 System
.out
.println("setParagraphAttributes not implemented");
1569 super.setParagraphAttributes(offset
, length
, s
, replace
);
1573 * This method flags a change in the document.
1575 * @param e - the Document event
1577 protected void fireChangedUpdate(DocumentEvent e
)
1579 // FIXME: Not implemented.
1580 System
.out
.println("fireChangedUpdate not implemented");
1581 super.fireChangedUpdate(e
);
1585 * This method fires an event intended to be caught by Undo listeners. It
1586 * simply calls the super version inherited from DefaultStyledDocument. With
1587 * this method, an HTML editor could easily provide undo support.
1589 * @param e - the UndoableEditEvent
1591 protected void fireUndoableEditUpdate(UndoableEditEvent e
)
1593 super.fireUndoableEditUpdate(e
);