1 7 package javax.swing.text.html; 8 9 import javax.swing.text.*; 10 import java.io.Writer ; 11 import java.util.Stack ; 12 import java.util.Enumeration ; 13 import java.util.Vector ; 14 import java.io.IOException ; 15 import java.util.StringTokenizer ; 16 import java.util.NoSuchElementException ; 17 import java.net.URL ; 18 19 25 26 27 public class HTMLWriter extends AbstractWriter { 28 32 private Stack blockElementStack = new Stack (); 33 private boolean inContent = false; 34 private boolean inPre = false; 35 37 private int preEndOffset; 38 private boolean inTextArea = false; 39 private boolean newlineOutputed = false; 40 private boolean completeDoc; 41 42 48 private Vector tags = new Vector (10); 49 50 53 private Vector tagValues = new Vector (10); 54 55 58 private Segment segment; 59 60 63 private Vector tagsToRemove = new Vector (10); 64 65 68 private boolean wroteHead; 69 70 73 private boolean replaceEntities; 74 75 78 private char[] tempChars; 79 80 81 88 public HTMLWriter(Writer w, HTMLDocument doc) { 89 this(w, doc, 0, doc.getLength()); 90 } 91 92 100 public HTMLWriter(Writer w, HTMLDocument doc, int pos, int len) { 101 super(w, doc, pos, len); 102 completeDoc = (pos == 0 && len == doc.getLength()); 103 setLineLength(80); 104 } 105 106 116 public void write() throws IOException , BadLocationException { 117 ElementIterator it = getElementIterator(); 118 Element current = null; 119 Element next = null; 120 121 wroteHead = false; 122 setCurrentLineLength(0); 123 replaceEntities = false; 124 setCanWrapLines(false); 125 if (segment == null) { 126 segment = new Segment(); 127 } 128 inPre = false; 129 boolean forcedBody = false; 130 while ((next = it.next()) != null) { 131 if (!inRange(next)) { 132 if (completeDoc && next.getAttributes().getAttribute( 133 StyleConstants.NameAttribute) == HTML.Tag.BODY) { 134 forcedBody = true; 135 } 136 else { 137 continue; 138 } 139 } 140 if (current != null) { 141 142 145 146 if (indentNeedsIncrementing(current, next)) { 147 incrIndent(); 148 } else if (current.getParentElement() != next.getParentElement()) { 149 155 Element top = (Element)blockElementStack.peek(); 156 while (top != next.getParentElement()) { 157 160 blockElementStack.pop(); 161 if (!synthesizedElement(top)) { 162 AttributeSet attrs = top.getAttributes(); 163 if (!matchNameAttribute(attrs, HTML.Tag.PRE) && 164 !isFormElementWithContent(attrs)) { 165 decrIndent(); 166 } 167 endTag(top); 168 } 169 top = (Element)blockElementStack.peek(); 170 } 171 } else if (current.getParentElement() == next.getParentElement()) { 172 177 Element top = (Element)blockElementStack.peek(); 178 if (top == current) { 179 blockElementStack.pop(); 180 endTag(top); 181 } 182 } 183 } 184 if (!next.isLeaf() || isFormElementWithContent(next.getAttributes())) { 185 blockElementStack.push(next); 186 startTag(next); 187 } else { 188 emptyTag(next); 189 } 190 current = next; 191 } 192 193 194 198 closeOutUnwantedEmbeddedTags(null); 199 200 if (forcedBody) { 201 blockElementStack.pop(); 202 endTag(current); 203 } 204 while (!blockElementStack.empty()) { 205 current = (Element)blockElementStack.pop(); 206 if (!synthesizedElement(current)) { 207 AttributeSet attrs = current.getAttributes(); 208 if (!matchNameAttribute(attrs, HTML.Tag.PRE) && 209 !isFormElementWithContent(attrs)) { 210 decrIndent(); 211 } 212 endTag(current); 213 } 214 } 215 216 if (completeDoc) { 217 writeAdditionalComments(); 218 } 219 220 segment.array = null; 221 } 222 223 224 235 protected void writeAttributes(AttributeSet attr) throws IOException { 236 convAttr.removeAttributes(convAttr); 238 convertToHTML32(attr, convAttr); 239 240 Enumeration names = convAttr.getAttributeNames(); 241 while (names.hasMoreElements()) { 242 Object name = names.nextElement(); 243 if (name instanceof HTML.Tag || 244 name instanceof StyleConstants || 245 name == HTML.Attribute.ENDTAG) { 246 continue; 247 } 248 write(" " + name + "=\"" + convAttr.getAttribute(name) + "\""); 249 } 250 } 251 252 261 protected void emptyTag(Element elem) throws BadLocationException, IOException { 262 263 if (!inContent && !inPre) { 264 indent(); 265 } 266 267 AttributeSet attr = elem.getAttributes(); 268 closeOutUnwantedEmbeddedTags(attr); 269 writeEmbeddedTags(attr); 270 271 if (matchNameAttribute(attr, HTML.Tag.CONTENT)) { 272 inContent = true; 273 text(elem); 274 } else if (matchNameAttribute(attr, HTML.Tag.COMMENT)) { 275 comment(elem); 276 } else { 277 boolean isBlock = isBlockTag(elem.getAttributes()); 278 if (inContent && isBlock ) { 279 writeLineSeparator(); 280 indent(); 281 } 282 283 Object nameTag = (attr != null) ? attr.getAttribute 284 (StyleConstants.NameAttribute) : null; 285 Object endTag = (attr != null) ? attr.getAttribute 286 (HTML.Attribute.ENDTAG) : null; 287 288 boolean outputEndTag = false; 289 if (nameTag != null && endTag != null && 293 (endTag instanceof String ) && 294 ((String )endTag).equals("true")) { 295 outputEndTag = true; 296 } 297 298 if (completeDoc && matchNameAttribute(attr, HTML.Tag.HEAD)) { 299 if (outputEndTag) { 300 writeStyles(((HTMLDocument )getDocument()).getStyleSheet()); 302 } 303 wroteHead = true; 304 } 305 306 write('<'); 307 if (outputEndTag) { 308 write('/'); 309 } 310 write(elem.getName()); 311 writeAttributes(attr); 312 write('>'); 313 if (matchNameAttribute(attr, HTML.Tag.TITLE) && !outputEndTag) { 314 Document doc = elem.getDocument(); 315 String title = (String )doc.getProperty(Document.TitleProperty); 316 write(title); 317 } else if (!inContent || isBlock) { 318 writeLineSeparator(); 319 if (isBlock && inContent) { 320 indent(); 321 } 322 } 323 } 324 } 325 326 333 protected boolean isBlockTag(AttributeSet attr) { 334 Object o = attr.getAttribute(StyleConstants.NameAttribute); 335 if (o instanceof HTML.Tag ) { 336 HTML.Tag name = (HTML.Tag ) o; 337 return name.isBlock(); 338 } 339 return false; 340 } 341 342 343 350 protected void startTag(Element elem) throws IOException , BadLocationException { 351 352 if (synthesizedElement(elem)) { 353 return; 354 } 355 356 AttributeSet attr = elem.getAttributes(); 358 Object nameAttribute = attr.getAttribute(StyleConstants.NameAttribute); 359 HTML.Tag name; 360 if (nameAttribute instanceof HTML.Tag ) { 361 name = (HTML.Tag )nameAttribute; 362 } 363 else { 364 name = null; 365 } 366 367 if (name == HTML.Tag.PRE) { 368 inPre = true; 369 preEndOffset = elem.getEndOffset(); 370 } 371 372 closeOutUnwantedEmbeddedTags(attr); 374 375 if (inContent) { 376 writeLineSeparator(); 377 inContent = false; 378 newlineOutputed = false; 379 } 380 381 if (completeDoc && name == HTML.Tag.BODY && !wroteHead) { 382 wroteHead = true; 384 indent(); 385 write("<head>"); 386 writeLineSeparator(); 387 incrIndent(); 388 writeStyles(((HTMLDocument )getDocument()).getStyleSheet()); 389 decrIndent(); 390 writeLineSeparator(); 391 indent(); 392 write("</head>"); 393 writeLineSeparator(); 394 } 395 396 indent(); 397 write('<'); 398 write(elem.getName()); 399 writeAttributes(attr); 400 write('>'); 401 if (name != HTML.Tag.PRE) { 402 writeLineSeparator(); 403 } 404 405 if (name == HTML.Tag.TEXTAREA) { 406 textAreaContent(elem.getAttributes()); 407 } else if (name == HTML.Tag.SELECT) { 408 selectContent(elem.getAttributes()); 409 } else if (completeDoc && name == HTML.Tag.BODY) { 410 writeMaps(((HTMLDocument )getDocument()).getMaps()); 413 } 414 else if (name == HTML.Tag.HEAD) { 415 wroteHead = true; 416 incrIndent(); 417 writeStyles(((HTMLDocument )getDocument()).getStyleSheet()); 418 decrIndent(); 419 } 420 HTMLDocument document = null; 421 if (name == HTML.Tag.BODY 422 && (document = (HTMLDocument )getDocument()).hasBaseTag()) { 423 incrIndent(); 424 indent(); 425 write("<base href = \"" + document.getBase() + "\">"); 426 writeLineSeparator(); 427 decrIndent(); 428 } 429 430 } 431 432 433 442 protected void textAreaContent(AttributeSet attr) throws BadLocationException, IOException { 443 Document doc = (Document)attr.getAttribute(StyleConstants.ModelAttribute); 444 if (doc != null && doc.getLength() > 0) { 445 if (segment == null) { 446 segment = new Segment(); 447 } 448 doc.getText(0, doc.getLength(), segment); 449 if (segment.count > 0) { 450 inTextArea = true; 451 incrIndent(); 452 indent(); 453 setCanWrapLines(true); 454 replaceEntities = true; 455 write(segment.array, segment.offset, segment.count); 456 replaceEntities = false; 457 setCanWrapLines(false); 458 writeLineSeparator(); 459 inTextArea = false; 460 decrIndent(); 461 } 462 } 463 } 464 465 466 476 protected void text(Element elem) throws BadLocationException, IOException { 477 int start = Math.max(getStartOffset(), elem.getStartOffset()); 478 int end = Math.min(getEndOffset(), elem.getEndOffset()); 479 if (start < end) { 480 if (segment == null) { 481 segment = new Segment(); 482 } 483 getDocument().getText(start, end - start, segment); 484 newlineOutputed = false; 485 if (segment.count > 0) { 486 if (segment.array[segment.offset + segment.count - 1] == '\n'){ 487 newlineOutputed = true; 488 } 489 if (inPre && end == preEndOffset) { 490 if (segment.count > 1) { 491 segment.count--; 492 } 493 else { 494 return; 495 } 496 } 497 replaceEntities = true; 498 setCanWrapLines(!inPre); 499 write(segment.array, segment.offset, segment.count); 500 setCanWrapLines(false); 501 replaceEntities = false; 502 } 503 } 504 } 505 506 512 protected void selectContent(AttributeSet attr) throws IOException { 513 Object model = attr.getAttribute(StyleConstants.ModelAttribute); 514 incrIndent(); 515 if (model instanceof OptionListModel ) { 516 OptionListModel listModel = (OptionListModel )model; 517 int size = listModel.getSize(); 518 for (int i = 0; i < size; i++) { 519 Option option = (Option )listModel.getElementAt(i); 520 writeOption(option); 521 } 522 } else if (model instanceof OptionComboBoxModel ) { 523 OptionComboBoxModel comboBoxModel = (OptionComboBoxModel )model; 524 int size = comboBoxModel.getSize(); 525 for (int i = 0; i < size; i++) { 526 Option option = (Option )comboBoxModel.getElementAt(i); 527 writeOption(option); 528 } 529 } 530 decrIndent(); 531 } 532 533 534 540 protected void writeOption(Option option) throws IOException { 541 542 indent(); 543 write('<'); 544 write("option"); 545 Object value = option.getAttributes().getAttribute 547 (HTML.Attribute.VALUE); 548 if (value != null) { 549 write(" value="+ value); 550 } 551 if (option.isSelected()) { 552 write(" selected"); 553 } 554 write('>'); 555 if (option.getLabel() != null) { 556 write(option.getLabel()); 557 } 558 writeLineSeparator(); 559 } 560 561 567 protected void endTag(Element elem) throws IOException { 568 if (synthesizedElement(elem)) { 569 return; 570 } 571 572 closeOutUnwantedEmbeddedTags(elem.getAttributes()); 574 if (inContent) { 575 if (!newlineOutputed && !inPre) { 576 writeLineSeparator(); 577 } 578 newlineOutputed = false; 579 inContent = false; 580 } 581 if (!inPre) { 582 indent(); 583 } 584 if (matchNameAttribute(elem.getAttributes(), HTML.Tag.PRE)) { 585 inPre = false; 586 } 587 write('<'); 588 write('/'); 589 write(elem.getName()); 590 write('>'); 591 writeLineSeparator(); 592 } 593 594 595 596 604 protected void comment(Element elem) throws BadLocationException, IOException { 605 AttributeSet as = elem.getAttributes(); 606 if (matchNameAttribute(as, HTML.Tag.COMMENT)) { 607 Object comment = as.getAttribute(HTML.Attribute.COMMENT); 608 if (comment instanceof String ) { 609 writeComment((String )comment); 610 } 611 else { 612 writeComment(null); 613 } 614 } 615 } 616 617 618 626 void writeComment(String string) throws IOException { 627 write("<!--"); 628 if (string != null) { 629 write(string); 630 } 631 write("-->"); 632 writeLineSeparator(); 633 } 634 635 636 640 void writeAdditionalComments() throws IOException { 641 Object comments = getDocument().getProperty 642 (HTMLDocument.AdditionalComments); 643 644 if (comments instanceof Vector ) { 645 Vector v = (Vector )comments; 646 for (int counter = 0, maxCounter = v.size(); counter < maxCounter; 647 counter++) { 648 writeComment(v.elementAt(counter).toString()); 649 } 650 } 651 } 652 653 654 659 protected boolean synthesizedElement(Element elem) { 660 if (matchNameAttribute(elem.getAttributes(), HTML.Tag.IMPLIED)) { 661 return true; 662 } 663 return false; 664 } 665 666 667 671 protected boolean matchNameAttribute(AttributeSet attr, HTML.Tag tag) { 672 Object o = attr.getAttribute(StyleConstants.NameAttribute); 673 if (o instanceof HTML.Tag ) { 674 HTML.Tag name = (HTML.Tag ) o; 675 if (name == tag) { 676 return true; 677 } 678 } 679 return false; 680 } 681 682 690 protected void writeEmbeddedTags(AttributeSet attr) throws IOException { 691 692 attr = convertToHTML(attr, oConvAttr); 694 695 Enumeration names = attr.getAttributeNames(); 696 while (names.hasMoreElements()) { 697 Object name = names.nextElement(); 698 if (name instanceof HTML.Tag ) { 699 HTML.Tag tag = (HTML.Tag )name; 700 if (tag == HTML.Tag.FORM || tags.contains(tag)) { 701 continue; 702 } 703 write('<'); 704 write(tag.toString()); 705 Object o = attr.getAttribute(tag); 706 if (o != null && o instanceof AttributeSet) { 707 writeAttributes((AttributeSet)o); 708 } 709 write('>'); 710 tags.addElement(tag); 711 tagValues.addElement(o); 712 } 713 } 714 } 715 716 717 722 private boolean noMatchForTagInAttributes(AttributeSet attr, HTML.Tag t, 723 Object tagValue) { 724 if (attr != null && attr.isDefined(t)) { 725 Object newValue = attr.getAttribute(t); 726 727 if ((tagValue == null) ? (newValue == null) : 728 (newValue != null && tagValue.equals(newValue))) { 729 return false; 730 } 731 } 732 return true; 733 } 734 735 736 744 protected void closeOutUnwantedEmbeddedTags(AttributeSet attr) throws IOException { 745 746 tagsToRemove.removeAllElements(); 747 748 attr = convertToHTML(attr, null); 750 751 HTML.Tag t; 752 Object tValue; 753 int firstIndex = -1; 754 int size = tags.size(); 755 for (int i = size - 1; i >= 0; i--) { 757 t = (HTML.Tag )tags.elementAt(i); 758 tValue = tagValues.elementAt(i); 759 if ((attr == null) || noMatchForTagInAttributes(attr, t, tValue)) { 760 firstIndex = i; 761 tagsToRemove.addElement(t); 762 } 763 } 764 if (firstIndex != -1) { 765 boolean removeAll = ((size - firstIndex) == tagsToRemove.size()); 767 for (int i = size - 1; i >= firstIndex; i--) { 768 t = (HTML.Tag )tags.elementAt(i); 769 if (removeAll || tagsToRemove.contains(t)) { 770 tags.removeElementAt(i); 771 tagValues.removeElementAt(i); 772 } 773 write('<'); 774 write('/'); 775 write(t.toString()); 776 write('>'); 777 } 778 size = tags.size(); 781 for (int i = firstIndex; i < size; i++) { 782 t = (HTML.Tag )tags.elementAt(i); 783 write('<'); 784 write(t.toString()); 785 Object o = tagValues.elementAt(i); 786 if (o != null && o instanceof AttributeSet) { 787 writeAttributes((AttributeSet)o); 788 } 789 write('>'); 790 } 791 } 792 } 793 794 795 800 private boolean isFormElementWithContent(AttributeSet attr) { 801 if (matchNameAttribute(attr, HTML.Tag.TEXTAREA) || 802 matchNameAttribute(attr, HTML.Tag.SELECT)) { 803 return true; 804 } 805 return false; 806 } 807 808 809 820 private boolean indentNext = false; 821 private boolean indentNeedsIncrementing(Element current, Element next) { 822 if ((next.getParentElement() == current) && !inPre) { 823 if (indentNext) { 824 indentNext = false; 825 return true; 826 } else if (synthesizedElement(next)) { 827 indentNext = true; 828 } else if (!synthesizedElement(current)){ 829 return true; 830 } 831 } 832 return false; 833 } 834 835 839 void writeMaps(Enumeration maps) throws IOException { 840 if (maps != null) { 841 while(maps.hasMoreElements()) { 842 Map map = (Map )maps.nextElement(); 843 String name = map.getName(); 844 845 incrIndent(); 846 indent(); 847 write("<map"); 848 if (name != null) { 849 write(" name=\""); 850 write(name); 851 write("\">"); 852 } 853 else { 854 write('>'); 855 } 856 writeLineSeparator(); 857 incrIndent(); 858 859 AttributeSet[] areas = map.getAreas(); 861 if (areas != null) { 862 for (int counter = 0, maxCounter = areas.length; 863 counter < maxCounter; counter++) { 864 indent(); 865 write("<area"); 866 writeAttributes(areas[counter]); 867 write("></area>"); 868 writeLineSeparator(); 869 } 870 } 871 decrIndent(); 872 indent(); 873 write("</map>"); 874 writeLineSeparator(); 875 decrIndent(); 876 } 877 } 878 } 879 880 885 void writeStyles(StyleSheet sheet) throws IOException { 886 if (sheet != null) { 887 Enumeration styles = sheet.getStyleNames(); 888 if (styles != null) { 889 boolean outputStyle = false; 890 while (styles.hasMoreElements()) { 891 String name = (String )styles.nextElement(); 892 if (!StyleContext.DEFAULT_STYLE.equals(name) && 894 writeStyle(name, sheet.getStyle(name), outputStyle)) { 895 outputStyle = true; 896 } 897 } 898 if (outputStyle) { 899 writeStyleEndTag(); 900 } 901 } 902 } 903 } 904 905 910 boolean writeStyle(String name, Style style, boolean outputStyle) 911 throws IOException { 912 boolean didOutputStyle = false; 913 Enumeration attributes = style.getAttributeNames(); 914 if (attributes != null) { 915 while (attributes.hasMoreElements()) { 916 Object attribute = attributes.nextElement(); 917 if (attribute instanceof CSS.Attribute ) { 918 String value = style.getAttribute(attribute).toString(); 919 if (value != null) { 920 if (!outputStyle) { 921 writeStyleStartTag(); 922 outputStyle = true; 923 } 924 if (!didOutputStyle) { 925 didOutputStyle = true; 926 indent(); 927 write(name); 928 write(" {"); 929 } 930 else { 931 write(";"); 932 } 933 write(' '); 934 write(attribute.toString()); 935 write(": "); 936 write(value); 937 } 938 } 939 } 940 } 941 if (didOutputStyle) { 942 write(" }"); 943 writeLineSeparator(); 944 } 945 return didOutputStyle; 946 } 947 948 void writeStyleStartTag() throws IOException { 949 indent(); 950 write("<style type=\"text/css\">"); 951 incrIndent(); 952 writeLineSeparator(); 953 indent(); 954 write("<!--"); 955 incrIndent(); 956 writeLineSeparator(); 957 } 958 959 void writeStyleEndTag() throws IOException { 960 decrIndent(); 961 indent(); 962 write("-->"); 963 writeLineSeparator(); 964 decrIndent(); 965 indent(); 966 write("</style>"); 967 writeLineSeparator(); 968 indent(); 969 } 970 971 973 982 AttributeSet convertToHTML(AttributeSet from, MutableAttributeSet to) { 983 if (to == null) { 984 to = convAttr; 985 } 986 to.removeAttributes(to); 987 if (writeCSS) { 988 convertToHTML40(from, to); 989 } else { 990 convertToHTML32(from, to); 991 } 992 return to; 993 } 994 995 1000 private boolean writeCSS = false; 1001 1002 1005 private MutableAttributeSet convAttr = new SimpleAttributeSet(); 1006 1007 1011 private MutableAttributeSet oConvAttr = new SimpleAttributeSet(); 1012 1013 1019 private static void convertToHTML32(AttributeSet from, MutableAttributeSet to) { 1020 if (from == null) { 1021 return; 1022 } 1023 Enumeration keys = from.getAttributeNames(); 1024 String value = ""; 1025 while (keys.hasMoreElements()) { 1026 Object key = keys.nextElement(); 1027 if (key instanceof CSS.Attribute ) { 1028 if ((key == CSS.Attribute.FONT_FAMILY) || 1029 (key == CSS.Attribute.FONT_SIZE) || 1030 (key == CSS.Attribute.COLOR)) { 1031 1032 createFontAttribute((CSS.Attribute )key, from, to); 1033 } else if (key == CSS.Attribute.FONT_WEIGHT) { 1034 CSS.FontWeight weightValue = (CSS.FontWeight ) 1036 from.getAttribute(CSS.Attribute.FONT_WEIGHT); 1037 if ((weightValue != null) && (weightValue.getValue() > 400)) { 1038 addAttribute(to, HTML.Tag.B, SimpleAttributeSet.EMPTY); 1039 } 1040 } else if (key == CSS.Attribute.FONT_STYLE) { 1041 String s = from.getAttribute(key).toString(); 1042 if (s.indexOf("italic") >= 0) { 1043 addAttribute(to, HTML.Tag.I, SimpleAttributeSet.EMPTY); 1044 } 1045 } else if (key == CSS.Attribute.TEXT_DECORATION) { 1046 String decor = from.getAttribute(key).toString(); 1047 if (decor.indexOf("underline") >= 0) { 1048 addAttribute(to, HTML.Tag.U, SimpleAttributeSet.EMPTY); 1049 } 1050 if (decor.indexOf("line-through") >= 0) { 1051 addAttribute(to, HTML.Tag.STRIKE, SimpleAttributeSet.EMPTY); 1052 } 1053 } else if (key == CSS.Attribute.VERTICAL_ALIGN) { 1054 String vAlign = from.getAttribute(key).toString(); 1055 if (vAlign.indexOf("sup") >= 0) { 1056 addAttribute(to, HTML.Tag.SUP, SimpleAttributeSet.EMPTY); 1057 } 1058 if (vAlign.indexOf("sub") >= 0) { 1059 addAttribute(to, HTML.Tag.SUB, SimpleAttributeSet.EMPTY); 1060 } 1061 } else if (key == CSS.Attribute.TEXT_ALIGN) { 1062 addAttribute(to, HTML.Attribute.ALIGN, 1063 from.getAttribute(key).toString()); 1064 } else { 1065 if (value.length() > 0) { 1067 value = value + "; "; 1068 } 1069 value = value + key + ": " + from.getAttribute(key); 1070 } 1071 } else { 1072 Object attr = from.getAttribute(key); 1073 if (attr instanceof AttributeSet) { 1074 attr = ((AttributeSet)attr).copyAttributes(); 1075 } 1076 addAttribute(to, key, attr); 1077 } 1078 } 1079 if (value.length() > 0) { 1080 to.addAttribute(HTML.Attribute.STYLE, value); 1081 } 1082 } 1083 1084 1088 private static void addAttribute(MutableAttributeSet to, Object key, Object value) { 1089 Object attr = to.getAttribute(key); 1090 if (attr == null || attr == SimpleAttributeSet.EMPTY) { 1091 to.addAttribute(key, value); 1092 } else { 1093 if (attr instanceof MutableAttributeSet && 1094 value instanceof AttributeSet) { 1095 ((MutableAttributeSet)attr).addAttributes((AttributeSet)value); 1096 } 1097 } 1098 } 1099 1100 1105 private static void createFontAttribute(CSS.Attribute a, AttributeSet from, 1106 MutableAttributeSet to) { 1107 MutableAttributeSet fontAttr = (MutableAttributeSet) 1108 to.getAttribute(HTML.Tag.FONT); 1109 if (fontAttr == null) { 1110 fontAttr = new SimpleAttributeSet(); 1111 to.addAttribute(HTML.Tag.FONT, fontAttr); 1112 } 1113 String htmlValue = from.getAttribute(a).toString(); 1115 if (a == CSS.Attribute.FONT_FAMILY) { 1116 fontAttr.addAttribute(HTML.Attribute.FACE, htmlValue); 1117 } else if (a == CSS.Attribute.FONT_SIZE) { 1118 fontAttr.addAttribute(HTML.Attribute.SIZE, htmlValue); 1119 } else if (a == CSS.Attribute.COLOR) { 1120 fontAttr.addAttribute(HTML.Attribute.COLOR, htmlValue); 1121 } 1122 } 1123 1124 1129 private static void convertToHTML40(AttributeSet from, MutableAttributeSet to) { 1130 Enumeration keys = from.getAttributeNames(); 1131 String value = ""; 1132 while (keys.hasMoreElements()) { 1133 Object key = keys.nextElement(); 1134 if (key instanceof CSS.Attribute ) { 1135 value = value + " " + key + "=" + from.getAttribute(key) + ";"; 1136 } else { 1137 to.addAttribute(key, from.getAttribute(key)); 1138 } 1139 } 1140 if (value.length() > 0) { 1141 to.addAttribute(HTML.Attribute.STYLE, value); 1142 } 1143 } 1144 1145 1152 1156 protected void writeLineSeparator() throws IOException { 1157 boolean oldReplace = replaceEntities; 1158 replaceEntities = false; 1159 super.writeLineSeparator(); 1160 replaceEntities = oldReplace; 1161 } 1162 1163 1168 protected void output(char[] chars, int start, int length) 1169 throws IOException { 1170 if (!replaceEntities) { 1171 super.output(chars, start, length); 1172 return; 1173 } 1174 int last = start; 1175 length += start; 1176 for (int counter = start; counter < length; counter++) { 1177 switch(chars[counter]) { 1180 case '<': 1182 if (counter > last) { 1183 super.output(chars, last, counter - last); 1184 } 1185 last = counter + 1; 1186 output("<"); 1187 break; 1188 case '>': 1189 if (counter > last) { 1190 super.output(chars, last, counter - last); 1191 } 1192 last = counter + 1; 1193 output(">"); 1194 break; 1195 case '&': 1196 if (counter > last) { 1197 super.output(chars, last, counter - last); 1198 } 1199 last = counter + 1; 1200 output("&"); 1201 break; 1202 case '"': 1203 if (counter > last) { 1204 super.output(chars, last, counter - last); 1205 } 1206 last = counter + 1; 1207 output("""); 1208 break; 1209 case '\n': 1211 case '\t': 1212 case '\r': 1213 break; 1214 default: 1215 if (chars[counter] < ' ' || chars[counter] > 127) { 1216 if (counter > last) { 1217 super.output(chars, last, counter - last); 1218 } 1219 last = counter + 1; 1220 output("&#"); 1223 output(String.valueOf((int)chars[counter])); 1224 output(";"); 1225 } 1226 break; 1227 } 1228 } 1229 if (last < length) { 1230 super.output(chars, last, length - last); 1231 } 1232 } 1233 1234 1238 private void output(String string) throws IOException { 1239 int length = string.length(); 1240 if (tempChars == null || tempChars.length < length) { 1241 tempChars = new char[length]; 1242 } 1243 string.getChars(0, length, tempChars, 0); 1244 super.output(tempChars, 0, length); 1245 } 1246} 1247 | Popular Tags |