package javax.swing.text.html; import java.awt.Color; import javax.swing.text.StyleContext; import javax.swing.text.ElementIterator; import javax.swing.text.AbstractDocument; import javax.swing.text.Style; import javax.swing.text.DefaultStyledDocument; import javax.swing.text.Element; import java.util.Enumeration; import javax.swing.text.StyleConstants; import javax.swing.text.BadLocationException; import java.io.IOException; import javax.swing.text.StyledDocument; import java.io.Writer; import java.util.Hashtable; import javax.swing.text.AttributeSet; import javax.swing.text.AbstractWriter; public class MinimalHTMLWriter extends AbstractWriter { private static final int BOLD = 1; private static final int ITALIC = 2; private static final int UNDERLINE = 4; private static final CSS css; private int fontMask; int startOffset; int endOffset; private AttributeSet fontAttributes; private Hashtable styleNameMapping; public MinimalHTMLWriter(Writer w, StyledDocument doc) { super(w, doc); this.fontMask = 0; this.startOffset = 0; this.endOffset = 0; } public MinimalHTMLWriter(Writer w, StyledDocument doc, int pos, int len) { super(w, doc, pos, len); this.fontMask = 0; this.startOffset = 0; this.endOffset = 0; } public void write() throws IOException, BadLocationException { this.styleNameMapping = new Hashtable(); this.writeStartTag(""); this.writeHeader(); this.writeBody(); this.writeEndTag(""); } @Override protected void writeAttributes(AttributeSet set) throws IOException { Enumeration attributeNames = set.getAttributeNames(); while (attributeNames.hasMoreElements()) { Object nextElement = attributeNames.nextElement(); if (nextElement instanceof StyleConstants.ParagraphConstants || nextElement instanceof StyleConstants.CharacterConstants || nextElement instanceof StyleConstants.FontConstants || nextElement instanceof StyleConstants.ColorConstants) { this.indent(); super.write(nextElement.toString()); super.write(':'); super.write(MinimalHTMLWriter.css.styleConstantsValueToCSSValue((StyleConstants)nextElement, set.getAttribute(nextElement)).toString()); super.write(';'); super.write('\n'); } else { continue; } } } @Override protected void text(Element elem) throws IOException, BadLocationException { String content = this.getText(elem); if (content.length() > 0 && content.charAt(content.length() - 1) == '\n') { content = content.substring(0, content.length() - 1); } if (content.length() > 0) { super.write(content); } } protected void writeStartTag(String content) throws IOException { this.indent(); super.write(content); super.write('\n'); this.incrIndent(); } protected void writeEndTag(String content) throws IOException { this.decrIndent(); this.indent(); super.write(content); super.write('\n'); } protected void writeHeader() throws IOException { this.writeStartTag(""); this.writeStartTag(""); this.writeEndTag(""); } protected void writeStyles() throws IOException { DefaultStyledDocument defaultStyledDocument = (DefaultStyledDocument)this.getDocument(); Enumeration styleNames = defaultStyledDocument.getStyleNames(); while (styleNames.hasMoreElements()) { Style style = defaultStyledDocument.getStyle((String)styleNames.nextElement()); if (style.getAttributeCount() == 1 && style.isDefined(StyleConstants.NameAttribute)) { continue; } this.indent(); super.write("p." + this.addStyleName(style.getName())); super.write(" {\n"); this.incrIndent(); this.writeAttributes(style); this.decrIndent(); this.indent(); super.write("}\n"); } } protected void writeBody() throws IOException, BadLocationException { ElementIterator elementIterator = this.getElementIterator(); elementIterator.current(); this.writeStartTag(""); int n = 0; Element next; while ((next = elementIterator.next()) != null) { if (!this.inRange(next)) { continue; } if ((next instanceof AbstractDocument.BranchElement)) { if (n != 0) { this.writeEndParagraph(); n = 0; this.fontMask = 0; } this.writeStartParagraph(next); } else if (this.isText(next)) { this.writeContent(next, n == 0); n = 1; } else { this.writeLeaf(next); n = 1; } } if (n != 0) { this.writeEndParagraph(); } this.writeEndTag(""); } protected void writeEndParagraph() throws IOException { this.writeEndMask(this.fontMask); if (this.inFontTag()) { this.endSpanTag(); } else { super.write('\n'); } this.writeEndTag("

"); } protected void writeStartParagraph(Element element) throws IOException { Object attribute = element.getAttributes().getAttribute(StyleConstants.ResolveAttribute); if ((attribute instanceof StyleContext.NamedStyle)) { this.writeStartTag("

"); } else { this.writeStartTag("

"); } } protected void writeLeaf(Element element) throws IOException { this.indent(); if (element.getName() == "icon") { this.writeImage(element); } else if (element.getName() == "component") { this.writeComponent(element); } } protected void writeImage(Element element) throws IOException { } protected void writeComponent(Element element) throws IOException { } protected boolean isText(Element element) { return element.getName() == "content"; } protected void writeContent(Element element, boolean b) throws IOException, BadLocationException { AttributeSet attributes = element.getAttributes(); this.writeNonHTMLAttributes(attributes); if (b) { this.indent(); } this.writeHTMLTags(attributes); this.text(element); } protected void writeHTMLTags(AttributeSet fontMask) throws IOException { int fontMask2 = this.fontMask; this.setFontMask(fontMask); int n = 0; int n2 = 0; if ((fontMask2 & 0x1) != 0x0) { if ((this.fontMask & 0x1) == 0x0) { n |= 0x1; } } else if ((this.fontMask & 0x1) != 0x0) { n2 |= 0x1; } if ((fontMask2 & 0x2) != 0x0) { if ((this.fontMask & 0x2) == 0x0) { n |= 0x2; } } else if ((this.fontMask & 0x2) != 0x0) { n2 |= 0x2; } if ((fontMask2 & 0x4) != 0x0) { if ((this.fontMask & 0x4) == 0x0) { n |= 0x4; } } else if ((this.fontMask & 0x4) != 0x0) { n2 |= 0x4; } this.writeEndMask(n); this.writeStartMask(n2); } private void setFontMask(AttributeSet a) { if (StyleConstants.isBold(a)) { this.fontMask |= 0x1; } if (StyleConstants.isItalic(a)) { this.fontMask |= 0x2; } if (StyleConstants.isUnderline(a)) { this.fontMask |= 0x4; } } private void writeStartMask(int n) throws IOException { if (n != 0) { if ((n & 0x4) != 0x0) { super.write(""); } if ((n & 0x2) != 0x0) { super.write(""); } if ((n & 0x1) != 0x0) { super.write(""); } } } private void writeEndMask(int n) throws IOException { if (n != 0) { if ((n & 0x1) != 0x0) { super.write(""); } if ((n & 0x2) != 0x0) { super.write(""); } if ((n & 0x4) != 0x0) { super.write(""); } } } protected void writeNonHTMLAttributes(AttributeSet fontAttributes) throws IOException { String str = ""; String s = "; "; if (this.inFontTag() && this.fontAttributes.isEqual(fontAttributes)) { return; } int n = 1; Color color = (Color)fontAttributes.getAttribute(StyleConstants.Foreground); if (color != null) { str = str + "color: " + MinimalHTMLWriter.css.styleConstantsValueToCSSValue((StyleConstants)StyleConstants.Foreground, color); n = 0; } Integer n2 = (Integer)fontAttributes.getAttribute(StyleConstants.FontSize); if (n2 != null) { if (n == 0) { str += s; } str = str + "font-size: " + (int)n2 + "pt"; n = 0; } String str2 = (String)fontAttributes.getAttribute(StyleConstants.FontFamily); if (str2 != null) { if (n == 0) { str += s; } str = str + "font-family: " + str2; } if (str.length() > 0) { if (this.fontMask != 0) { this.writeEndMask(this.fontMask); this.fontMask = 0; } this.startSpanTag(str); this.fontAttributes = fontAttributes; } else if (this.fontAttributes != null) { this.writeEndMask(this.fontMask); this.fontMask = 0; this.endSpanTag(); } return; } protected boolean inFontTag() { return this.fontAttributes != null; } protected void endFontTag() throws IOException { super.write('\n'); this.writeEndTag(""); this.fontAttributes = null; } protected void startFontTag(String str) throws IOException { boolean n = false; if (this.inFontTag()) { this.endFontTag(); n = true; } this.writeStartTag(""); if (!(n == 0)) { this.indent(); } } private void startSpanTag(String str) throws IOException { boolean n = false; if (this.inFontTag()) { this.endSpanTag(); n = true; } this.writeStartTag(""); if (!(n == 0)) { this.indent(); } } private void endSpanTag() throws IOException { super.write('\n'); this.writeEndTag(""); this.fontAttributes = null; } private String addStyleName(String string) { if (this.styleNameMapping == null) { return string; } Object o = null; for (int i = string.length() - 1; i >= 0; --i) { if (!this.isValidCharacter(string.charAt(i))) { if (o == null) { o = new StringBuilder(string); } o.setCharAt(i, 'a'); } } for (string = ((o != null) ? o.toString() : string); this.styleNameMapping.get(string) != null; string += 'x') {} this.styleNameMapping.put(string, string); return string; } private String mapStyleName(String key) { if (this.styleNameMapping == null) { return key; } String s = (String)this.styleNameMapping.get(key); return (s == null) ? key : s; } private boolean isValidCharacter(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } static { css = new CSS(); } }