summaryrefslogtreecommitdiff
path: root/libjava/classpath/javax/swing/text/rtf/RTFScanner.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/javax/swing/text/rtf/RTFScanner.java')
-rw-r--r--libjava/classpath/javax/swing/text/rtf/RTFScanner.java294
1 files changed, 294 insertions, 0 deletions
diff --git a/libjava/classpath/javax/swing/text/rtf/RTFScanner.java b/libjava/classpath/javax/swing/text/rtf/RTFScanner.java
new file mode 100644
index 000000000..2eca159c4
--- /dev/null
+++ b/libjava/classpath/javax/swing/text/rtf/RTFScanner.java
@@ -0,0 +1,294 @@
+/* RTFScanner.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text.rtf;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+/**
+ * Provides a scanner that scans an {@link InputStream} for tokens of the
+ * RTF syntax.
+ *
+ * This scanner is based upon the RTF specification 1.6
+ * available at:
+ *
+ * <a
+ * href="http://msdn.microsoft.com/library/en-us/dnrtfspec/html/rtfspec.asp">
+ * RTF specification at MSDN</a>
+ *
+ * @author Roman Kennke (roman@ontographics.com)
+ */
+class RTFScanner
+{
+
+ /**
+ * The reader from which we read the RTF data.
+ */
+ private Reader in;
+
+ /**
+ * This is used to constuct strings from the read in chars.
+ */
+ private StringBuffer buffer;
+
+ /**
+ * Lookahead token.
+ */
+ private Token lastToken;
+
+ /**
+ * Constructs a new RTFScanner without initializing the {@link Reader}.
+ */
+ private RTFScanner()
+ {
+ buffer = new StringBuffer();
+ }
+
+ /**
+ * Constructs a new RTFScanner for the given {@link InputStream}.
+ * The stream is wrapped into an {@link InputStreamReader} and if it's
+ * not yet buffered then the Reader is wrapped in a {@link BufferedReader}
+ *
+ * @param stream the {@link InputStream} to read RTF data from
+ */
+ public RTFScanner(InputStream stream)
+ {
+ this();
+ InputStreamReader reader = new InputStreamReader(stream);
+ in = new BufferedReader(reader);
+ }
+
+ /**
+ * Constructs a new RTFScanner for the given {@link Reader}.
+ *
+ * If the reader is not an instance of {@link BufferedReader} then it
+ * is wrapped into a BufferedReader.
+ *
+ * @param reader the {@link BufferedReader} to read RTF data from
+ */
+ public RTFScanner(Reader reader)
+ {
+ this();
+ if (reader instanceof BufferedReader)
+ {
+ in = reader;
+ }
+ else
+ {
+ in = new BufferedReader(reader);
+ }
+ }
+
+ /**
+ * Reads in the next {@link Token} from the stream.
+ *
+ * @return the read {@link Token}
+ *
+ * @throws IOException if the underlying stream has problems
+ */
+ private Token readTokenImpl()
+ throws IOException
+ {
+ Token token = null;
+
+ int c = in.read();
+ switch(c)
+ {
+ case -1:
+ token = new Token(Token.EOF);
+ break;
+
+ case '{':
+ token = new Token(Token.LCURLY);
+ break;
+
+ case '}':
+ token = new Token(Token.RCURLY);
+ break;
+
+ case '\\':
+ buffer.delete(0, buffer.length());
+ buffer.append((char) c);
+ token = readControlWord();
+ break;
+
+ default:
+ buffer.delete(0, buffer.length());
+ buffer.append((char) c);
+ token = readText();
+ break;
+ }
+
+ return token;
+ }
+
+ Token peekToken()
+ throws IOException
+ {
+ lastToken = readTokenImpl();
+ return lastToken;
+ }
+
+ Token readToken()
+ throws IOException
+ {
+ Token token;
+ if (lastToken != null)
+ {
+ token = lastToken;
+ lastToken = null;
+ }
+ else
+ token = readTokenImpl();
+ return token;
+ }
+
+ /**
+ * Reads in a control word and optional parameter.
+ *
+ * @return the read in control word as {@link ControlWordToken}
+ *
+ * @throws IOException if the underlying stream has problems
+ */
+ private Token readControlWord()
+ throws IOException
+ {
+ // this flag indicates if we are still reading the name or are already
+ // in the parameter
+ boolean readingName = true;
+ String name = null;
+ String param = null;
+
+ while (true)
+ {
+ in.mark(1);
+ int c = in.read();
+
+ // check for 'a'..'z'
+ if (readingName && (c >= 'a') && (c <= 'z'))
+ {
+ buffer.append((char) c);
+ }
+ else if ((c >= '0') && (c <= '9'))
+ {
+ // if the last char was in the name, then finish reading the name
+ if (readingName)
+ {
+ name = buffer.toString();
+ buffer.delete(0, buffer.length());
+ readingName = false;
+ }
+ buffer.append((char) c);
+ }
+ else
+ {
+ // if we were in the name, then finish this
+ if (readingName)
+ {
+ name = buffer.toString();
+ }
+ // otherwise finish the parameter
+ else
+ {
+ param = buffer.toString();
+ }
+
+ // clear up
+ buffer.delete(0, buffer.length());
+ // reset input buffer to last char
+ in.reset();
+ // break while loop
+ break;
+ }
+ }
+
+ ControlWordToken token = null;
+
+ if (param == null)
+ token = new ControlWordToken(name);
+ else
+ token =new ControlWordToken(name, Integer.parseInt(param));
+
+ return token;
+
+ }
+
+ /**
+ * Reads in a block of text.
+ *
+ * @return the token for the text
+ */
+ private Token readText()
+ throws IOException
+ {
+
+ boolean readingText = true;
+ while (readingText)
+ {
+ in.mark(1);
+ int c = in.read();
+ switch(c)
+ {
+ case '\\':
+ case '{':
+ case '}':
+ case -1:
+ readingText = false;
+ in.reset();
+ break;
+
+ default:
+ buffer.append((char) c);
+ break;
+ }
+
+ }
+
+ String text = buffer.toString();
+ Token token = new TextToken(text);
+
+ buffer.delete(0, buffer.length());
+
+ return token;
+
+ }
+}