/*
 * Copyright 1997-2000 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
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
 * <code>ByteToChar</code> converters
 * are suddenly 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;
}
