1 package net.sf.saxon.event; 2 import net.sf.saxon.trans.XPathException; 3 4 import java.util.Properties ; 5 6 15 16 17 public class HTMLIndenter extends ProxyReceiver { 18 19 private int level = 0; 20 private int indentSpaces = 3; 21 private String indentChars = " "; 22 private boolean sameLine = false; 23 private boolean isInlineTag = false; 24 private boolean inFormattedTag = false; 25 private boolean afterInline = false; 26 private boolean afterFormatted = true; private int[] propertyStack = new int[20]; 28 29 30 33 protected static String [] inlineTags = { 34 "tt", "i", "b", "u", "s", "strike", "big", "small", "em", "strong", "dfn", "code", "samp", 35 "kbd", "var", "cite", "abbr", "acronym", "a", "img", "applet", "object", "font", 36 "basefont", "br", "script", "map", "q", "sub", "sup", "span", "bdo", "iframe", "input", 37 "select", "textarea", "label", "button", "ins", "del" }; 38 39 42 private static HTMLTagHashSet inlineTable = new HTMLTagHashSet(101); 43 44 static { 45 for (int j=0; j<inlineTags.length; j++) { 46 inlineTable.add(inlineTags[j]); 47 } 48 } 49 50 protected static final int IS_INLINE = 1; 51 protected static final int IS_FORMATTED = 2; 52 53 59 protected int classifyTag(int nameCode) { 60 int r = 0; 61 String tag = getNamePool().getDisplayName(nameCode); 62 if (inlineTable.contains(tag)) { 63 r |= IS_INLINE; 64 } 65 if (formattedTable.contains(tag)) { 66 r |= IS_FORMATTED; 67 } 68 return r; 69 } 70 71 73 private static HTMLTagHashSet formattedTable = new HTMLTagHashSet(23); 74 protected static String [] formattedTags = {"pre", "script", "style", "textarea", "xmp"}; 75 77 static { 78 for (int i=0; i<formattedTags.length; i++) { 79 formattedTable.add(formattedTags[i]); 80 } 81 } 82 83 public HTMLIndenter() {} 84 85 88 89 public void setOutputProperties(Properties props) { 90 String s = props.getProperty(SaxonOutputKeys.INDENT_SPACES); 91 if (s==null) { 92 indentSpaces = 3; 93 } else { 94 try { 95 indentSpaces = Integer.parseInt(s); 96 } catch (NumberFormatException err) { 97 indentSpaces = 3; 98 } 99 } 100 } 101 102 105 106 public void startElement(int nameCode, int typeCode, int locationId, int properties) throws XPathException { 107 int tagProps = classifyTag(nameCode); 108 if (level >= propertyStack.length) { 109 int[] p2 = new int[level*2]; 110 System.arraycopy(propertyStack, 0, p2, 0, propertyStack.length); 111 propertyStack = p2; 112 } 113 propertyStack[level] = tagProps; 114 isInlineTag = (tagProps & IS_INLINE) != 0; 115 inFormattedTag = inFormattedTag || ((tagProps & IS_FORMATTED) != 0); 116 if (!isInlineTag && !inFormattedTag && 117 !afterInline && !afterFormatted) { 118 indent(); 119 } 120 121 super.startElement(nameCode, typeCode, locationId, properties); 122 level++; 123 sameLine = true; 124 afterInline = false; 125 afterFormatted = false; 126 } 127 128 131 132 public void endElement() throws XPathException { 133 level--; 134 boolean thisInline = (propertyStack[level] & IS_INLINE) != 0; 135 boolean thisFormatted = (propertyStack[level] & IS_FORMATTED) != 0; 136 if (!thisInline && !thisFormatted && !afterInline && 137 !sameLine && !afterFormatted && !inFormattedTag) { 138 indent(); 139 afterInline = false; 140 afterFormatted = false; 141 } else { 142 afterInline = thisInline; 143 afterFormatted = thisFormatted; 144 } 145 super.endElement(); 146 inFormattedTag = inFormattedTag && !thisFormatted; 147 sameLine = false; 148 } 149 150 153 154 public void characters(CharSequence chars, int locationId, int properties) throws XPathException { 155 if (inFormattedTag) { 156 super.characters(chars, locationId, properties); 157 } else { 158 int lastNL = 0; 159 160 for (int i=0; i<chars.length(); i++) { 161 if (chars.charAt(i)=='\n' || (i-lastNL > 120 && chars.charAt(i)==' ')) { 162 sameLine = false; 163 super.characters(chars.subSequence(lastNL, i), locationId, properties); 164 indent(); 165 lastNL = i+1; 166 while (lastNL<chars.length() && chars.charAt(lastNL)==' ') { 167 lastNL++; 168 } 169 } 170 } 171 if (lastNL < chars.length()) { 172 super.characters(chars.subSequence(lastNL, chars.length()), locationId, properties); 173 } 174 } 175 afterInline = false; 176 } 177 178 181 182 public void comment(CharSequence chars, int locationId, int properties) throws XPathException { 183 indent(); 184 super.comment(chars, locationId, properties); 185 } 186 187 190 191 private void indent() throws XPathException { 192 int spaces = level * indentSpaces; 193 while (spaces > indentChars.length()) { 194 indentChars += indentChars; 195 } 196 super.characters("\n", 0, 0); 197 super.characters(indentChars.subSequence(0, spaces), 0, 0); 198 sameLine = false; 199 } 200 201 }; 202 203 221 | Popular Tags |