< prev index next >

src/java.desktop/share/classes/javax/swing/text/rtf/RTFParser.java

Print this page




  37  *
  38  * @see AbstractFilter
  39  * @see RTFFilter
  40  */
  41 abstract class RTFParser extends AbstractFilter
  42 {
  43   /** The current RTF group nesting level. */
  44   public int level;
  45 
  46   private int state;
  47   private StringBuffer currentCharacters;
  48   private String pendingKeyword;                // where keywords go while we
  49                                                 // read their parameters
  50   private int pendingCharacter;                 // for the \'xx construct
  51 
  52   private long binaryBytesLeft;                  // in a \bin blob?
  53   ByteArrayOutputStream binaryBuf;
  54   private boolean[] savedSpecials;
  55 
  56   /** A stream to which to write warnings and debugging information
  57    *  while parsing. This is set to <code>System.out</code> to log
  58    *  any anomalous information to stdout. */
  59   protected PrintStream warnings;
  60 
  61   // value for the 'state' variable
  62   private final int S_text = 0;          // reading random text
  63   private final int S_backslashed = 1;   // read a backslash, waiting for next
  64   private final int S_token = 2;         // reading a multicharacter token
  65   private final int S_parameter = 3;     // reading a token's parameter
  66 
  67   private final int S_aftertick = 4;     // after reading \'
  68   private final int S_aftertickc = 5;    // after reading \'x
  69 
  70   private final int S_inblob = 6;        // in a \bin blob
  71 
  72   /** Implemented by subclasses to interpret a parameter-less RTF keyword.
  73    *  The keyword is passed without the leading '/' or any delimiting
  74    *  whitespace. */
  75   public abstract boolean handleKeyword(String keyword);
  76   /** Implemented by subclasses to interpret a keyword with a parameter.
  77    *  @param keyword   The keyword, as with <code>handleKeyword(String)</code>.
  78    *  @param parameter The parameter following the keyword. */
  79   public abstract boolean handleKeyword(String keyword, int parameter);
  80   /** Implemented by subclasses to interpret text from the RTF stream. */
  81   public abstract void handleText(String text);
  82   public void handleText(char ch)
  83   { handleText(String.valueOf(ch)); }
  84   /** Implemented by subclasses to handle the contents of the \bin keyword. */
  85   public abstract void handleBinaryBlob(byte[] data);
  86   /** Implemented by subclasses to react to an increase
  87    *  in the nesting level. */
  88   public abstract void begingroup();
  89   /** Implemented by subclasses to react to the end of a group. */
  90   public abstract void endgroup();
  91 
  92   // table of non-text characters in rtf
  93   static final boolean rtfSpecialsTable[];
  94   static {
  95     rtfSpecialsTable = noSpecialsTable.clone();
  96     rtfSpecialsTable['\n'] = true;
  97     rtfSpecialsTable['\r'] = true;


 290             binaryBuf = null;
 291         }
 292       }
 293   }
 294 
 295   /** Flushes any buffered but not yet written characters.
 296    *  Subclasses which override this method should call this
 297    *  method <em>before</em> flushing
 298    *  any of their own buffers. */
 299   public void flush()
 300     throws IOException
 301   {
 302     super.flush();
 303 
 304     if (state == S_text && currentCharacters.length() > 0) {
 305       handleText(currentCharacters.toString());
 306       currentCharacters = new StringBuffer();
 307     }
 308   }
 309 
 310   /** Closes the parser. Currently, this simply does a <code>flush()</code>,
 311    *  followed by some minimal consistency checks. */
 312   public void close()
 313     throws IOException
 314   {
 315     flush();
 316 
 317     if (state != S_text || level > 0) {
 318       warning("Truncated RTF file.");
 319 
 320       /* TODO: any sane way to handle termination in a non-S_text state? */
 321       /* probably not */
 322 
 323       /* this will cause subclasses to behave more reasonably
 324          some of the time */
 325       while (level > 0) {
 326           endgroup();
 327           level --;
 328       }
 329     }
 330 


  37  *
  38  * @see AbstractFilter
  39  * @see RTFFilter
  40  */
  41 abstract class RTFParser extends AbstractFilter
  42 {
  43   /** The current RTF group nesting level. */
  44   public int level;
  45 
  46   private int state;
  47   private StringBuffer currentCharacters;
  48   private String pendingKeyword;                // where keywords go while we
  49                                                 // read their parameters
  50   private int pendingCharacter;                 // for the \'xx construct
  51 
  52   private long binaryBytesLeft;                  // in a \bin blob?
  53   ByteArrayOutputStream binaryBuf;
  54   private boolean[] savedSpecials;
  55 
  56   /** A stream to which to write warnings and debugging information
  57    *  while parsing. This is set to {@code System.out} to log
  58    *  any anomalous information to stdout. */
  59   protected PrintStream warnings;
  60 
  61   // value for the 'state' variable
  62   private final int S_text = 0;          // reading random text
  63   private final int S_backslashed = 1;   // read a backslash, waiting for next
  64   private final int S_token = 2;         // reading a multicharacter token
  65   private final int S_parameter = 3;     // reading a token's parameter
  66 
  67   private final int S_aftertick = 4;     // after reading \'
  68   private final int S_aftertickc = 5;    // after reading \'x
  69 
  70   private final int S_inblob = 6;        // in a \bin blob
  71 
  72   /** Implemented by subclasses to interpret a parameter-less RTF keyword.
  73    *  The keyword is passed without the leading '/' or any delimiting
  74    *  whitespace. */
  75   public abstract boolean handleKeyword(String keyword);
  76   /** Implemented by subclasses to interpret a keyword with a parameter.
  77    *  @param keyword   The keyword, as with {@code handleKeyword(String)}.
  78    *  @param parameter The parameter following the keyword. */
  79   public abstract boolean handleKeyword(String keyword, int parameter);
  80   /** Implemented by subclasses to interpret text from the RTF stream. */
  81   public abstract void handleText(String text);
  82   public void handleText(char ch)
  83   { handleText(String.valueOf(ch)); }
  84   /** Implemented by subclasses to handle the contents of the \bin keyword. */
  85   public abstract void handleBinaryBlob(byte[] data);
  86   /** Implemented by subclasses to react to an increase
  87    *  in the nesting level. */
  88   public abstract void begingroup();
  89   /** Implemented by subclasses to react to the end of a group. */
  90   public abstract void endgroup();
  91 
  92   // table of non-text characters in rtf
  93   static final boolean rtfSpecialsTable[];
  94   static {
  95     rtfSpecialsTable = noSpecialsTable.clone();
  96     rtfSpecialsTable['\n'] = true;
  97     rtfSpecialsTable['\r'] = true;


 290             binaryBuf = null;
 291         }
 292       }
 293   }
 294 
 295   /** Flushes any buffered but not yet written characters.
 296    *  Subclasses which override this method should call this
 297    *  method <em>before</em> flushing
 298    *  any of their own buffers. */
 299   public void flush()
 300     throws IOException
 301   {
 302     super.flush();
 303 
 304     if (state == S_text && currentCharacters.length() > 0) {
 305       handleText(currentCharacters.toString());
 306       currentCharacters = new StringBuffer();
 307     }
 308   }
 309 
 310   /** Closes the parser. Currently, this simply does a {@code flush()},
 311    *  followed by some minimal consistency checks. */
 312   public void close()
 313     throws IOException
 314   {
 315     flush();
 316 
 317     if (state != S_text || level > 0) {
 318       warning("Truncated RTF file.");
 319 
 320       /* TODO: any sane way to handle termination in a non-S_text state? */
 321       /* probably not */
 322 
 323       /* this will cause subclasses to behave more reasonably
 324          some of the time */
 325       while (level > 0) {
 326           endgroup();
 327           level --;
 328       }
 329     }
 330 
< prev index next >