jdk/src/share/classes/javax/swing/text/rtf/RTFParser.java
author duke
Sat, 01 Dec 2007 00:00:00 +0000
changeset 2 90ce3da70b43
child 1287 a04aca99c77a
permissions -rw-r--r--
Initial load
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
     2
 * Copyright 1997-2000 Sun Microsystems, Inc.  All Rights Reserved.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Sun designates this
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 * by Sun in the LICENSE file that accompanied this code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 * CA 95054 USA or visit www.sun.com if you need additional information or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 * have any questions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
package javax.swing.text.rtf;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
import java.io.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.lang.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
 * <b>RTFParser</b> is a subclass of <b>AbstractFilter</b> which understands basic RTF syntax
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
 * and passes a stream of control words, text, and begin/end group
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
 * indications to its subclass.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
 * Normally programmers will only use <b>RTFFilter</b>, a subclass of this class that knows what to
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
 * do with the tokens this class parses.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
 * @see AbstractFilter
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
 * @see RTFFilter
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
abstract class RTFParser extends AbstractFilter
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
  /** The current RTF group nesting level. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
  public int level;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
  private int state;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
  private StringBuffer currentCharacters;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
  private String pendingKeyword;                // where keywords go while we
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
                                                // read their parameters
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
  private int pendingCharacter;                 // for the \'xx construct
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
  private long binaryBytesLeft;                  // in a \bin blob?
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
  ByteArrayOutputStream binaryBuf;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
  private boolean[] savedSpecials;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
  /** A stream to which to write warnings and debugging information
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
   *  while parsing. This is set to <code>System.out</code> to log
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
   *  any anomalous information to stdout. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
  protected PrintStream warnings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
  // value for the 'state' variable
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
  private final int S_text = 0;          // reading random text
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
  private final int S_backslashed = 1;   // read a backslash, waiting for next
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
  private final int S_token = 2;         // reading a multicharacter token
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
  private final int S_parameter = 3;     // reading a token's parameter
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
  private final int S_aftertick = 4;     // after reading \'
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
  private final int S_aftertickc = 5;    // after reading \'x
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
  private final int S_inblob = 6;        // in a \bin blob
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
  /** Implemented by subclasses to interpret a parameter-less RTF keyword.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
   *  The keyword is passed without the leading '/' or any delimiting
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
   *  whitespace. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
  public abstract boolean handleKeyword(String keyword);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
  /** Implemented by subclasses to interpret a keyword with a parameter.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
   *  @param keyword   The keyword, as with <code>handleKeyword(String)</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
   *  @param parameter The parameter following the keyword. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
  public abstract boolean handleKeyword(String keyword, int parameter);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
  /** Implemented by subclasses to interpret text from the RTF stream. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
  public abstract void handleText(String text);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
  public void handleText(char ch)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
  { handleText(String.valueOf(ch)); }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
  /** Implemented by subclasses to handle the contents of the \bin keyword. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
  public abstract void handleBinaryBlob(byte[] data);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
  /** Implemented by subclasses to react to an increase
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
   *  in the nesting level. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
  public abstract void begingroup();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
  /** Implemented by subclasses to react to the end of a group. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
  public abstract void endgroup();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
  // table of non-text characters in rtf
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
  static final boolean rtfSpecialsTable[];
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
  static {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
    rtfSpecialsTable = (boolean[])noSpecialsTable.clone();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
    rtfSpecialsTable['\n'] = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
    rtfSpecialsTable['\r'] = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
    rtfSpecialsTable['{'] = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
    rtfSpecialsTable['}'] = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
    rtfSpecialsTable['\\'] = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
  }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
  public RTFParser()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
    currentCharacters = new StringBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
    state = S_text;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
    pendingKeyword = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    level = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
    //warnings = System.out;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
    specialsTable = rtfSpecialsTable;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
  }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
  // TODO: Handle wrapup at end of file correctly.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
  public void writeSpecial(int b)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
    throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
    write((char)b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
  }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
    protected void warning(String s) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
        if (warnings != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
            warnings.println(s);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
  public void write(String s)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
    if (state != S_text) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
      int index = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
      int length = s.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
      while(index < length && state != S_text) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
        write(s.charAt(index));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
        index ++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
      }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
      if(index >= length)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
      s = s.substring(index);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
    if (currentCharacters.length() > 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
      currentCharacters.append(s);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
    else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
      handleText(s);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
  }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
  public void write(char ch)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
    throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
    boolean ok;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
    switch (state)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
      case S_text:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
        if (ch == '\n' || ch == '\r') {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
          break;  // unadorned newlines are ignored
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
        } else if (ch == '{') {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
          if (currentCharacters.length() > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
            handleText(currentCharacters.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
            currentCharacters = new StringBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
          }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
          level ++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
          begingroup();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
        } else if(ch == '}') {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
          if (currentCharacters.length() > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
            handleText(currentCharacters.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
            currentCharacters = new StringBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
          }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
          if (level == 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
            throw new IOException("Too many close-groups in RTF text");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
          endgroup();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
          level --;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
        } else if(ch == '\\') {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
          if (currentCharacters.length() > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
            handleText(currentCharacters.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
            currentCharacters = new StringBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
          }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
          state = S_backslashed;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
          currentCharacters.append(ch);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
      case S_backslashed:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
        if (ch == '\'') {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
          state = S_aftertick;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
          break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
        if (!Character.isLetter(ch)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
          char newstring[] = new char[1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
          newstring[0] = ch;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
          if (!handleKeyword(new String(newstring))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
            warning("Unknown keyword: " + newstring + " (" + (byte)ch + ")");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
          }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
          state = S_text;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
          pendingKeyword = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
          /* currentCharacters is already an empty stringBuffer */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
          break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
        state = S_token;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
        /* FALL THROUGH */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
      case S_token:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
        if (Character.isLetter(ch)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
          currentCharacters.append(ch);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
          pendingKeyword = currentCharacters.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
          currentCharacters = new StringBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
          // Parameter following?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
          if (Character.isDigit(ch) || (ch == '-')) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
            state = S_parameter;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
            currentCharacters.append(ch);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
          } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
            ok = handleKeyword(pendingKeyword);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
            if (!ok)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
              warning("Unknown keyword: " + pendingKeyword);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
            pendingKeyword = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
            state = S_text;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
            // Non-space delimiters get included in the text
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
            if (!Character.isWhitespace(ch))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
              write(ch);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
          }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
      case S_parameter:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
        if (Character.isDigit(ch)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
          currentCharacters.append(ch);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
          /* TODO: Test correct behavior of \bin keyword */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
          if (pendingKeyword.equals("bin")) {  /* magic layer-breaking kwd */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
            long parameter = Long.parseLong(currentCharacters.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
            pendingKeyword = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
            state = S_inblob;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
            binaryBytesLeft = parameter;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
            if (binaryBytesLeft > Integer.MAX_VALUE)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
                binaryBuf = new ByteArrayOutputStream(Integer.MAX_VALUE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
            else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
                binaryBuf = new ByteArrayOutputStream((int)binaryBytesLeft);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
            savedSpecials = specialsTable;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
            specialsTable = allSpecialsTable;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
          }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
          int parameter = Integer.parseInt(currentCharacters.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
          ok = handleKeyword(pendingKeyword, parameter);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
          if (!ok)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
            warning("Unknown keyword: " + pendingKeyword +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
                    " (param " + currentCharacters + ")");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
          pendingKeyword = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
          currentCharacters = new StringBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
          state = S_text;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
          // Delimiters here are interpreted as text too
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
          if (!Character.isWhitespace(ch))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
            write(ch);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
      case S_aftertick:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        if (Character.digit(ch, 16) == -1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
          state = S_text;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
        else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
          pendingCharacter = Character.digit(ch, 16);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
          state = S_aftertickc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
      case S_aftertickc:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
        state = S_text;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
        if (Character.digit(ch, 16) != -1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
        {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
          pendingCharacter = pendingCharacter * 16 + Character.digit(ch, 16);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
          ch = translationTable[pendingCharacter];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
          if (ch != 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
              handleText(ch);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
      case S_inblob:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        binaryBuf.write(ch);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
        binaryBytesLeft --;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
        if (binaryBytesLeft == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
            state = S_text;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
            specialsTable = savedSpecials;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
            savedSpecials = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
            handleBinaryBlob(binaryBuf.toByteArray());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
            binaryBuf = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
      }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
  }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
  /** Flushes any buffered but not yet written characters.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
   *  Subclasses which override this method should call this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
   *  method <em>before</em> flushing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
   *  any of their own buffers. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
  public void flush()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
    throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
    super.flush();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
    if (state == S_text && currentCharacters.length() > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
      handleText(currentCharacters.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
      currentCharacters = new StringBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
  }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
  /** Closes the parser. Currently, this simply does a <code>flush()</code>,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
   *  followed by some minimal consistency checks. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
  public void close()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
    throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
    flush();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
    if (state != S_text || level > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
      warning("Truncated RTF file.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
      /* TODO: any sane way to handle termination in a non-S_text state? */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
      /* probably not */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
      /* this will cause subclasses to behave more reasonably
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
         some of the time */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
      while (level > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
          endgroup();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
          level --;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
      }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
    super.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
  }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
}