1 21 22 package org.armedbear.j; 23 24 public final class HtmlFormatter extends Formatter implements Constants 25 { 26 private static final int HTML_FORMAT_FIRST = JavaFormatter.JAVA_FORMAT_LAST + 1; 28 29 private static final int HTML_FORMAT_TEXT = HTML_FORMAT_FIRST; 30 private static final int HTML_FORMAT_COMMENT = HTML_FORMAT_FIRST + 1; 31 private static final int HTML_FORMAT_TAG = HTML_FORMAT_FIRST + 2; 32 private static final int HTML_FORMAT_TAG_IMAGE = HTML_FORMAT_FIRST + 3; 33 private static final int HTML_FORMAT_TAG_ANCHOR = HTML_FORMAT_FIRST + 4; 34 private static final int HTML_FORMAT_TAG_TABLE = HTML_FORMAT_FIRST + 5; 35 private static final int HTML_FORMAT_TAG_TABLE_ROW = HTML_FORMAT_FIRST + 6; 36 private static final int HTML_FORMAT_TAG_TABLE_DATA = HTML_FORMAT_FIRST + 7; 37 private static final int HTML_FORMAT_SCRIPT = HTML_FORMAT_FIRST + 8; 38 39 private StringBuffer sb = new StringBuffer (); 40 41 private JavaFormatter javaFormatter; 42 43 public HtmlFormatter(Buffer buffer) 44 { 45 this.buffer = buffer; 46 javaFormatter = new JavaFormatter(buffer, LANGUAGE_JAVASCRIPT); 47 } 48 49 private void endToken(int state) 50 { 51 if (sb.length() > 0) { 52 int format = HTML_FORMAT_TEXT; 53 switch (state) { 54 case STATE_NEUTRAL: 55 break; 56 case STATE_TAG: 57 format = HTML_FORMAT_TAG; 58 break; 59 case STATE_HTML_COMMENT: 60 format = HTML_FORMAT_COMMENT; 61 break; 62 case STATE_SCRIPT: 63 format = HTML_FORMAT_SCRIPT; 64 break; 65 default: 66 break; 67 } 68 addSegment(sb.toString(), format); 69 sb.setLength(0); 70 } 71 } 72 73 public LineSegmentList formatLine(Line line) 74 { 75 if (line == null) { 76 clearSegmentList(); 77 addSegment("", HTML_FORMAT_TEXT); 78 return segmentList; 79 } 80 final int flags = line.flags(); 81 if (flags == STATE_SCRIPT || flags == STATE_COMMENT) { 82 final String trim = line.trim(); 83 if (trim.startsWith("<!--")) { 84 clearSegmentList(); 85 addSegment(line.getText(), HTML_FORMAT_COMMENT); 86 return segmentList; 87 } 88 if (!trim.regionMatches(true, 0, "</script>", 0, 9)) 89 return javaFormatter.formatLine(line); 90 } 91 parseLine(line.getText(), flags); 92 for (int i = 0; i < segmentList.size(); i++) { 93 LineSegment segment = segmentList.getSegment(i); 94 if (segment.getFormat() != HTML_FORMAT_TAG) 95 continue; 96 String token = segment.getText().toLowerCase(); 97 if (token.startsWith("<a ") || token.equals("<a>")|| token.equals("</a>")) 98 segment.setFormat(HTML_FORMAT_TAG_ANCHOR); 99 else if (token.startsWith("<img ") || token.equals("<img>")) 100 segment.setFormat(HTML_FORMAT_TAG_IMAGE); 101 else if (token.startsWith("<table ") || token.equals("<table>") || token.equals("</table>")) 102 segment.setFormat(HTML_FORMAT_TAG_TABLE); 103 else if (token.startsWith("<tr ") || token.equals("<tr>") || token.equals("</tr>")) 104 segment.setFormat(HTML_FORMAT_TAG_TABLE_ROW); 105 else if (token.startsWith("<td ") || token.equals("<td>") || token.equals("</td>")) 106 segment.setFormat(HTML_FORMAT_TAG_TABLE_DATA); 107 } 108 return segmentList; 109 } 110 111 private void parseLine(String text, int state) 112 { 113 if (Editor.tabsAreVisible()) 114 text = Utilities.makeTabsVisible(text, buffer.getTabWidth()); 115 else 116 text = Utilities.detab(text, buffer.getTabWidth()); 117 clearSegmentList(); 118 sb.setLength(0); 119 int i = 0; 120 final int limit = text.length(); 121 while (i < limit) { 122 char c = text.charAt(i); 123 if (state == STATE_HTML_COMMENT) { 124 if (i < limit-2 && text.substring(i, i+3).equals("-->")) { 125 sb.append("-->"); 126 endToken(state); 127 state = STATE_NEUTRAL; 128 i += 3; 129 } else { 130 sb.append(c); 131 ++i; 132 } 133 continue; 134 } 135 if (state == STATE_TAG) { 136 if (c == '>') { 137 sb.append(c); 138 endToken(state); 139 state = STATE_NEUTRAL; 140 } else 141 sb.append(c); 142 ++i; 143 continue; 144 } 145 if (state == STATE_SCRIPT) { 146 if (c == '<') { 147 if (text.regionMatches(true, i, "</script>", 0, 4)) { 148 endToken(state); 149 state = STATE_TAG; 150 sb.append(text.substring(i, i+9)); 151 endToken(state); 152 state = STATE_NEUTRAL; 153 i += 9; 154 continue; 155 } 156 } 157 sb.append(c); 158 ++i; 159 continue; 160 } 161 if (state == STATE_SCRIPT_TAG) { 162 if (c == '>') { 163 sb.append(c); 164 endToken(state); 165 state = STATE_SCRIPT; 166 } else 167 sb.append(c); 168 ++i; 169 continue; 170 } 171 if (c == '<') { 173 endToken(state); 174 if (text.regionMatches(i, "<!--", 0, 4)) { 175 state = STATE_HTML_COMMENT; 176 sb.append("<!--"); 177 i += 4; 178 continue; 179 } 180 sb.append(c); 181 state = STATE_TAG; 182 } else 183 sb.append(c); 184 ++i; 185 } 186 endToken(state); 187 } 188 189 public boolean parseBuffer() 190 { 191 Line line = buffer.getFirstLine(); 192 if (line == null) 193 return false; 194 Position pos = new Position(line, 0); 195 boolean changed = false; 196 int state = STATE_NEUTRAL; 197 while (line != null) { 198 int oldflags = line.flags(); 199 if (state != oldflags) { 200 line.setFlags(state); 201 changed = true; 202 } 203 final int limit = line.length(); 204 for (int i = 0; i < limit; i++) { 205 char c = line.charAt(i); 206 if (state == STATE_HTML_COMMENT) { 207 if (c == '-') { 208 pos.moveTo(line, i); 209 if (pos.lookingAt("-->")) { 210 state = STATE_NEUTRAL; 211 i += 2; 212 continue; 213 } 214 } 215 continue; 216 } 217 if (state == STATE_SCRIPT_TAG) { 218 if (c == '>') { 219 state = STATE_SCRIPT; 220 continue; 221 } 222 } 223 if (state == STATE_TAG) { 224 if (c == '>') { 225 state = STATE_NEUTRAL; 226 continue; 227 } 228 } 229 if (state == STATE_SCRIPT) { 230 if (c == '<') { 231 pos.moveTo(line, i); 232 if (pos.lookingAtIgnoreCase("</script>")) { 233 state = STATE_NEUTRAL; 234 i += 8; 235 } 236 } else if (c == '/' && i < limit-1) { 237 c = line.charAt(i+1); 238 if (c == '*') { 239 pos.moveTo(line, i); 240 state = STATE_COMMENT; 241 ++i; 242 } 243 } 244 continue; 245 } 246 if (state == STATE_COMMENT) { 247 if (c == '*' && i < limit-1) { 248 c = line.charAt(i+1); 249 if (c == '/') { 250 pos.moveTo(line, i); 251 state = STATE_SCRIPT; 252 ++i; 253 } 254 } 255 continue; 256 } 257 if (c == '<') { 259 pos.moveTo(line, i); 260 if (pos.lookingAt("<!--")) { 261 state = STATE_HTML_COMMENT; 262 i += 3; 263 continue; 264 } 265 if (pos.lookingAtIgnoreCase("<script>")) { 266 state = STATE_SCRIPT; 267 i += 7; 268 continue; 269 } 270 if (pos.lookingAtIgnoreCase("<script ")) { 271 state = STATE_SCRIPT_TAG; 272 i += 7; 273 continue; 274 } 275 state = STATE_TAG; 276 continue; 277 } 278 } 279 line = line.next(); 280 } 281 buffer.setNeedsParsing(false); 282 return changed; 283 } 284 285 public FormatTable getFormatTable() 286 { 287 if (formatTable == null) { 288 formatTable = javaFormatter.getFormatTable(); 289 formatTable.setModeName("HtmlMode"); 290 formatTable.addEntryFromPrefs(HTML_FORMAT_TEXT, "text"); 291 formatTable.addEntryFromPrefs(HTML_FORMAT_COMMENT, "comment"); 292 formatTable.addEntryFromPrefs(HTML_FORMAT_TAG, "tag"); 293 formatTable.addEntryFromPrefs(HTML_FORMAT_TAG_IMAGE, "image"); 294 formatTable.addEntryFromPrefs(HTML_FORMAT_TAG_ANCHOR, "anchor"); 295 formatTable.addEntryFromPrefs(HTML_FORMAT_TAG_TABLE, "table"); 296 formatTable.addEntryFromPrefs(HTML_FORMAT_TAG_TABLE_ROW, "tableRow"); 297 formatTable.addEntryFromPrefs(HTML_FORMAT_TAG_TABLE_DATA, "tableData"); 298 formatTable.addEntryFromPrefs(HTML_FORMAT_SCRIPT, "script"); 299 } 300 return formatTable; 301 } 302 303 public void reset() 304 { 305 javaFormatter.reset(); 306 super.reset(); 307 } 308 } 309 | Popular Tags |