1 7 package javax.swing.text.rtf; 8 9 import java.io.*; 10 import java.lang.*; 11 12 23 abstract class RTFParser extends AbstractFilter 24 { 25 26 public int level; 27 28 private int state; 29 private StringBuffer currentCharacters; 30 private String pendingKeyword; private int pendingCharacter; 34 private long binaryBytesLeft; ByteArrayOutputStream binaryBuf; 36 private boolean[] savedSpecials; 37 38 41 protected PrintStream warnings; 42 43 private final int S_text = 0; private final int S_backslashed = 1; private final int S_token = 2; private final int S_parameter = 3; 49 private final int S_aftertick = 4; private final int S_aftertickc = 5; 52 private final int S_inblob = 6; 54 57 public abstract boolean handleKeyword(String keyword); 58 61 public abstract boolean handleKeyword(String keyword, int parameter); 62 63 public abstract void handleText(String text); 64 public void handleText(char ch) 65 { handleText(String.valueOf(ch)); } 66 67 public abstract void handleBinaryBlob(byte[] data); 68 70 public abstract void begingroup(); 71 72 public abstract void endgroup(); 73 74 static final boolean rtfSpecialsTable[]; 76 static { 77 rtfSpecialsTable = (boolean[])noSpecialsTable.clone(); 78 rtfSpecialsTable['\n'] = true; 79 rtfSpecialsTable['\r'] = true; 80 rtfSpecialsTable['{'] = true; 81 rtfSpecialsTable['}'] = true; 82 rtfSpecialsTable['\\'] = true; 83 } 84 85 public RTFParser() 86 { 87 currentCharacters = new StringBuffer (); 88 state = S_text; 89 pendingKeyword = null; 90 level = 0; 91 93 specialsTable = rtfSpecialsTable; 94 } 95 96 98 public void writeSpecial(int b) 99 throws IOException 100 { 101 write((char)b); 102 } 103 104 protected void warning(String s) { 105 if (warnings != null) { 106 warnings.println(s); 107 } 108 } 109 110 public void write(String s) 111 throws IOException 112 { 113 if (state != S_text) { 114 int index = 0; 115 int length = s.length(); 116 while(index < length && state != S_text) { 117 write(s.charAt(index)); 118 index ++; 119 } 120 121 if(index >= length) 122 return; 123 124 s = s.substring(index); 125 } 126 127 if (currentCharacters.length() > 0) 128 currentCharacters.append(s); 129 else 130 handleText(s); 131 } 132 133 public void write(char ch) 134 throws IOException 135 { 136 boolean ok; 137 138 switch (state) 139 { 140 case S_text: 141 if (ch == '\n' || ch == '\r') { 142 break; } else if (ch == '{') { 144 if (currentCharacters.length() > 0) { 145 handleText(currentCharacters.toString()); 146 currentCharacters = new StringBuffer (); 147 } 148 level ++; 149 begingroup(); 150 } else if(ch == '}') { 151 if (currentCharacters.length() > 0) { 152 handleText(currentCharacters.toString()); 153 currentCharacters = new StringBuffer (); 154 } 155 if (level == 0) 156 throw new IOException("Too many close-groups in RTF text"); 157 endgroup(); 158 level --; 159 } else if(ch == '\\') { 160 if (currentCharacters.length() > 0) { 161 handleText(currentCharacters.toString()); 162 currentCharacters = new StringBuffer (); 163 } 164 state = S_backslashed; 165 } else { 166 currentCharacters.append(ch); 167 } 168 break; 169 case S_backslashed: 170 if (ch == '\'') { 171 state = S_aftertick; 172 break; 173 } 174 if (!Character.isLetter(ch)) { 175 char newstring[] = new char[1]; 176 newstring[0] = ch; 177 if (!handleKeyword(new String (newstring))) { 178 warning("Unknown keyword: " + newstring + " (" + (byte)ch + ")"); 179 } 180 state = S_text; 181 pendingKeyword = null; 182 183 break; 184 } 185 186 state = S_token; 187 188 case S_token: 189 if (Character.isLetter(ch)) { 190 currentCharacters.append(ch); 191 } else { 192 pendingKeyword = currentCharacters.toString(); 193 currentCharacters = new StringBuffer (); 194 195 if (Character.isDigit(ch) || (ch == '-')) { 197 state = S_parameter; 198 currentCharacters.append(ch); 199 } else { 200 ok = handleKeyword(pendingKeyword); 201 if (!ok) 202 warning("Unknown keyword: " + pendingKeyword); 203 pendingKeyword = null; 204 state = S_text; 205 206 if (!Character.isWhitespace(ch)) 208 write(ch); 209 } 210 } 211 break; 212 case S_parameter: 213 if (Character.isDigit(ch)) { 214 currentCharacters.append(ch); 215 } else { 216 217 if (pendingKeyword.equals("bin")) { 218 long parameter = Long.parseLong(currentCharacters.toString()); 219 pendingKeyword = null; 220 state = S_inblob; 221 binaryBytesLeft = parameter; 222 if (binaryBytesLeft > Integer.MAX_VALUE) 223 binaryBuf = new ByteArrayOutputStream(Integer.MAX_VALUE); 224 else 225 binaryBuf = new ByteArrayOutputStream((int)binaryBytesLeft); 226 savedSpecials = specialsTable; 227 specialsTable = allSpecialsTable; 228 break; 229 } 230 231 int parameter = Integer.parseInt(currentCharacters.toString()); 232 ok = handleKeyword(pendingKeyword, parameter); 233 if (!ok) 234 warning("Unknown keyword: " + pendingKeyword + 235 " (param " + currentCharacters + ")"); 236 pendingKeyword = null; 237 currentCharacters = new StringBuffer (); 238 state = S_text; 239 240 if (!Character.isWhitespace(ch)) 242 write(ch); 243 } 244 break; 245 case S_aftertick: 246 if (Character.digit(ch, 16) == -1) 247 state = S_text; 248 else { 249 pendingCharacter = Character.digit(ch, 16); 250 state = S_aftertickc; 251 } 252 break; 253 case S_aftertickc: 254 state = S_text; 255 if (Character.digit(ch, 16) != -1) 256 { 257 pendingCharacter = pendingCharacter * 16 + Character.digit(ch, 16); 258 ch = translationTable[pendingCharacter]; 259 if (ch != 0) 260 handleText(ch); 261 } 262 break; 263 case S_inblob: 264 binaryBuf.write(ch); 265 binaryBytesLeft --; 266 if (binaryBytesLeft == 0) { 267 state = S_text; 268 specialsTable = savedSpecials; 269 savedSpecials = null; 270 handleBinaryBlob(binaryBuf.toByteArray()); 271 binaryBuf = null; 272 } 273 } 274 } 275 276 280 public void flush() 281 throws IOException 282 { 283 super.flush(); 284 285 if (state == S_text && currentCharacters.length() > 0) { 286 handleText(currentCharacters.toString()); 287 currentCharacters = new StringBuffer (); 288 } 289 } 290 291 293 public void close() 294 throws IOException 295 { 296 flush(); 297 298 if (state != S_text || level > 0) { 299 warning("Truncated RTF file."); 300 301 302 303 304 306 while (level > 0) { 307 endgroup(); 308 level --; 309 } 310 } 311 312 super.close(); 313 } 314 315 } 316 317 | Popular Tags |