/*
 * Copyright 1997-2004 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.lang.*;
import java.util.*;
import java.io.*;
import java.awt.Font;
import java.awt.Color;

import javax.swing.text.*;

/**
 * Takes a sequence of RTF tokens and text and appends the text
 * described by the RTF to a <code>StyledDocument</code> (the <em>target</em>).
 * The RTF is lexed
 * from the character stream by the <code>RTFParser</code> which is this class's
 * superclass.
 *
 * This class is an indirect subclass of OutputStream. It must be closed
 * in order to guarantee that all of the text has been sent to
 * the text acceptor.
 *
 *   @see RTFParser
 *   @see java.io.OutputStream
 */
class RTFReader extends RTFParser
{
  /** The object to which the parsed text is sent. */
  StyledDocument target;

  /** Miscellaneous information about the parser's state. This
   *  dictionary is saved and restored when an RTF group begins
   *  or ends. */
  Dictionary parserState;   /* Current parser state */
  /** This is the "dst" item from parserState. rtfDestination
   *  is the current rtf destination. It is cached in an instance
   *  variable for speed. */
  Destination rtfDestination;
  /** This holds the current document attributes. */
  MutableAttributeSet documentAttributes;

  /** This Dictionary maps Integer font numbers to String font names. */
  Dictionary fontTable;
  /** This array maps color indices to Color objects. */
  Color[] colorTable;
  /** This array maps character style numbers to Style objects. */
  Style[] characterStyles;
  /** This array maps paragraph style numbers to Style objects. */
  Style[] paragraphStyles;
  /** This array maps section style numbers to Style objects. */
  Style[] sectionStyles;

  /** This is the RTF version number, extracted from the \rtf keyword.
   *  The version information is currently not used. */
  int rtfversion;

  /** <code>true</code> to indicate that if the next keyword is unknown,
   *  the containing group should be ignored. */
  boolean ignoreGroupIfUnknownKeyword;

  /** The parameter of the most recently parsed \\ucN keyword,
   *  used for skipping alternative representations after a
   *  Unicode character. */
  int skippingCharacters;

  static private Dictionary straightforwardAttributes;
  static {
      straightforwardAttributes = RTFAttributes.attributesByKeyword();
  }

  private MockAttributeSet mockery;

  /* this should be final, but there's a bug in javac... */
  /** textKeywords maps RTF keywords to single-character strings,
   *  for those keywords which simply insert some text. */
  static Dictionary textKeywords = null;
  static {
      textKeywords = new Hashtable();
      textKeywords.put("\\",         "\\");
      textKeywords.put("{",          "{");
      textKeywords.put("}",          "}");
      textKeywords.put(" ",          "\u00A0");  /* not in the spec... */
      textKeywords.put("~",          "\u00A0");  /* nonbreaking space */
      textKeywords.put("_",          "\u2011");  /* nonbreaking hyphen */
      textKeywords.put("bullet",     "\u2022");
      textKeywords.put("emdash",     "\u2014");
      textKeywords.put("emspace",    "\u2003");
      textKeywords.put("endash",     "\u2013");
      textKeywords.put("enspace",    "\u2002");
      textKeywords.put("ldblquote",  "\u201C");
      textKeywords.put("lquote",     "\u2018");
      textKeywords.put("ltrmark",    "\u200E");
      textKeywords.put("rdblquote",  "\u201D");
      textKeywords.put("rquote",     "\u2019");
      textKeywords.put("rtlmark",    "\u200F");
      textKeywords.put("tab",        "\u0009");
      textKeywords.put("zwj",        "\u200D");
      textKeywords.put("zwnj",       "\u200C");

      /* There is no Unicode equivalent to an optional hyphen, as far as
         I can tell. */
      textKeywords.put("-",          "\u2027");  /* TODO: optional hyphen */
  }

  /* some entries in parserState */
  static final String TabAlignmentKey = "tab_alignment";
  static final String TabLeaderKey = "tab_leader";

  static Dictionary characterSets;
  static boolean useNeXTForAnsi = false;
  static {
      characterSets = new Hashtable();
  }

/* TODO: per-font font encodings ( \fcharset control word ) ? */

/**
 * Creates a new RTFReader instance. Text will be sent to
 * the specified TextAcceptor.
 *
 * @param destination The TextAcceptor which is to receive the text.
 */
public RTFReader(StyledDocument destination)
{
    int i;

    target = destination;
    parserState = new Hashtable();
    fontTable = new Hashtable();

    rtfversion = -1;

    mockery = new MockAttributeSet();
    documentAttributes = new SimpleAttributeSet();
}

/** Called when the RTFParser encounters a bin keyword in the
 *  RTF stream.
 *
 *  @see RTFParser
 */
public void handleBinaryBlob(byte[] data)
{
    if (skippingCharacters > 0) {
        /* a blob only counts as one character for skipping purposes */
        skippingCharacters --;
        return;
    }

    /* someday, someone will want to do something with blobs */
}


/**
 * Handles any pure text (containing no control characters) in the input
 * stream. Called by the superclass. */
public void handleText(String text)
{
    if (skippingCharacters > 0) {
        if (skippingCharacters >= text.length()) {
            skippingCharacters -= text.length();
            return;
        } else {
            text = text.substring(skippingCharacters);
            skippingCharacters = 0;
        }
    }

    if (rtfDestination != null) {
        rtfDestination.handleText(text);
        return;
    }

    warning("Text with no destination. oops.");
}

/** The default color for text which has no specified color. */
Color defaultColor()
{
    return Color.black;
}

/** Called by the superclass when a new RTF group is begun.
 *  This implementation saves the current <code>parserState</code>, and gives
 *  the current destination a chance to save its own state.
 * @see RTFParser#begingroup
 */
public void begingroup()
{
    if (skippingCharacters > 0) {
        /* TODO this indicates an error in the RTF. Log it? */
        skippingCharacters = 0;
    }

    /* we do this little dance to avoid cloning the entire state stack and
       immediately throwing it away. */
    Object oldSaveState = parserState.get("_savedState");
    if (oldSaveState != null)
        parserState.remove("_savedState");
    Dictionary saveState = (Dictionary)((Hashtable)parserState).clone();
    if (oldSaveState != null)
        saveState.put("_savedState", oldSaveState);
    parserState.put("_savedState", saveState);

    if (rtfDestination != null)
        rtfDestination.begingroup();
}

/** Called by the superclass when the current RTF group is closed.
 *  This restores the parserState saved by <code>begingroup()</code>
 *  as well as invoking the endgroup method of the current
 *  destination.
 * @see RTFParser#endgroup
 */
public void endgroup()
{
    if (skippingCharacters > 0) {
        /* NB this indicates an error in the RTF. Log it? */
        skippingCharacters = 0;
    }

    Dictionary restoredState = (Dictionary)parserState.get("_savedState");
    Destination restoredDestination = (Destination)restoredState.get("dst");
    if (restoredDestination != rtfDestination) {
        rtfDestination.close(); /* allow the destination to clean up */
        rtfDestination = restoredDestination;
    }
    Dictionary oldParserState = parserState;
    parserState = restoredState;
    if (rtfDestination != null)
        rtfDestination.endgroup(oldParserState);
}

protected void setRTFDestination(Destination newDestination)
{
    /* Check that setting the destination won't close the
       current destination (should never happen) */
    Dictionary previousState = (Dictionary)parserState.get("_savedState");
    if (previousState != null) {
        if (rtfDestination != previousState.get("dst")) {
            warning("Warning, RTF destination overridden, invalid RTF.");
            rtfDestination.close();
        }
    }
    rtfDestination = newDestination;
    parserState.put("dst", rtfDestination);
}

/** Called by the user when there is no more input (<i>i.e.</i>,
 * at the end of the RTF file.)
 *
 * @see OutputStream#close
 */
public void close()
    throws IOException
{
    Enumeration docProps = documentAttributes.getAttributeNames();
    while(docProps.hasMoreElements()) {
        Object propName = docProps.nextElement();
        target.putProperty(propName,
                           documentAttributes.getAttribute((String)propName));
    }

    /* RTFParser should have ensured that all our groups are closed */

    warning("RTF filter done.");

    super.close();
}

/**
 * Handles a parameterless RTF keyword. This is called by the superclass
 * (RTFParser) when a keyword is found in the input stream.
 *
 * @returns <code>true</code> if the keyword is recognized and handled;
 *          <code>false</code> otherwise
 * @see RTFParser#handleKeyword
 */
public boolean handleKeyword(String keyword)
{
    Object item;
    boolean ignoreGroupIfUnknownKeywordSave = ignoreGroupIfUnknownKeyword;

    if (skippingCharacters > 0) {
        skippingCharacters --;
        return true;
    }

    ignoreGroupIfUnknownKeyword = false;

    if ((item = textKeywords.get(keyword)) != null) {
        handleText((String)item);
        return true;
    }

    if (keyword.equals("fonttbl")) {
        setRTFDestination(new FonttblDestination());
        return true;
    }

    if (keyword.equals("colortbl")) {
        setRTFDestination(new ColortblDestination());
        return true;
    }

    if (keyword.equals("stylesheet")) {
        setRTFDestination(new StylesheetDestination());
        return true;
    }

    if (keyword.equals("info")) {
        setRTFDestination(new InfoDestination());
        return false;
    }

    if (keyword.equals("mac")) {
        setCharacterSet("mac");
        return true;
    }

    if (keyword.equals("ansi")) {
        if (useNeXTForAnsi)
            setCharacterSet("NeXT");
        else
            setCharacterSet("ansi");
        return true;
    }

    if (keyword.equals("next")) {
        setCharacterSet("NeXT");
        return true;
    }

    if (keyword.equals("pc")) {
        setCharacterSet("cpg437"); /* IBM Code Page 437 */
        return true;
    }

    if (keyword.equals("pca")) {
        setCharacterSet("cpg850"); /* IBM Code Page 850 */
        return true;
    }

    if (keyword.equals("*")) {
        ignoreGroupIfUnknownKeyword = true;
        return true;
    }

    if (rtfDestination != null) {
        if(rtfDestination.handleKeyword(keyword))
            return true;
    }

    /* this point is reached only if the keyword is unrecognized */

    /* other destinations we don't understand and therefore ignore */
    if (keyword.equals("aftncn") ||
        keyword.equals("aftnsep") ||
        keyword.equals("aftnsepc") ||
        keyword.equals("annotation") ||
        keyword.equals("atnauthor") ||
        keyword.equals("atnicn") ||
        keyword.equals("atnid") ||
        keyword.equals("atnref") ||
        keyword.equals("atntime") ||
        keyword.equals("atrfend") ||
        keyword.equals("atrfstart") ||
        keyword.equals("bkmkend") ||
        keyword.equals("bkmkstart") ||
        keyword.equals("datafield") ||
        keyword.equals("do") ||
        keyword.equals("dptxbxtext") ||
        keyword.equals("falt") ||
        keyword.equals("field") ||
        keyword.equals("file") ||
        keyword.equals("filetbl") ||
        keyword.equals("fname") ||
        keyword.equals("fontemb") ||
        keyword.equals("fontfile") ||
        keyword.equals("footer") ||
        keyword.equals("footerf") ||
        keyword.equals("footerl") ||
        keyword.equals("footerr") ||
        keyword.equals("footnote") ||
        keyword.equals("ftncn") ||
        keyword.equals("ftnsep") ||
        keyword.equals("ftnsepc") ||
        keyword.equals("header") ||
        keyword.equals("headerf") ||
        keyword.equals("headerl") ||
        keyword.equals("headerr") ||
        keyword.equals("keycode") ||
        keyword.equals("nextfile") ||
        keyword.equals("object") ||
        keyword.equals("pict") ||
        keyword.equals("pn") ||
        keyword.equals("pnseclvl") ||
        keyword.equals("pntxtb") ||
        keyword.equals("pntxta") ||
        keyword.equals("revtbl") ||
        keyword.equals("rxe") ||
        keyword.equals("tc") ||
        keyword.equals("template") ||
        keyword.equals("txe") ||
        keyword.equals("xe")) {
        ignoreGroupIfUnknownKeywordSave = true;
    }

    if (ignoreGroupIfUnknownKeywordSave) {
        setRTFDestination(new DiscardingDestination());
    }

    return false;
}

/**
 * Handles an RTF keyword and its integer parameter.
 * This is called by the superclass
 * (RTFParser) when a keyword is found in the input stream.
 *
 * @returns <code>true</code> if the keyword is recognized and handled;
 *          <code>false</code> otherwise
 * @see RTFParser#handleKeyword
 */
public boolean handleKeyword(String keyword, int parameter)
{
    boolean ignoreGroupIfUnknownKeywordSave = ignoreGroupIfUnknownKeyword;

    if (skippingCharacters > 0) {
        skippingCharacters --;
        return true;
    }

    ignoreGroupIfUnknownKeyword = false;

    if (keyword.equals("uc")) {
        /* count of characters to skip after a unicode character */
        parserState.put("UnicodeSkip", Integer.valueOf(parameter));
        return true;
    }
    if (keyword.equals("u")) {
        if (parameter < 0)
            parameter = parameter + 65536;
        handleText((char)parameter);
        Number skip = (Number)(parserState.get("UnicodeSkip"));
        if (skip != null) {
            skippingCharacters = skip.intValue();
        } else {
            skippingCharacters = 1;
        }
        return true;
    }

    if (keyword.equals("rtf")) {
        rtfversion = parameter;
        setRTFDestination(new DocumentDestination());
        return true;
    }

    if (keyword.startsWith("NeXT") ||
        keyword.equals("private"))
        ignoreGroupIfUnknownKeywordSave = true;

    if (rtfDestination != null) {
        if(rtfDestination.handleKeyword(keyword, parameter))
            return true;
    }

    /* this point is reached only if the keyword is unrecognized */

    if (ignoreGroupIfUnknownKeywordSave) {
        setRTFDestination(new DiscardingDestination());
    }

    return false;
}

private void setTargetAttribute(String name, Object value)
{
//    target.changeAttributes(new LFDictionary(LFArray.arrayWithObject(value), LFArray.arrayWithObject(name)));
}

/**
 * setCharacterSet sets the current translation table to correspond with
 * the named character set. The character set is loaded if necessary.
 *
 * @see AbstractFilter
 */
public void setCharacterSet(String name)
{
    Object set;

    try {
        set = getCharacterSet(name);
    } catch (Exception e) {
        warning("Exception loading RTF character set \"" + name + "\": " + e);
        set = null;
    }

    if (set != null) {
        translationTable = (char[])set;
    } else {
        warning("Unknown RTF character set \"" + name + "\"");
        if (!name.equals("ansi")) {
            try {
                translationTable = (char[])getCharacterSet("ansi");
            } catch (IOException e) {
                throw new InternalError("RTFReader: Unable to find character set resources (" + e + ")");
            }
        }
    }

    setTargetAttribute(Constants.RTFCharacterSet, name);
}

/** Adds a character set to the RTFReader's list
 *  of known character sets */
public static void
defineCharacterSet(String name, char[] table)
{
    if (table.length < 256)
        throw new IllegalArgumentException("Translation table must have 256 entries.");
    characterSets.put(name, table);
}

/** Looks up a named character set. A character set is a 256-entry
 *  array of characters, mapping unsigned byte values to their Unicode
 *  equivalents. The character set is loaded if necessary.
 *
 *  @returns the character set
 */
public static Object
getCharacterSet(final String name)
    throws IOException
{
    char[] set;

    set = (char [])characterSets.get(name);
    if (set == null) {
      InputStream charsetStream;
      charsetStream = (InputStream)java.security.AccessController.
                      doPrivileged(new java.security.PrivilegedAction() {
          public Object run() {
              return RTFReader.class.getResourceAsStream
                                     ("charsets/" + name + ".txt");
          }
      });
      set = readCharset(charsetStream);
      defineCharacterSet(name, set);
    }
    return set;
}

/** Parses a character set from an InputStream. The character set
 * must contain 256 decimal integers, separated by whitespace, with
 * no punctuation. B- and C- style comments are allowed.
 *
 * @returns the newly read character set
 */
static char[] readCharset(InputStream strm)
     throws IOException
{
    char[] values = new char[256];
    int i;
    StreamTokenizer in = new StreamTokenizer(new BufferedReader(
            new InputStreamReader(strm, "ISO-8859-1")));

    in.eolIsSignificant(false);
    in.commentChar('#');
    in.slashSlashComments(true);
    in.slashStarComments(true);

    i = 0;
    while (i < 256) {
        int ttype;
        try {
            ttype = in.nextToken();
        } catch (Exception e) {
            throw new IOException("Unable to read from character set file (" + e + ")");
        }
        if (ttype != in.TT_NUMBER) {
//          System.out.println("Bad token: type=" + ttype + " tok=" + in.sval);
            throw new IOException("Unexpected token in character set file");
//          continue;
        }
        values[i] = (char)(in.nval);
        i++;
    }

    return values;
}

static char[] readCharset(java.net.URL href)
     throws IOException
{
    return readCharset(href.openStream());
}

/** An interface (could be an entirely abstract class) describing
 *  a destination. The RTF reader always has a current destination
 *  which is where text is sent.
 *
 *  @see RTFReader
 */
interface Destination {
    void handleBinaryBlob(byte[] data);
    void handleText(String text);
    boolean handleKeyword(String keyword);
    boolean handleKeyword(String keyword, int parameter);

    void begingroup();
    void endgroup(Dictionary oldState);

    void close();
}

/** This data-sink class is used to implement ignored destinations
 *  (e.g. {\*\blegga blah blah blah} )
 *  It accepts all keywords and text but does nothing with them. */
class DiscardingDestination implements Destination
{
    public void handleBinaryBlob(byte[] data)
    {
        /* Discard binary blobs. */
    }

    public void handleText(String text)
    {
        /* Discard text. */
    }

    public boolean handleKeyword(String text)
    {
        /* Accept and discard keywords. */
        return true;
    }

    public boolean handleKeyword(String text, int parameter)
    {
        /* Accept and discard parameterized keywords. */
        return true;
    }

    public void begingroup()
    {
        /* Ignore groups --- the RTFReader will keep track of the
           current group level as necessary */
    }

    public void endgroup(Dictionary oldState)
    {
        /* Ignore groups */
    }

    public void close()
    {
        /* No end-of-destination cleanup needed */
    }
}

/** Reads the fonttbl group, inserting fonts into the RTFReader's
 *  fontTable dictionary. */
class FonttblDestination implements Destination
{
    int nextFontNumber;
    Object fontNumberKey = null;
    String nextFontFamily;

    public void handleBinaryBlob(byte[] data)
    { /* Discard binary blobs. */ }

    public void handleText(String text)
    {
        int semicolon = text.indexOf(';');
        String fontName;

        if (semicolon > -1)
            fontName = text.substring(0, semicolon);
        else
            fontName = text;


        /* TODO: do something with the font family. */

        if (nextFontNumber == -1
            && fontNumberKey != null) {
            //font name might be broken across multiple calls
            fontName = fontTable.get(fontNumberKey) + fontName;
        } else {
            fontNumberKey = Integer.valueOf(nextFontNumber);
        }
        fontTable.put(fontNumberKey, fontName);

        nextFontNumber = -1;
        nextFontFamily = null;
        return;
    }

    public boolean handleKeyword(String keyword)
    {
        if (keyword.charAt(0) == 'f') {
            nextFontFamily = keyword.substring(1);
            return true;
        }

        return false;
    }

    public boolean handleKeyword(String keyword, int parameter)
    {
        if (keyword.equals("f")) {
            nextFontNumber = parameter;
            return true;
        }

        return false;
    }

    /* Groups are irrelevant. */
    public void begingroup() {}
    public void endgroup(Dictionary oldState) {}

    /* currently, the only thing we do when the font table ends is
       dump its contents to the debugging log. */
    public void close()
    {
        Enumeration nums = fontTable.keys();
        warning("Done reading font table.");
        while(nums.hasMoreElements()) {
            Integer num = (Integer)nums.nextElement();
            warning("Number " + num + ": " + fontTable.get(num));
        }
    }
}

/** Reads the colortbl group. Upon end-of-group, the RTFReader's
 *  color table is set to an array containing the read colors. */
class ColortblDestination implements Destination
{
    int red, green, blue;
    Vector proTemTable;

    public ColortblDestination()
    {
        red = 0;
        green = 0;
        blue = 0;
        proTemTable = new Vector();
    }

    public void handleText(String text)
    {
        int index = 0;

        for (index = 0; index < text.length(); index ++) {
            if (text.charAt(index) == ';') {
                Color newColor;
                newColor = new Color(red, green, blue);
                proTemTable.addElement(newColor);
            }
        }
    }

    public void close()
    {
        int count = proTemTable.size();
        warning("Done reading color table, " + count + " entries.");
        colorTable = new Color[count];
        proTemTable.copyInto(colorTable);
    }

    public boolean handleKeyword(String keyword, int parameter)
    {
        if (keyword.equals("red"))
            red = parameter;
        else if (keyword.equals("green"))
            green = parameter;
        else if (keyword.equals("blue"))
            blue = parameter;
        else
            return false;

        return true;
    }

    /* Colortbls don't understand any parameterless keywords */
    public boolean handleKeyword(String keyword) { return false; }

    /* Groups are irrelevant. */
    public void begingroup() {}
    public void endgroup(Dictionary oldState) {}

    /* Shouldn't see any binary blobs ... */
    public void handleBinaryBlob(byte[] data) {}
}

/** Handles the stylesheet keyword. Styles are read and sorted
 *  into the three style arrays in the RTFReader. */
class StylesheetDestination
    extends DiscardingDestination
    implements Destination
{
    Dictionary definedStyles;

    public StylesheetDestination()
    {
        definedStyles = new Hashtable();
    }

    public void begingroup()
    {
        setRTFDestination(new StyleDefiningDestination());
    }

    public void close()
    {
        Vector chrStyles, pgfStyles, secStyles;
        chrStyles = new Vector();
        pgfStyles = new Vector();
        secStyles = new Vector();
        Enumeration styles = definedStyles.elements();
        while(styles.hasMoreElements()) {
            StyleDefiningDestination style;
            Style defined;
            style = (StyleDefiningDestination)styles.nextElement();
            defined = style.realize();
            warning("Style "+style.number+" ("+style.styleName+"): "+defined);
            String stype = (String)defined.getAttribute(Constants.StyleType);
            Vector toSet;
            if (stype.equals(Constants.STSection)) {
                toSet = secStyles;
            } else if (stype.equals(Constants.STCharacter)) {
                toSet = chrStyles;
            } else {
                toSet = pgfStyles;
            }
            if (toSet.size() <= style.number)
                toSet.setSize(style.number + 1);
            toSet.setElementAt(defined, style.number);
        }
        if (!(chrStyles.isEmpty())) {
            Style[] styleArray = new Style[chrStyles.size()];
            chrStyles.copyInto(styleArray);
            characterStyles = styleArray;
        }
        if (!(pgfStyles.isEmpty())) {
            Style[] styleArray = new Style[pgfStyles.size()];
            pgfStyles.copyInto(styleArray);
            paragraphStyles = styleArray;
        }
        if (!(secStyles.isEmpty())) {
            Style[] styleArray = new Style[secStyles.size()];
            secStyles.copyInto(styleArray);
            sectionStyles = styleArray;
        }

/* (old debugging code)
        int i, m;
        if (characterStyles != null) {
          m = characterStyles.length;
          for(i=0;i<m;i++)
            warnings.println("chrStyle["+i+"]="+characterStyles[i]);
        } else warnings.println("No character styles.");
        if (paragraphStyles != null) {
          m = paragraphStyles.length;
          for(i=0;i<m;i++)
            warnings.println("pgfStyle["+i+"]="+paragraphStyles[i]);
        } else warnings.println("No paragraph styles.");
        if (sectionStyles != null) {
          m = characterStyles.length;
          for(i=0;i<m;i++)
            warnings.println("secStyle["+i+"]="+sectionStyles[i]);
        } else warnings.println("No section styles.");
*/
    }

    /** This subclass handles an individual style */
    class StyleDefiningDestination
        extends AttributeTrackingDestination
        implements Destination
    {
        final int STYLENUMBER_NONE = 222;
        boolean additive;
        boolean characterStyle;
        boolean sectionStyle;
        public String styleName;
        public int number;
        int basedOn;
        int nextStyle;
        boolean hidden;

        Style realizedStyle;

        public StyleDefiningDestination()
        {
            additive = false;
            characterStyle = false;
            sectionStyle = false;
            styleName = null;
            number = 0;
            basedOn = STYLENUMBER_NONE;
            nextStyle = STYLENUMBER_NONE;
            hidden = false;
        }

        public void handleText(String text)
        {
            if (styleName != null)
                styleName = styleName + text;
            else
                styleName = text;
        }

        public void close() {
            int semicolon = (styleName == null) ? 0 : styleName.indexOf(';');
            if (semicolon > 0)
                styleName = styleName.substring(0, semicolon);
            definedStyles.put(Integer.valueOf(number), this);
            super.close();
        }

        public boolean handleKeyword(String keyword)
        {
            if (keyword.equals("additive")) {
                additive = true;
                return true;
            }
            if (keyword.equals("shidden")) {
                hidden = true;
                return true;
            }
            return super.handleKeyword(keyword);
        }

        public boolean handleKeyword(String keyword, int parameter)
        {
            if (keyword.equals("s")) {
                characterStyle = false;
                sectionStyle = false;
                number = parameter;
            } else if (keyword.equals("cs")) {
                characterStyle = true;
                sectionStyle = false;
                number = parameter;
            } else if (keyword.equals("ds")) {
                characterStyle = false;
                sectionStyle = true;
                number = parameter;
            } else if (keyword.equals("sbasedon")) {
                basedOn = parameter;
            } else if (keyword.equals("snext")) {
                nextStyle = parameter;
            } else {
                return super.handleKeyword(keyword, parameter);
            }
            return true;
        }

        public Style realize()
        {
            Style basis = null;
            Style next = null;

            if (realizedStyle != null)
                return realizedStyle;

            if (basedOn != STYLENUMBER_NONE) {
                StyleDefiningDestination styleDest;
                styleDest = (StyleDefiningDestination)definedStyles.get(Integer.valueOf(basedOn));
                if (styleDest != null && styleDest != this) {
                    basis = styleDest.realize();
                }
            }

            /* NB: Swing StyleContext doesn't allow distinct styles with
               the same name; RTF apparently does. This may confuse the
               user. */
            realizedStyle = target.addStyle(styleName, basis);

            if (characterStyle) {
                realizedStyle.addAttributes(currentTextAttributes());
                realizedStyle.addAttribute(Constants.StyleType,
                                           Constants.STCharacter);
            } else if (sectionStyle) {
                realizedStyle.addAttributes(currentSectionAttributes());
                realizedStyle.addAttribute(Constants.StyleType,
                                           Constants.STSection);
            } else { /* must be a paragraph style */
                realizedStyle.addAttributes(currentParagraphAttributes());
                realizedStyle.addAttribute(Constants.StyleType,
                                           Constants.STParagraph);
            }

            if (nextStyle != STYLENUMBER_NONE) {
                StyleDefiningDestination styleDest;
                styleDest = (StyleDefiningDestination)definedStyles.get(Integer.valueOf(nextStyle));
                if (styleDest != null) {
                    next = styleDest.realize();
                }
            }

            if (next != null)
                realizedStyle.addAttribute(Constants.StyleNext, next);
            realizedStyle.addAttribute(Constants.StyleAdditive,
                                       Boolean.valueOf(additive));
            realizedStyle.addAttribute(Constants.StyleHidden,
                                       Boolean.valueOf(hidden));

            return realizedStyle;
        }
    }
}

/** Handles the info group. Currently no info keywords are recognized
 *  so this is a subclass of DiscardingDestination. */
class InfoDestination
    extends DiscardingDestination
    implements Destination
{
}

/** RTFReader.TextHandlingDestination is an abstract RTF destination
 *  which simply tracks the attributes specified by the RTF control words
 *  in internal form and can produce acceptable AttributeSets for the
 *  current character, paragraph, and section attributes. It is up
 *  to the subclasses to determine what is done with the actual text. */
abstract class AttributeTrackingDestination implements Destination
{
    /** This is the "chr" element of parserState, cached for
     *  more efficient use */
    MutableAttributeSet characterAttributes;
    /** This is the "pgf" element of parserState, cached for
     *  more efficient use */
    MutableAttributeSet paragraphAttributes;
    /** This is the "sec" element of parserState, cached for
     *  more efficient use */
    MutableAttributeSet sectionAttributes;

    public AttributeTrackingDestination()
    {
        characterAttributes = rootCharacterAttributes();
        parserState.put("chr", characterAttributes);
        paragraphAttributes = rootParagraphAttributes();
        parserState.put("pgf", paragraphAttributes);
        sectionAttributes = rootSectionAttributes();
        parserState.put("sec", sectionAttributes);
    }

    abstract public void handleText(String text);

    public void handleBinaryBlob(byte[] data)
    {
        /* This should really be in TextHandlingDestination, but
         * since *nobody* does anything with binary blobs, this
         * is more convenient. */
        warning("Unexpected binary data in RTF file.");
    }

    public void begingroup()
    {
        AttributeSet characterParent = currentTextAttributes();
        AttributeSet paragraphParent = currentParagraphAttributes();
        AttributeSet sectionParent = currentSectionAttributes();

        /* It would probably be more efficient to use the
         * resolver property of the attributes set for
         * implementing rtf groups,
         * but that's needed for styles. */

        /* update the cached attribute dictionaries */
        characterAttributes = new SimpleAttributeSet();
        characterAttributes.addAttributes(characterParent);
        parserState.put("chr", characterAttributes);

        paragraphAttributes = new SimpleAttributeSet();
        paragraphAttributes.addAttributes(paragraphParent);
        parserState.put("pgf", paragraphAttributes);

        sectionAttributes = new SimpleAttributeSet();
        sectionAttributes.addAttributes(sectionParent);
        parserState.put("sec", sectionAttributes);
    }

    public void endgroup(Dictionary oldState)
    {
        characterAttributes = (MutableAttributeSet)parserState.get("chr");
        paragraphAttributes = (MutableAttributeSet)parserState.get("pgf");
        sectionAttributes   = (MutableAttributeSet)parserState.get("sec");
    }

    public void close()
    {
    }

    public boolean handleKeyword(String keyword)
    {
        if (keyword.equals("ulnone")) {
            return handleKeyword("ul", 0);
        }

        {
            Object item = straightforwardAttributes.get(keyword);
            if (item != null) {
                RTFAttribute attr = (RTFAttribute)item;
                boolean ok;

                switch(attr.domain()) {
                  case RTFAttribute.D_CHARACTER:
                    ok = attr.set(characterAttributes);
                    break;
                  case RTFAttribute.D_PARAGRAPH:
                    ok = attr.set(paragraphAttributes);
                    break;
                  case RTFAttribute.D_SECTION:
                    ok = attr.set(sectionAttributes);
                    break;
                  case RTFAttribute.D_META:
                    mockery.backing = parserState;
                    ok = attr.set(mockery);
                    mockery.backing = null;
                    break;
                  case RTFAttribute.D_DOCUMENT:
                    ok = attr.set(documentAttributes);
                    break;
                  default:
                    /* should never happen */
                    ok = false;
                    break;
                }
                if (ok)
                    return true;
            }
        }


        if (keyword.equals("plain")) {
            resetCharacterAttributes();
            return true;
        }

        if (keyword.equals("pard")) {
            resetParagraphAttributes();
            return true;
        }

        if (keyword.equals("sectd")) {
            resetSectionAttributes();
            return true;
        }

        return false;
    }

    public boolean handleKeyword(String keyword, int parameter)
    {
        boolean booleanParameter = (parameter != 0);

        if (keyword.equals("fc"))
            keyword = "cf"; /* whatEVER, dude. */

        if (keyword.equals("f")) {
            parserState.put(keyword, Integer.valueOf(parameter));
            return true;
        }
        if (keyword.equals("cf")) {
            parserState.put(keyword, Integer.valueOf(parameter));
            return true;
        }

        {
            Object item = straightforwardAttributes.get(keyword);
            if (item != null) {
                RTFAttribute attr = (RTFAttribute)item;
                boolean ok;

                switch(attr.domain()) {
                  case RTFAttribute.D_CHARACTER:
                    ok = attr.set(characterAttributes, parameter);
                    break;
                  case RTFAttribute.D_PARAGRAPH:
                    ok = attr.set(paragraphAttributes, parameter);
                    break;
                  case RTFAttribute.D_SECTION:
                    ok = attr.set(sectionAttributes, parameter);
                    break;
                  case RTFAttribute.D_META:
                    mockery.backing = parserState;
                    ok = attr.set(mockery, parameter);
                    mockery.backing = null;
                    break;
                  case RTFAttribute.D_DOCUMENT:
                    ok = attr.set(documentAttributes, parameter);
                    break;
                  default:
                    /* should never happen */
                    ok = false;
                    break;
                }
                if (ok)
                    return true;
            }
        }

        if (keyword.equals("fs")) {
            StyleConstants.setFontSize(characterAttributes, (parameter / 2));
            return true;
        }

        /* TODO: superscript/subscript */

        if (keyword.equals("sl")) {
            if (parameter == 1000) {  /* magic value! */
                characterAttributes.removeAttribute(StyleConstants.LineSpacing);
            } else {
                /* TODO: The RTF sl attribute has special meaning if it's
                   negative. Make sure that SwingText has the same special
                   meaning, or find a way to imitate that. When SwingText
                   handles this, also recognize the slmult keyword. */
                StyleConstants.setLineSpacing(characterAttributes,
                                              parameter / 20f);
            }
            return true;
        }

        /* TODO: Other kinds of underlining */

        if (keyword.equals("tx") || keyword.equals("tb")) {
            float tabPosition = parameter / 20f;
            int tabAlignment, tabLeader;
            Number item;

            tabAlignment = TabStop.ALIGN_LEFT;
            item = (Number)(parserState.get("tab_alignment"));
            if (item != null)
                tabAlignment = item.intValue();
            tabLeader = TabStop.LEAD_NONE;
            item = (Number)(parserState.get("tab_leader"));
            if (item != null)
                tabLeader = item.intValue();
            if (keyword.equals("tb"))
                tabAlignment = TabStop.ALIGN_BAR;

            parserState.remove("tab_alignment");
            parserState.remove("tab_leader");

            TabStop newStop = new TabStop(tabPosition, tabAlignment, tabLeader);
            Dictionary tabs;
            Integer stopCount;

            tabs = (Dictionary)parserState.get("_tabs");
            if (tabs == null) {
                tabs = new Hashtable();
                parserState.put("_tabs", tabs);
                stopCount = Integer.valueOf(1);
            } else {
                stopCount = (Integer)tabs.get("stop count");
                stopCount = Integer.valueOf(1 + stopCount.intValue());
            }
            tabs.put(stopCount, newStop);
            tabs.put("stop count", stopCount);
            parserState.remove("_tabs_immutable");

            return true;
        }

        if (keyword.equals("s") &&
            paragraphStyles != null) {
            parserState.put("paragraphStyle", paragraphStyles[parameter]);
            return true;
        }

        if (keyword.equals("cs") &&
            characterStyles != null) {
            parserState.put("characterStyle", characterStyles[parameter]);
            return true;
        }

        if (keyword.equals("ds") &&
            sectionStyles != null) {
            parserState.put("sectionStyle", sectionStyles[parameter]);
            return true;
        }

        return false;
    }

    /** Returns a new MutableAttributeSet containing the
     *  default character attributes */
    protected MutableAttributeSet rootCharacterAttributes()
    {
        MutableAttributeSet set = new SimpleAttributeSet();

        /* TODO: default font */

        StyleConstants.setItalic(set, false);
        StyleConstants.setBold(set, false);
        StyleConstants.setUnderline(set, false);
        StyleConstants.setForeground(set, defaultColor());

        return set;
    }

    /** Returns a new MutableAttributeSet containing the
     *  default paragraph attributes */
    protected MutableAttributeSet rootParagraphAttributes()
    {
        MutableAttributeSet set = new SimpleAttributeSet();

        StyleConstants.setLeftIndent(set, 0f);
        StyleConstants.setRightIndent(set, 0f);
        StyleConstants.setFirstLineIndent(set, 0f);

        /* TODO: what should this be, really? */
        set.setResolveParent(target.getStyle(StyleContext.DEFAULT_STYLE));

        return set;
    }

    /** Returns a new MutableAttributeSet containing the
     *  default section attributes */
    protected MutableAttributeSet rootSectionAttributes()
    {
        MutableAttributeSet set = new SimpleAttributeSet();

        return set;
    }

    /**
     * Calculates the current text (character) attributes in a form suitable
     * for SwingText from the current parser state.
     *
     * @returns a new MutableAttributeSet containing the text attributes.
     */
    MutableAttributeSet currentTextAttributes()
    {
        MutableAttributeSet attributes =
            new SimpleAttributeSet(characterAttributes);
        Integer fontnum;
        Integer stateItem;

        /* figure out the font name */
        /* TODO: catch exceptions for undefined attributes,
           bad font indices, etc.? (as it stands, it is the caller's
           job to clean up after corrupt RTF) */
        fontnum = (Integer)parserState.get("f");
        /* note setFontFamily() can not handle a null font */
        String fontFamily;
        if (fontnum != null)
            fontFamily = (String)fontTable.get(fontnum);
        else
            fontFamily = null;
        if (fontFamily != null)
            StyleConstants.setFontFamily(attributes, fontFamily);
        else
            attributes.removeAttribute(StyleConstants.FontFamily);

        if (colorTable != null) {
            stateItem = (Integer)parserState.get("cf");
            if (stateItem != null) {
                Color fg = colorTable[stateItem.intValue()];
                StyleConstants.setForeground(attributes, fg);
            } else {
                /* AttributeSet dies if you set a value to null */
                attributes.removeAttribute(StyleConstants.Foreground);
            }
        }

        if (colorTable != null) {
            stateItem = (Integer)parserState.get("cb");
            if (stateItem != null) {
                Color bg = colorTable[stateItem.intValue()];
                attributes.addAttribute(StyleConstants.Background,
                                        bg);
            } else {
                /* AttributeSet dies if you set a value to null */
                attributes.removeAttribute(StyleConstants.Background);
            }
        }

        Style characterStyle = (Style)parserState.get("characterStyle");
        if (characterStyle != null)
            attributes.setResolveParent(characterStyle);

        /* Other attributes are maintained directly in "attributes" */

        return attributes;
    }

    /**
     * Calculates the current paragraph attributes (with keys
     * as given in StyleConstants) from the current parser state.
     *
     * @returns a newly created MutableAttributeSet.
     * @see StyleConstants
     */
    MutableAttributeSet currentParagraphAttributes()
    {
        /* NB if there were a mutableCopy() method we should use it */
        MutableAttributeSet bld = new SimpleAttributeSet(paragraphAttributes);

        Integer stateItem;

        /*** Tab stops ***/
        TabStop tabs[];

        tabs = (TabStop[])parserState.get("_tabs_immutable");
        if (tabs == null) {
            Dictionary workingTabs = (Dictionary)parserState.get("_tabs");
            if (workingTabs != null) {
                int count = ((Integer)workingTabs.get("stop count")).intValue();
                tabs = new TabStop[count];
                for (int ix = 1; ix <= count; ix ++)
                    tabs[ix-1] = (TabStop)workingTabs.get(Integer.valueOf(ix));
                parserState.put("_tabs_immutable", tabs);
            }
        }
        if (tabs != null)
            bld.addAttribute(Constants.Tabs, tabs);

        Style paragraphStyle = (Style)parserState.get("paragraphStyle");
        if (paragraphStyle != null)
            bld.setResolveParent(paragraphStyle);

        return bld;
    }

    /**
     * Calculates the current section attributes
     * from the current parser state.
     *
     * @returns a newly created MutableAttributeSet.
     */
    public AttributeSet currentSectionAttributes()
    {
        MutableAttributeSet attributes = new SimpleAttributeSet(sectionAttributes);

        Style sectionStyle = (Style)parserState.get("sectionStyle");
        if (sectionStyle != null)
            attributes.setResolveParent(sectionStyle);

        return attributes;
    }

    /** Resets the filter's internal notion of the current character
     *  attributes to their default values. Invoked to handle the
     *  \plain keyword. */
    protected void resetCharacterAttributes()
    {
        handleKeyword("f", 0);
        handleKeyword("cf", 0);

        handleKeyword("fs", 24);  /* 12 pt. */

        Enumeration attributes = straightforwardAttributes.elements();
        while(attributes.hasMoreElements()) {
            RTFAttribute attr = (RTFAttribute)attributes.nextElement();
            if (attr.domain() == RTFAttribute.D_CHARACTER)
                attr.setDefault(characterAttributes);
        }

        handleKeyword("sl", 1000);

        parserState.remove("characterStyle");
    }

    /** Resets the filter's internal notion of the current paragraph's
     *  attributes to their default values. Invoked to handle the
     *  \pard keyword. */
    protected void resetParagraphAttributes()
    {
        parserState.remove("_tabs");
        parserState.remove("_tabs_immutable");
        parserState.remove("paragraphStyle");

        StyleConstants.setAlignment(paragraphAttributes,
                                    StyleConstants.ALIGN_LEFT);

        Enumeration attributes = straightforwardAttributes.elements();
        while(attributes.hasMoreElements()) {
            RTFAttribute attr = (RTFAttribute)attributes.nextElement();
            if (attr.domain() == RTFAttribute.D_PARAGRAPH)
                attr.setDefault(characterAttributes);
        }
    }

    /** Resets the filter's internal notion of the current section's
     *  attributes to their default values. Invoked to handle the
     *  \sectd keyword. */
    protected void resetSectionAttributes()
    {
        Enumeration attributes = straightforwardAttributes.elements();
        while(attributes.hasMoreElements()) {
            RTFAttribute attr = (RTFAttribute)attributes.nextElement();
            if (attr.domain() == RTFAttribute.D_SECTION)
                attr.setDefault(characterAttributes);
        }

        parserState.remove("sectionStyle");
    }
}

/** RTFReader.TextHandlingDestination provides basic text handling
 *  functionality. Subclasses must implement: <dl>
 *  <dt>deliverText()<dd>to handle a run of text with the same
 *                       attributes
 *  <dt>finishParagraph()<dd>to end the current paragraph and
 *                           set the paragraph's attributes
 *  <dt>endSection()<dd>to end the current section
 *  </dl>
 */
abstract class TextHandlingDestination
    extends AttributeTrackingDestination
    implements Destination
{
    /** <code>true</code> if the reader has not just finished
     *  a paragraph; false upon startup */
    boolean inParagraph;

    public TextHandlingDestination()
    {
        super();
        inParagraph = false;
    }

    public void handleText(String text)
    {
        if (! inParagraph)
            beginParagraph();

        deliverText(text, currentTextAttributes());
    }

    abstract void deliverText(String text, AttributeSet characterAttributes);

    public void close()
    {
        if (inParagraph)
            endParagraph();

        super.close();
    }

    public boolean handleKeyword(String keyword)
    {
        if (keyword.equals("\r") || keyword.equals("\n")) {
            keyword = "par";
        }

        if (keyword.equals("par")) {
//          warnings.println("Ending paragraph.");
            endParagraph();
            return true;
        }

        if (keyword.equals("sect")) {
//          warnings.println("Ending section.");
            endSection();
            return true;
        }

        return super.handleKeyword(keyword);
    }

    protected void beginParagraph()
    {
        inParagraph = true;
    }

    protected void endParagraph()
    {
        AttributeSet pgfAttributes = currentParagraphAttributes();
        AttributeSet chrAttributes = currentTextAttributes();
        finishParagraph(pgfAttributes, chrAttributes);
        inParagraph = false;
    }

    abstract void finishParagraph(AttributeSet pgfA, AttributeSet chrA);

    abstract void endSection();
}

/** RTFReader.DocumentDestination is a concrete subclass of
 *  TextHandlingDestination which appends the text to the
 *  StyledDocument given by the <code>target</code> ivar of the
 *  containing RTFReader.
 */
class DocumentDestination
    extends TextHandlingDestination
    implements Destination
{
    public void deliverText(String text, AttributeSet characterAttributes)
    {
        try {
            target.insertString(target.getLength(),
                                text,
                                currentTextAttributes());
        } catch (BadLocationException ble) {
            /* This shouldn't be able to happen, of course */
            /* TODO is InternalError the correct error to throw? */
            throw new InternalError(ble.getMessage());
        }
    }

    public void finishParagraph(AttributeSet pgfAttributes,
                                AttributeSet chrAttributes)
    {
        int pgfEndPosition = target.getLength();
        try {
            target.insertString(pgfEndPosition, "\n", chrAttributes);
            target.setParagraphAttributes(pgfEndPosition, 1, pgfAttributes, true);
        } catch (BadLocationException ble) {
            /* This shouldn't be able to happen, of course */
            /* TODO is InternalError the correct error to throw? */
            throw new InternalError(ble.getMessage());
        }
    }

    public void endSection()
    {
        /* If we implemented sections, we'd end 'em here */
    }
}

}
