- /*
 - * @(#)AbstractFilter.java 1.7 00/02/02
 - *
 - * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
 - *
 - * This software is the proprietary information of Sun Microsystems, Inc.
 - * Use is subject to license terms.
 - *
 - */
 - package javax.swing.text.rtf;
 - import java.io.*;
 - import java.lang.*;
 - /**
 - * A generic superclass for streams which read and parse text
 - * consisting of runs of characters interspersed with occasional
 - * ``specials'' (formatting characters).
 - *
 - * <p> Most of the functionality
 - * of this class would be redundant except that the ByteToChar converters
 - * are suddently private API. Presumably this class will disappear
 - * when the API is made public again. (sigh) That will also let us handle
 - * multibyte character sets...
 - *
 - * <P> A subclass should override at least <code>write(char)</code>
 - * and <code>writeSpecial(int)</code>. For efficiency's sake it's a
 - * good idea to override <code>write(String)</code> as well. The subclass'
 - * initializer may also install appropriate translation and specials tables.
 - *
 - * @see OutputStream
 - */
 - abstract class AbstractFilter extends OutputStream
 - {
 - /** A table mapping bytes to characters */
 - protected char translationTable[];
 - /** A table indicating which byte values should be interpreted as
 - * characters and which should be treated as formatting codes */
 - protected boolean specialsTable[];
 - /** A translation table which does ISO Latin-1 (trivial) */
 - static final char latin1TranslationTable[];
 - /** A specials table which indicates that no characters are special */
 - static final boolean noSpecialsTable[];
 - /** A specials table which indicates that all characters are special */
 - static final boolean allSpecialsTable[];
 - static {
 - int i;
 - noSpecialsTable = new boolean[256];
 - for (i = 0; i < 256; i++)
 - noSpecialsTable[i] = false;
 - allSpecialsTable = new boolean[256];
 - for (i = 0; i < 256; i++)
 - allSpecialsTable[i] = true;
 - latin1TranslationTable = new char[256];
 - for (i = 0; i < 256; i++)
 - latin1TranslationTable[i] = (char)i;
 - }
 - /**
 - * A convenience method that reads text from a FileInputStream
 - * and writes it to the receiver.
 - * The format in which the file
 - * is read is determined by the concrete subclass of
 - * AbstractFilter to which this method is sent.
 - * <p>This method does not close the receiver after reaching EOF on
 - * the input stream.
 - * The user must call <code>close()</code> to ensure that all
 - * data are processed.
 - *
 - * @param in An InputStream providing text.
 - */
 - public void readFromStream(InputStream in)
 - throws IOException
 - {
 - byte buf[];
 - int count;
 - buf = new byte[16384];
 - while(true) {
 - count = in.read(buf);
 - if (count < 0)
 - break;
 - this.write(buf, 0, count);
 - }
 - }
 - public void readFromReader(Reader in)
 - throws IOException
 - {
 - char buf[];
 - int count;
 - buf = new char[2048];
 - while(true) {
 - count = in.read(buf);
 - if (count < 0)
 - break;
 - for (int i = 0; i < count; i++) {
 - this.write(buf[i]);
 - }
 - }
 - }
 - public AbstractFilter()
 - {
 - translationTable = latin1TranslationTable;
 - specialsTable = noSpecialsTable;
 - }
 - /**
 - * Implements the abstract method of OutputStream, of which this class
 - * is a subclass.
 - */
 - public void write(int b)
 - throws IOException
 - {
 - if (b < 0)
 - b += 256;
 - if (specialsTable[b])
 - writeSpecial(b);
 - else {
 - char ch = translationTable[b];
 - if (ch != (char)0)
 - write(ch);
 - }
 - }
 - /**
 - * Implements the buffer-at-a-time write method for greater
 - * efficiency.
 - *
 - * <p> <strong>PENDING:</strong> Does <code>write(byte[])</code>
 - * call <code>write(byte[], int, int)</code> or is it the other way
 - * around?
 - */
 - public void write(byte[] buf, int off, int len)
 - throws IOException
 - {
 - StringBuffer accumulator = null;
 - while (len > 0) {
 - short b = (short)buf[off];
 - // stupid signed bytes
 - if (b < 0)
 - b += 256;
 - if (specialsTable[b]) {
 - if (accumulator != null) {
 - write(accumulator.toString());
 - accumulator = null;
 - }
 - writeSpecial(b);
 - } else {
 - char ch = translationTable[b];
 - if (ch != (char)0) {
 - if (accumulator == null)
 - accumulator = new StringBuffer();
 - accumulator.append(ch);
 - }
 - }
 - len --;
 - off ++;
 - }
 - if (accumulator != null)
 - write(accumulator.toString());
 - }
 - /**
 - * Hopefully, all subclasses will override this method to accept strings
 - * of text, but if they don't, AbstractFilter's implementation
 - * will spoon-feed them via <code>write(char)</code>.
 - *
 - * @param s The string of non-special characters written to the
 - * OutputStream.
 - */
 - public void write(String s)
 - throws IOException
 - {
 - int index, length;
 - length = s.length();
 - for(index = 0; index < length; index ++) {
 - write(s.charAt(index));
 - }
 - }
 - /**
 - * Subclasses must provide an implementation of this method which
 - * accepts a single (non-special) character.
 - *
 - * @param ch The character written to the OutputStream.
 - */
 - protected abstract void write(char ch) throws IOException;
 - /**
 - * Subclasses must provide an implementation of this method which
 - * accepts a single special byte. No translation is performed
 - * on specials.
 - *
 - * @param b The byte written to the OutputStream.
 - */
 - protected abstract void writeSpecial(int b) throws IOException;
 - }