libjava/ChangeLog:
[official-gcc.git] / libjava / classpath / javax / swing / text / html / HTMLWriter.java
blob6cc23df9aabe20087a6a6021298998bbf0e582a7
1 /* HTMLWriter.java --
2 Copyright (C) 2006 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)
9 any later version.
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
19 02110-1301 USA.
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
24 combination.
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. */
38 package javax.swing.text.html;
40 import gnu.java.lang.CPStringBuilder;
42 import java.io.IOException;
43 import java.io.Writer;
45 import java.util.Enumeration;
46 import java.util.HashSet;
48 import javax.swing.ComboBoxModel;
50 import javax.swing.text.AbstractWriter;
51 import javax.swing.text.AttributeSet;
52 import javax.swing.text.BadLocationException;
53 import javax.swing.text.Document;
54 import javax.swing.text.Element;
55 import javax.swing.text.StyleConstants;
57 import javax.swing.text.html.HTML;
58 import javax.swing.text.html.HTMLDocument;
59 import javax.swing.text.html.Option;
61 /**
62 * HTMLWriter,
63 * A Writer for HTMLDocuments.
65 * @author David Fu (fchoong at netbeans.jp)
68 public class HTMLWriter
69 extends AbstractWriter
71 /**
72 * We keep a reference of the writer passed by the construct.
74 private Writer outWriter = null;
76 /**
77 * We keep a reference of the HTMLDocument passed by the construct.
79 private HTMLDocument htmlDoc = null;
81 /**
82 * Used to keep track of which embeded has been written out.
84 private HashSet openEmbededTagHashSet = null;
86 private String new_line_str = "" + NEWLINE;
88 private char[] html_entity_char_arr = {'<', '>', '&', '"'};
90 private String[] html_entity_escape_str_arr = {"&lt;", "&gt;", "&amp;",
91 "&quot;"};
93 // variables used to output Html Fragment
94 private int doc_pos = -1;
95 private int doc_len = -1;
96 private int doc_offset_remaining = -1;
97 private int doc_len_remaining = -1;
98 private HashSet htmlFragmentParentHashSet = null;
99 private Element startElem = null;
100 private Element endElem = null;
101 private boolean fg_pass_start_elem = false;
102 private boolean fg_pass_end_elem = false;
105 * Constructs a HTMLWriter.
107 * @param writer writer to write output to
108 * @param doc the HTMLDocument to output
110 public HTMLWriter(Writer writer, HTMLDocument doc)
112 super(writer, doc);
113 outWriter = writer;
114 htmlDoc = doc;
115 openEmbededTagHashSet = new HashSet();
116 } // public HTMLWriter(Writer writer, HTMLDocument doc)
119 * Constructs a HTMLWriter which outputs a Html Fragment.
121 * @param writer <code>Writer</code> to write output to
122 * @param doc the <code>javax.swing.text.html.HTMLDocument</code>
123 * to output
124 * @param pos position to start outputing the document
125 * @param len amount to output the document
127 public HTMLWriter(Writer writer, HTMLDocument doc, int pos, int len)
129 super(writer, doc, pos, len);
130 outWriter = writer;
131 htmlDoc = doc;
132 openEmbededTagHashSet = new HashSet();
134 doc_pos = pos;
135 doc_offset_remaining = pos;
136 doc_len = len;
137 doc_len_remaining = len;
138 htmlFragmentParentHashSet = new HashSet();
139 } // public HTMLWriter(Writer writer, HTMLDocument doc, int pos, int len)
142 * Call this method to start outputing HTML.
144 * @throws IOException on any I/O exceptions
145 * @throws BadLocationException if a pos is not a valid position in the
146 * html doc element
148 public void write()
149 throws IOException, BadLocationException
151 Element rootElem = htmlDoc.getDefaultRootElement();
153 if (doc_pos == -1 && doc_len == -1)
155 // Normal traversal.
156 traverse(rootElem);
157 } // if(doc_pos == -1 && doc_len == -1)
158 else
160 // Html fragment traversal.
161 if (doc_pos == -1 || doc_len == -1)
162 throw new BadLocationException("Bad Location("
163 + doc_pos + ", " + doc_len + ")", doc_pos);
165 startElem = htmlDoc.getCharacterElement(doc_pos);
167 int start_offset = startElem.getStartOffset();
169 // Positions before start_offset will not be traversed, and thus
170 // will not be counted.
171 if (start_offset > 0)
172 doc_offset_remaining = doc_offset_remaining - start_offset;
174 Element tempParentElem = startElem;
176 while ((tempParentElem = tempParentElem.getParentElement()) != null)
178 if (!htmlFragmentParentHashSet.contains(tempParentElem))
179 htmlFragmentParentHashSet.add(tempParentElem);
180 } // while((tempParentElem = tempParentElem.getParentElement())
181 // != null)
183 // NOTE: 20061030 - fchoong - the last index should not be included.
184 endElem = htmlDoc.getCharacterElement(doc_pos + doc_len - 1);
186 tempParentElem = endElem;
188 while ((tempParentElem = tempParentElem.getParentElement()) != null)
190 if (!htmlFragmentParentHashSet.contains(tempParentElem))
191 htmlFragmentParentHashSet.add(tempParentElem);
192 } // while((tempParentElem = tempParentElem.getParentElement())
193 // != null)
195 traverseHtmlFragment(rootElem);
197 } // else
199 // NOTE: close out remaining open embeded tags.
200 Object[] tag_arr = openEmbededTagHashSet.toArray();
202 for (int i = 0; i < tag_arr.length; i++)
204 writeRaw("</" + tag_arr[i].toString() + ">");
205 } // for(int i = 0; i < tag_arr.length; i++)
207 } // public void write() throws IOException, BadLocationException
210 * Writes all the attributes in the attrSet, except for attrbutes with
211 * keys of <code>javax.swing.text.html.HTML.Tag</code>,
212 * <code>javax.swing.text.StyleConstants</code> or
213 * <code>javax.swing.text.html.HTML.Attribute.ENDTAG</code>.
215 * @param attrSet attrSet to write out
217 * @throws IOException on any I/O exceptions
219 protected void writeAttributes(AttributeSet attrSet)
220 throws IOException
222 Enumeration attrNameEnum = attrSet.getAttributeNames();
224 while (attrNameEnum.hasMoreElements())
226 Object key = attrNameEnum.nextElement();
227 Object value = attrSet.getAttribute(key);
229 // HTML.Attribute.ENDTAG is an instance, not a class.
230 if (!((key instanceof HTML.Tag) || (key instanceof StyleConstants)
231 || (key == HTML.Attribute.ENDTAG)))
233 if (key == HTML.Attribute.SELECTED)
234 writeRaw(" selected");
235 else if (key == HTML.Attribute.CHECKED)
236 writeRaw(" checked");
237 else
238 writeRaw(" " + key + "=\"" + value + "\"");
239 } // if(!((key instanceof HTML.Tag) || (key instanceof
240 // StyleConstants) || (key == HTML.Attribute.ENDTAG)))
241 } // while(attrNameEnum.hasMoreElements())
243 } // protected void writeAttributes(AttributeSet attrSet) throws IOException
246 * Writes out an empty tag. i.e. a tag without any child elements.
248 * @param paramElem the element to output as an empty tag
250 * @throws IOException on any I/O exceptions
251 * @throws BadLocationException if a pos is not a valid position in the
252 * html doc element
254 protected void emptyTag(Element paramElem)
255 throws IOException, BadLocationException
257 String elem_name = paramElem.getName();
258 AttributeSet attrSet = paramElem.getAttributes();
260 writeRaw("<" + elem_name);
261 writeAttributes(attrSet);
262 writeRaw(">");
264 if (isBlockTag(attrSet))
266 writeRaw("</" + elem_name + ">");
267 } // if(isBlockTag(attrSet))
269 } // protected void emptyTag(Element paramElem)
270 // throws IOException, BadLocationException
273 * Determines if it is a block tag or not.
275 * @param attrSet the attrSet of the element
277 * @return <code>true</code> if it is a block tag
278 * <code>false</code> if it is a not block tag
280 protected boolean isBlockTag(AttributeSet attrSet)
282 return ((HTML.Tag)
283 attrSet.getAttribute(StyleConstants.NameAttribute)).isBlock();
284 } // protected boolean isBlockTag(AttributeSet attrSet)
287 * Writes out a start tag. Synthesized elements are skipped.
289 * @param paramElem the element to output as a start tag
290 * @throws IOException on any I/O exceptions
291 * @throws BadLocationException if a pos is not a valid position in the
292 * html doc element
294 protected void startTag(Element paramElem)
295 throws IOException, BadLocationException
297 // NOTE: Sysnthesized elements do no call this method at all.
298 String elem_name = paramElem.getName();
299 AttributeSet attrSet = paramElem.getAttributes();
301 indent();
302 writeRaw("<" + elem_name);
303 writeAttributes(attrSet);
304 writeRaw(">");
305 writeLineSeparator(); // Extra formatting to look more like the RI.
306 incrIndent();
308 } // protected void startTag(Element paramElem)
309 // throws IOException, BadLocationException
312 * Writes out the contents of a textarea.
314 * @param attrSet the attrSet of the element to output as a text area
315 * @throws IOException on any I/O exceptions
316 * @throws BadLocationException if a pos is not a valid position in the
317 * html doc element
319 protected void textAreaContent(AttributeSet attrSet)
320 throws IOException, BadLocationException
322 writeLineSeparator(); // Extra formatting to look more like the RI.
323 indent();
324 writeRaw("<textarea");
325 writeAttributes(attrSet);
326 writeRaw(">");
328 Document tempDocument =
329 (Document) attrSet.getAttribute(StyleConstants.ModelAttribute);
331 writeRaw(tempDocument.getText(0, tempDocument.getLength()));
332 indent();
333 writeRaw("</textarea>");
335 } // protected void textAreaContent(AttributeSet attrSet)
336 // throws IOException, BadLocationException
339 * Writes out text, within the appropriate range if it is specified.
341 * @param paramElem the element to output as a text
342 * @throws IOException on any I/O exceptions
343 * @throws BadLocationException if a pos is not a valid position in the
344 * html doc element
346 protected void text(Element paramElem)
347 throws IOException, BadLocationException
349 int offset = paramElem.getStartOffset();
350 int len = paramElem.getEndOffset() - paramElem.getStartOffset();
351 String txt_value = htmlDoc.getText(offset, len);
353 writeContent(txt_value);
355 } // protected void text(Element paramElem)
356 // throws IOException, BadLocationException
359 * Writes out the contents of a select element.
361 * @param attrSet the attrSet of the element to output as a select box
363 * @throws IOException on any I/O exceptions
365 protected void selectContent(AttributeSet attrSet)
366 throws IOException
368 writeLineSeparator(); // Extra formatting to look more like the RI.
369 indent();
370 writeRaw("<select");
371 writeAttributes(attrSet);
372 writeRaw(">");
373 incrIndent();
374 writeLineSeparator(); // extra formatting to look more like the RI.
376 ComboBoxModel comboBoxModel =
377 (ComboBoxModel) attrSet.getAttribute(StyleConstants.ModelAttribute);
379 for (int i = 0; i < comboBoxModel.getSize(); i++)
381 writeOption((Option) comboBoxModel.getElementAt(i));
382 } // for(int i = 0; i < comboBoxModel.getSize(); i++)
384 decrIndent();
385 indent();
386 writeRaw("</select>");
388 } // protected void selectContent(AttributeSet attrSet) throws IOException
391 * Writes out the contents of an option element.
393 * @param option the option object to output as a select option
395 * @throws IOException on any I/O exceptions
397 protected void writeOption(Option option)
398 throws IOException
400 indent();
401 writeRaw("<option");
402 writeAttributes(option.getAttributes());
403 writeRaw(">");
405 writeContent(option.getLabel());
407 writeRaw("</option>");
408 writeLineSeparator(); // extra formatting to look more like the RI.
410 } // protected void writeOption(Option option) throws IOException
413 * Writes out an end tag.
415 * @param paramElem the element to output as an end tag
417 * @throws IOException on any I/O exceptions
419 protected void endTag(Element paramElem)
420 throws IOException
422 String elem_name = paramElem.getName();
424 //writeLineSeparator(); // Extra formatting to look more like the RI.
425 decrIndent();
426 indent();
427 writeRaw("</" + elem_name + ">");
428 writeLineSeparator(); // Extra formatting to look more like the RI.
430 } // protected void endTag(Element paramElem) throws IOException
433 * Writes out the comment.
435 * @param paramElem the element to output as a comment
437 protected void comment(Element paramElem)
438 throws IOException, BadLocationException
440 AttributeSet attrSet = paramElem.getAttributes();
442 String comment_str = (String) attrSet.getAttribute(HTML.Attribute.COMMENT);
444 writeRaw("<!--" + comment_str + "-->");
446 } // protected void comment(Element paramElem)
447 // throws IOException, BadLocationException
450 * Determines if element is a synthesized
451 * <code>javax.swing.text.Element</code> or not.
453 * @param element the element to test
455 * @return <code>true</code> if it is a synthesized element,
456 * <code>false</code> if it is a not synthesized element
458 protected boolean synthesizedElement(Element element)
460 AttributeSet attrSet = element.getAttributes();
461 Object tagType = attrSet.getAttribute(StyleConstants.NameAttribute);
463 if (tagType == HTML.Tag.CONTENT || tagType == HTML.Tag.COMMENT
464 || tagType == HTML.Tag.IMPLIED)
465 return true;
466 else
467 return false;
468 } // protected boolean synthesizedElement(Element element)
471 * Determines if
472 * <code>javax.swing.text.StyleConstants.NameAttribute</code>
473 * matches tag or not.
475 * @param attrSet the <code>javax.swing.text.AttributeSet</code> of
476 * element to be matched
477 * @param tag the HTML.Tag to match
479 * @return <code>true</code> if it matches,
480 * <code>false</code> if it does not match
482 protected boolean matchNameAttribute(AttributeSet attrSet, HTML.Tag tag)
484 Object tagType = attrSet.getAttribute(StyleConstants.NameAttribute);
486 if (tagType == tag)
487 return true;
488 else
489 return false;
490 } // protected boolean matchNameAttribute(AttributeSet attrSet,
491 // HTML.Tag tag)
494 * Writes out an embedded tag. The tags not already in
495 * openEmbededTagHashSet will written out.
497 * @param attrSet the <code>javax.swing.text.AttributeSet</code> of
498 * the element to write out
500 * @throws IOException on any I/O exceptions
502 protected void writeEmbeddedTags(AttributeSet attrSet)
503 throws IOException
505 Enumeration attrNameEnum = attrSet.getAttributeNames();
507 while (attrNameEnum.hasMoreElements())
509 Object key = attrNameEnum.nextElement();
510 Object value = attrSet.getAttribute(key);
512 if (key instanceof HTML.Tag)
514 if (!openEmbededTagHashSet.contains(key))
516 writeRaw("<" + key);
517 writeAttributes((AttributeSet) value);
518 writeRaw(">");
519 openEmbededTagHashSet.add(key);
520 } // if(!openEmbededTagHashSet.contains(key))
521 } // if(key instanceof HTML.Tag)
522 } // while(attrNameEnum.hasMoreElements())
524 } // protected void writeEmbeddedTags(AttributeSet attrSet)
525 // throws IOException
528 * Closes out an unwanted embedded tag. The tags from the
529 * openEmbededTagHashSet not found in attrSet will be written out.
531 * @param attrSet the AttributeSet of the element to write out
533 * @throws IOException on any I/O exceptions
535 protected void closeOutUnwantedEmbeddedTags(AttributeSet attrSet)
536 throws IOException
538 Object[] tag_arr = openEmbededTagHashSet.toArray();
540 for (int i = 0; i < tag_arr.length; i++)
542 HTML.Tag key = (HTML.Tag) tag_arr[i];
544 if (!attrSet.isDefined(key))
546 writeRaw("</" + key.toString() + ">");
547 openEmbededTagHashSet.remove(key);
548 } // if(!attrSet.isDefined(key))
549 } // for(int i = 0; i < tag_arr.length; i++)
551 } // protected void closeOutUnwantedEmbeddedTags(AttributeSet attrSet)
552 // throws IOException
555 * Writes out a line separator. Overwrites the parent to write out a new
556 * line.
558 * @throws IOException on any I/O exceptions.
560 protected void writeLineSeparator()
561 throws IOException
563 writeRaw(new_line_str);
564 } // protected void writeLineSeparator() throws IOException
567 * Write to the writer. Character entites such as &lt;, &gt;
568 * are escaped appropriately.
570 * @param chars char array to write out
571 * @param off offset
572 * @param len length
574 * @throws IOException on any I/O exceptions
576 protected void output(char[] chars, int off, int len)
577 throws IOException
579 CPStringBuilder strBuffer = new CPStringBuilder();
581 for (int i = 0; i < chars.length; i++)
583 if (isCharHtmlEntity(chars[i]))
584 strBuffer.append(escapeCharHtmlEntity(chars[i]));
585 else
586 strBuffer.append(chars[i]);
587 } // for(int i = 0; i < chars.length; i++)
589 writeRaw(strBuffer.toString());
591 } // protected void output(char[] chars, int off, int len)
592 // throws IOException
594 //-------------------------------------------------------------------------
595 // private methods
598 * The main method used to traverse through the elements.
600 * @param paramElem element to traverse
602 * @throws IOException on any I/O exceptions
604 private void traverse(Element paramElem)
605 throws IOException, BadLocationException
607 Element currElem = paramElem;
609 AttributeSet attrSet = currElem.getAttributes();
611 closeOutUnwantedEmbeddedTags(attrSet);
613 // handle the tag
614 if (synthesizedElement(paramElem))
616 if (matchNameAttribute(attrSet, HTML.Tag.CONTENT))
618 writeEmbeddedTags(attrSet);
619 text(currElem);
620 } // if(matchNameAttribute(attrSet, HTML.Tag.CONTENT))
621 else if (matchNameAttribute(attrSet, HTML.Tag.COMMENT))
623 comment(currElem);
624 } // else if(matchNameAttribute(attrSet, HTML.Tag.COMMENT))
625 else if (matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
627 int child_elem_count = currElem.getElementCount();
629 if (child_elem_count > 0)
631 for (int i = 0; i < child_elem_count; i++)
633 Element childElem = paramElem.getElement(i);
635 traverse(childElem);
637 } // for(int i = 0; i < child_elem_count; i++)
638 } // if(child_elem_count > 0)
639 } // else if(matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
640 } // if(synthesizedElement(paramElem))
641 else
643 // NOTE: 20061030 - fchoong - title is treated specially here.
644 // based on RI behavior.
645 if (matchNameAttribute(attrSet, HTML.Tag.TITLE))
647 boolean fg_is_end_tag = false;
648 Enumeration attrNameEnum = attrSet.getAttributeNames();
650 while (attrNameEnum.hasMoreElements())
652 Object key = attrNameEnum.nextElement();
653 Object value = attrSet.getAttribute(key);
655 if (key == HTML.Attribute.ENDTAG && value.equals("true"))
656 fg_is_end_tag = true;
657 } // while(attrNameEnum.hasMoreElements())
659 if (fg_is_end_tag)
660 writeRaw("</title>");
661 else
663 indent();
664 writeRaw("<title>");
666 String title_str =
667 (String) htmlDoc.getProperty(HTMLDocument.TitleProperty);
669 if (title_str != null)
670 writeContent(title_str);
672 } // else
673 } // if(matchNameAttribute(attrSet, HTML.Tag.TITLE))
674 else if (matchNameAttribute(attrSet, HTML.Tag.PRE))
676 // We pursue more stringent formating here.
677 attrSet = paramElem.getAttributes();
679 indent();
680 writeRaw("<pre");
681 writeAttributes(attrSet);
682 writeRaw(">");
684 int child_elem_count = currElem.getElementCount();
686 for (int i = 0; i < child_elem_count; i++)
688 Element childElem = paramElem.getElement(i);
690 traverse(childElem);
692 } // for(int i = 0; i < child_elem_count; i++)
694 writeRaw("</pre>");
696 } // else if(matchNameAttribute(attrSet, HTML.Tag.PRE))
697 else if (matchNameAttribute(attrSet, HTML.Tag.SELECT))
699 selectContent(attrSet);
700 } // else if(matchNameAttribute(attrSet, HTML.Tag.SELECT))
701 else if (matchNameAttribute(attrSet, HTML.Tag.TEXTAREA))
703 textAreaContent(attrSet);
704 } // else if(matchNameAttribute(attrSet, HTML.Tag.TEXTAREA))
705 else
707 int child_elem_count = currElem.getElementCount();
709 if (child_elem_count > 0)
711 startTag(currElem);
713 for (int i = 0; i < child_elem_count; i++)
715 Element childElem = paramElem.getElement(i);
717 traverse(childElem);
719 } // for(int i = 0; i < child_elem_count; i++)
721 endTag(currElem);
723 } // if(child_elem_count > 0)
724 else
726 emptyTag(currElem);
727 } // else
728 } // else
729 } // else
731 } // private void traverse(Element paramElem)
732 // throws IOException, BadLocationException
735 * The method used to traverse through a html fragment.
737 * @param paramElem element to traverse
739 * @throws IOException on any I/O exceptions
741 private void traverseHtmlFragment(Element paramElem)
742 throws IOException, BadLocationException
744 // NOTE: This method is similar to traverse(Element paramElem)
745 Element currElem = paramElem;
747 boolean fg_is_fragment_parent_elem = false;
748 boolean fg_is_start_and_end_elem = false;
750 if (htmlFragmentParentHashSet.contains(paramElem))
751 fg_is_fragment_parent_elem = true;
753 if (paramElem == startElem)
754 fg_pass_start_elem = true;
756 if (paramElem == startElem && paramElem == endElem)
757 fg_is_start_and_end_elem = true;
759 AttributeSet attrSet = currElem.getAttributes();
761 closeOutUnwantedEmbeddedTags(attrSet);
763 if (fg_is_fragment_parent_elem || (fg_pass_start_elem
764 && fg_pass_end_elem == false) || fg_is_start_and_end_elem)
766 // handle the tag
767 if (synthesizedElement(paramElem))
769 if (matchNameAttribute(attrSet, HTML.Tag.CONTENT))
771 writeEmbeddedTags(attrSet);
773 int content_offset = paramElem.getStartOffset();
774 int content_length = currElem.getEndOffset() - content_offset;
776 if (doc_offset_remaining > 0)
778 if (content_length > doc_offset_remaining)
780 int split_len = content_length;
782 split_len = split_len - doc_offset_remaining;
784 if (split_len > doc_len_remaining)
785 split_len = doc_len_remaining;
787 // we need to split it.
788 String txt_value = htmlDoc.getText(content_offset
789 + doc_offset_remaining, split_len);
791 writeContent(txt_value);
793 doc_offset_remaining = 0; // the offset is used up.
794 doc_len_remaining = doc_len_remaining - split_len;
795 } // if(content_length > doc_offset_remaining)
796 else
798 // doc_offset_remaining is greater than the entire
799 // length of content
800 doc_offset_remaining = doc_offset_remaining
801 - content_length;
802 } // else
803 } // if(doc_offset_remaining > 0)
804 else if (content_length <= doc_len_remaining)
806 // we can fit the entire content.
807 text(currElem);
808 doc_len_remaining = doc_len_remaining - content_length;
809 } // else if(content_length <= doc_len_remaining)
810 else
812 // we need to split it.
813 String txt_value = htmlDoc.getText(content_offset,
814 doc_len_remaining);
816 writeContent(txt_value);
818 doc_len_remaining = 0;
819 } // else
821 } // if(matchNameAttribute(attrSet, HTML.Tag.CONTENT))
822 else if (matchNameAttribute(attrSet, HTML.Tag.COMMENT))
824 comment(currElem);
825 } // else if(matchNameAttribute(attrSet, HTML.Tag.COMMENT))
826 else if (matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
828 int child_elem_count = currElem.getElementCount();
830 if (child_elem_count > 0)
832 for (int i = 0; i < child_elem_count; i++)
834 Element childElem = paramElem.getElement(i);
836 traverseHtmlFragment(childElem);
838 } // for(int i = 0; i < child_elem_count; i++)
839 } // if(child_elem_count > 0)
840 } // else if(matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
841 } // if(synthesizedElement(paramElem))
842 else
844 // NOTE: 20061030 - fchoong - the isLeaf() condition seems to
845 // generate the closest behavior to the RI.
846 if (paramElem.isLeaf())
848 if (doc_offset_remaining > 0)
850 doc_offset_remaining--;
851 } // if(doc_offset_remaining > 0)
852 else if (doc_len_remaining > 0)
854 doc_len_remaining--;
855 } // else if(doc_len_remaining > 0)
856 } // if(paramElem.isLeaf())
858 // NOTE: 20061030 - fchoong - title is treated specially here.
859 // based on RI behavior.
860 if (matchNameAttribute(attrSet, HTML.Tag.TITLE))
862 boolean fg_is_end_tag = false;
863 Enumeration attrNameEnum = attrSet.getAttributeNames();
865 while (attrNameEnum.hasMoreElements())
867 Object key = attrNameEnum.nextElement();
868 Object value = attrSet.getAttribute(key);
870 if (key == HTML.Attribute.ENDTAG && value.equals("true"))
871 fg_is_end_tag = true;
872 } // while(attrNameEnum.hasMoreElements())
874 if (fg_is_end_tag)
875 writeRaw("</title>");
876 else
878 indent();
879 writeRaw("<title>");
881 String title_str =
882 (String) htmlDoc.getProperty(HTMLDocument.TitleProperty);
884 if (title_str != null)
885 writeContent(title_str);
887 } // else
888 } // if(matchNameAttribute(attrSet, HTML.Tag.TITLE))
889 else if (matchNameAttribute(attrSet, HTML.Tag.PRE))
891 // We pursue more stringent formating here.
892 attrSet = paramElem.getAttributes();
894 indent();
895 writeRaw("<pre");
896 writeAttributes(attrSet);
897 writeRaw(">");
899 int child_elem_count = currElem.getElementCount();
901 for (int i = 0; i < child_elem_count; i++)
903 Element childElem = paramElem.getElement(i);
905 traverseHtmlFragment(childElem);
907 } // for(int i = 0; i < child_elem_count; i++)
909 writeRaw("</pre>");
911 } // else if(matchNameAttribute(attrSet, HTML.Tag.PRE))
912 else if (matchNameAttribute(attrSet, HTML.Tag.SELECT))
914 selectContent(attrSet);
915 } // else if(matchNameAttribute(attrSet, HTML.Tag.SELECT))
916 else if (matchNameAttribute(attrSet, HTML.Tag.TEXTAREA))
918 textAreaContent(attrSet);
919 } // else if(matchNameAttribute(attrSet, HTML.Tag.TEXTAREA))
920 else
922 int child_elem_count = currElem.getElementCount();
924 if (child_elem_count > 0)
926 startTag(currElem);
928 for (int i = 0; i < child_elem_count; i++)
930 Element childElem = paramElem.getElement(i);
932 traverseHtmlFragment(childElem);
934 } // for(int i = 0; i < child_elem_count; i++)
936 endTag(currElem);
938 } // if(child_elem_count > 0)
939 else
941 emptyTag(currElem);
942 } // else
943 } // else
944 } // else
946 } // if(fg_is_fragment_parent_elem || (fg_pass_start_elem
947 // && fg_pass_end_elem == false) || fg_is_start_and_end_elem)
949 if (paramElem == endElem)
950 fg_pass_end_elem = true;
952 } // private void traverseHtmlFragment(Element paramElem)
953 // throws IOException, BadLocationException
956 * Write to the writer without any modifications.
958 * @param param_str the str to write out
960 * @throws IOException on any I/O exceptions
962 private void writeRaw(String param_str)
963 throws IOException
965 super.output(param_str.toCharArray(), 0, param_str.length());
966 } // private void writeRaw(char[] chars, int off, int len)
967 // throws IOException
970 * Write to the writer, escaping HTML character entitie where neccessary.
972 * @param param_str the str to write out
974 * @throws IOException on any I/O exceptions
976 private void writeContent(String param_str)
977 throws IOException
979 char[] str_char_arr = param_str.toCharArray();
981 if (hasHtmlEntity(param_str))
982 output(str_char_arr, 0, str_char_arr.length);
983 else
984 super.output(str_char_arr, 0, str_char_arr.length);
986 } // private void writeContent(String param_str) throws IOException
989 * Use this for debugging. Writes out all attributes regardless of type.
991 * @param attrSet the <code>javax.swing.text.AttributeSet</code> to
992 * write out
994 * @throws IOException on any I/O exceptions
996 private void writeAllAttributes(AttributeSet attrSet)
997 throws IOException
999 Enumeration attrNameEnum = attrSet.getAttributeNames();
1001 while (attrNameEnum.hasMoreElements())
1003 Object key = attrNameEnum.nextElement();
1004 Object value = attrSet.getAttribute(key);
1006 writeRaw(" " + key + "=\"" + value + "\"");
1007 writeRaw(" " + key.getClass().toString() + "=\""
1008 + value.getClass().toString() + "\"");
1009 } // while(attrNameEnum.hasMoreElements())
1011 } // private void writeAllAttributes(AttributeSet attrSet)
1012 // throws IOException
1015 * Tests if the str contains any html entities.
1017 * @param param_str the str to test
1019 * @return <code>true</code> if it has a html entity
1020 * <code>false</code> if it does not have a html entity
1022 private boolean hasHtmlEntity(String param_str)
1024 boolean ret_bool = false;
1026 for (int i = 0; i < html_entity_char_arr.length; i++)
1028 if (param_str.indexOf(html_entity_char_arr[i]) != -1)
1030 ret_bool = true;
1031 break;
1032 } // if(param_str.indexOf(html_entity_char_arr[i]) != -1)
1033 } // for(int i = 0; i < html_entity_char_arr.length; i++)
1035 return ret_bool;
1036 } // private boolean hasHtmlEntity(String param_str)
1039 * Tests if the char is a html entities.
1041 * @param param_char the char to test
1043 * @return <code>true</code> if it is a html entity
1044 * <code>false</code> if it is not a html entity.
1046 private boolean isCharHtmlEntity(char param_char)
1048 boolean ret_bool = false;
1050 for (int i = 0; i < html_entity_char_arr.length; i++)
1052 if (param_char == html_entity_char_arr[i])
1054 ret_bool = true;
1055 break;
1056 } // if(param_char == html_entity_char_arr[i])
1057 } // for(int i = 0; i < html_entity_char_arr.length; i++)
1059 return ret_bool;
1060 } // private boolean hasHtmlEntity(String param_str)
1063 * Escape html entities.
1065 * @param param_char the char to escape
1067 * @return escaped html entity. Original char is returned as a str if is
1068 * is not a html entity
1070 private String escapeCharHtmlEntity(char param_char)
1072 String ret_str = "" + param_char;
1074 for (int i = 0; i < html_entity_char_arr.length; i++)
1076 if (param_char == html_entity_char_arr[i])
1078 ret_str = html_entity_escape_str_arr[i];
1079 break;
1080 } // if(param_char == html_entity_char_arr[i])
1081 } // for(int i = 0; i < html_entity_char_arr.length; i++)
1083 return ret_str;
1084 } // private String escapeCharHtmlEntity(char param_char)
1086 } // public class HTMLWriter extends AbstractWriter