/*
 * Copyright 1997-2002 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.awt.Color;
import java.awt.Font;
import java.io.OutputStream;
import java.io.IOException;

import javax.swing.text.*;

/**
 * Generates an RTF output stream (java.io.OutputStream) from rich text
 * (handed off through a series of LTTextAcceptor calls).  Can be used to
 * generate RTF from any object which knows how to write to a text acceptor
 * (e.g., LTAttributedText and LTRTFFilter).
 *
 * <p>Note that this is a lossy conversion since RTF's model of
 * text does not exactly correspond with LightText's.
 *
 * @see LTAttributedText
 * @see LTRTFFilter
 * @see LTTextAcceptor
 * @see java.io.OutputStream
 */

class RTFGenerator extends Object
{
    /* These dictionaries map Colors, font names, or Style objects
       to Integers */
    Dictionary colorTable;
    int colorCount;
    Dictionary fontTable;
    int fontCount;
    Dictionary styleTable;
    int styleCount;

    /* where all the text is going */
    OutputStream outputStream;

    boolean afterKeyword;

    MutableAttributeSet outputAttributes;

    /* the value of the last \\ucN keyword emitted */
    int unicodeCount;

    /* for efficiency's sake (ha) */
    private Segment workingSegment;

    int[] outputConversion;

    /** The default color, used for text without an explicit color
     *  attribute. */
    static public final Color defaultRTFColor = Color.black;

    static public final float defaultFontSize = 12f;

    static public final String defaultFontFamily = "Helvetica";

    /* constants so we can avoid allocating objects in inner loops */
    /* these should all be final, but javac seems to be a bit buggy */
    static protected Integer One, Zero;
    static protected Boolean False;
    static protected Float ZeroPointZero;
    static private Object MagicToken;

    /* An array of character-keyword pairs. This could be done
       as a dictionary (and lookup would be quicker), but that
       would require allocating an object for every character
       written (slow!). */
    static class CharacterKeywordPair
      { public char character; public String keyword; };
    static protected CharacterKeywordPair[] textKeywords;

    static {
        One = new Integer(1);
        Zero = new Integer(0);
        False = Boolean.valueOf(false);
        MagicToken = new Object();
        ZeroPointZero = new Float(0);

        Dictionary textKeywordDictionary = RTFReader.textKeywords;
        Enumeration keys = textKeywordDictionary.keys();
        Vector tempPairs = new Vector();
        while(keys.hasMoreElements()) {
            CharacterKeywordPair pair = new CharacterKeywordPair();
            pair.keyword = (String)keys.nextElement();
            pair.character = ((String)textKeywordDictionary.get(pair.keyword)).charAt(0);
            tempPairs.addElement(pair);
        }
        textKeywords = new CharacterKeywordPair[tempPairs.size()];
        tempPairs.copyInto(textKeywords);
    }

    static final char[] hexdigits = { '0', '1', '2', '3', '4', '5', '6', '7',
                                      '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

static public void writeDocument(Document d, OutputStream to)
    throws IOException
{
    RTFGenerator gen = new RTFGenerator(to);
    Element root = d.getDefaultRootElement();

    gen.examineElement(root);
    gen.writeRTFHeader();
    gen.writeDocumentProperties(d);

    /* TODO this assumes a particular element structure; is there
       a way to iterate more generically ? */
    int max = root.getElementCount();
    for(int idx = 0; idx < max; idx++)
        gen.writeParagraphElement(root.getElement(idx));

    gen.writeRTFTrailer();
}

public RTFGenerator(OutputStream to)
{
    colorTable = new Hashtable();
    colorTable.put(defaultRTFColor, new Integer(0));
    colorCount = 1;

    fontTable = new Hashtable();
    fontCount = 0;

    styleTable = new Hashtable();
    /* TODO: put default style in style table */
    styleCount = 0;

    workingSegment = new Segment();

    outputStream = to;

    unicodeCount = 1;
}

public void examineElement(Element el)
{
    AttributeSet a = el.getAttributes();
    String fontName;
    Object foregroundColor, backgroundColor;

    tallyStyles(a);

    if (a != null) {
        /* TODO: default color must be color 0! */

        foregroundColor = StyleConstants.getForeground(a);
        if (foregroundColor != null &&
            colorTable.get(foregroundColor) == null) {
            colorTable.put(foregroundColor, new Integer(colorCount));
            colorCount ++;
        }

        backgroundColor = a.getAttribute(StyleConstants.Background);
        if (backgroundColor != null &&
            colorTable.get(backgroundColor) == null) {
            colorTable.put(backgroundColor, new Integer(colorCount));
            colorCount ++;
        }

        fontName = StyleConstants.getFontFamily(a);

        if (fontName == null)
            fontName = defaultFontFamily;

        if (fontName != null &&
            fontTable.get(fontName) == null) {
            fontTable.put(fontName, new Integer(fontCount));
            fontCount ++;
        }
    }

    int el_count = el.getElementCount();
    for(int el_idx = 0; el_idx < el_count; el_idx ++) {
        examineElement(el.getElement(el_idx));
    }
}

private void tallyStyles(AttributeSet a) {
    while (a != null) {
        if (a instanceof Style) {
            Integer aNum = (Integer)styleTable.get(a);
            if (aNum == null) {
                styleCount = styleCount + 1;
                aNum = new Integer(styleCount);
                styleTable.put(a, aNum);
            }
        }
        a = a.getResolveParent();
    }
}

private Style findStyle(AttributeSet a)
{
    while(a != null) {
        if (a instanceof Style) {
            Object aNum = styleTable.get(a);
            if (aNum != null)
                return (Style)a;
        }
        a = a.getResolveParent();
    }
    return null;
}

private Integer findStyleNumber(AttributeSet a, String domain)
{
    while(a != null) {
        if (a instanceof Style) {
            Integer aNum = (Integer)styleTable.get(a);
            if (aNum != null) {
                if (domain == null ||
                    domain.equals(a.getAttribute(Constants.StyleType)))
                    return aNum;
            }

        }
        a = a.getResolveParent();
    }
    return null;
}

static private Object attrDiff(MutableAttributeSet oldAttrs,
                               AttributeSet newAttrs,
                               Object key,
                               Object dfl)
{
    Object oldValue, newValue;

    oldValue = oldAttrs.getAttribute(key);
    newValue = newAttrs.getAttribute(key);

    if (newValue == oldValue)
        return null;
    if (newValue == null) {
        oldAttrs.removeAttribute(key);
        if (dfl != null && !dfl.equals(oldValue))
            return dfl;
        else
            return null;
    }
    if (oldValue == null ||
        !equalArraysOK(oldValue, newValue)) {
        oldAttrs.addAttribute(key, newValue);
        return newValue;
    }
    return null;
}

static private boolean equalArraysOK(Object a, Object b)
{
    Object[] aa, bb;
    if (a == b)
        return true;
    if (a == null || b == null)
        return false;
    if (a.equals(b))
        return true;
    if (!(a.getClass().isArray() && b.getClass().isArray()))
        return false;
    aa = (Object[])a;
    bb = (Object[])b;
    if (aa.length != bb.length)
        return false;

    int i;
    int l = aa.length;
    for(i = 0; i < l; i++) {
        if (!equalArraysOK(aa[i], bb[i]))
            return false;
    }

    return true;
}

/* Writes a line break to the output file, for ease in debugging */
public void writeLineBreak()
    throws IOException
{
    writeRawString("\n");
    afterKeyword = false;
}


public void writeRTFHeader()
    throws IOException
{
    int index;

    /* TODO: Should the writer attempt to examine the text it's writing
       and pick a character set which will most compactly represent the
       document? (currently the writer always uses the ansi character
       set, which is roughly ISO-8859 Latin-1, and uses Unicode escapes
       for all other characters. However Unicode is a relatively
       recent addition to RTF, and not all readers will understand it.) */
    writeBegingroup();
    writeControlWord("rtf", 1);
    writeControlWord("ansi");
    outputConversion = outputConversionForName("ansi");
    writeLineBreak();

    /* write font table */
    String[] sortedFontTable = new String[fontCount];
    Enumeration fonts = fontTable.keys();
    String font;
    while(fonts.hasMoreElements()) {
        font = (String)fonts.nextElement();
        Integer num = (Integer)(fontTable.get(font));
        sortedFontTable[num.intValue()] = font;
    }
    writeBegingroup();
    writeControlWord("fonttbl");
    for(index = 0; index < fontCount; index ++) {
        writeControlWord("f", index);
        writeControlWord("fnil");  /* TODO: supply correct font style */
        writeText(sortedFontTable[index]);
        writeText(";");
    }
    writeEndgroup();
    writeLineBreak();

    /* write color table */
    if (colorCount > 1) {
        Color[] sortedColorTable = new Color[colorCount];
        Enumeration colors = colorTable.keys();
        Color color;
        while(colors.hasMoreElements()) {
            color = (Color)colors.nextElement();
            Integer num = (Integer)(colorTable.get(color));
            sortedColorTable[num.intValue()] = color;
        }
        writeBegingroup();
        writeControlWord("colortbl");
        for(index = 0; index < colorCount; index ++) {
            color = sortedColorTable[index];
            if (color != null) {
                writeControlWord("red", color.getRed());
                writeControlWord("green", color.getGreen());
                writeControlWord("blue", color.getBlue());
            }
            writeRawString(";");
        }
        writeEndgroup();
        writeLineBreak();
    }

    /* write the style sheet */
    if (styleCount > 1) {
        writeBegingroup();
        writeControlWord("stylesheet");
        Enumeration styles = styleTable.keys();
        while(styles.hasMoreElements()) {
            Style style = (Style)styles.nextElement();
            int styleNumber = ((Integer)styleTable.get(style)).intValue();
            writeBegingroup();
            String styleType = (String)style.getAttribute(Constants.StyleType);
            if (styleType == null)
                styleType = Constants.STParagraph;
            if (styleType.equals(Constants.STCharacter)) {
                writeControlWord("*");
                writeControlWord("cs", styleNumber);
            } else if(styleType.equals(Constants.STSection)) {
                writeControlWord("*");
                writeControlWord("ds", styleNumber);
            } else {
                writeControlWord("s", styleNumber);
            }

            AttributeSet basis = style.getResolveParent();
            MutableAttributeSet goat;
            if (basis == null) {
                goat = new SimpleAttributeSet();
            } else {
                goat = new SimpleAttributeSet(basis);
            }

            updateSectionAttributes(goat, style, false);
            updateParagraphAttributes(goat, style, false);
            updateCharacterAttributes(goat, style, false);

            basis = style.getResolveParent();
            if (basis != null && basis instanceof Style) {
                Integer basedOn = (Integer)styleTable.get(basis);
                if (basedOn != null) {
                    writeControlWord("sbasedon", basedOn.intValue());
                }
            }

            Style nextStyle = (Style)style.getAttribute(Constants.StyleNext);
            if (nextStyle != null) {
                Integer nextNum = (Integer)styleTable.get(nextStyle);
                if (nextNum != null) {
                    writeControlWord("snext", nextNum.intValue());
                }
            }

            Boolean hidden = (Boolean)style.getAttribute(Constants.StyleHidden);
            if (hidden != null && hidden.booleanValue())
                writeControlWord("shidden");

            Boolean additive = (Boolean)style.getAttribute(Constants.StyleAdditive);
            if (additive != null && additive.booleanValue())
                writeControlWord("additive");


            writeText(style.getName());
            writeText(";");
            writeEndgroup();
        }
        writeEndgroup();
        writeLineBreak();
    }

    outputAttributes = new SimpleAttributeSet();
}

void writeDocumentProperties(Document doc)
    throws IOException
{
    /* Write the document properties */
    int i;
    boolean wroteSomething = false;

    for(i = 0; i < RTFAttributes.attributes.length; i++) {
        RTFAttribute attr = RTFAttributes.attributes[i];
        if (attr.domain() != RTFAttribute.D_DOCUMENT)
            continue;
        Object prop = doc.getProperty(attr.swingName());
        boolean ok = attr.writeValue(prop, this, false);
        if (ok)
            wroteSomething = true;
    }

    if (wroteSomething)
        writeLineBreak();
}

public void writeRTFTrailer()
    throws IOException
{
    writeEndgroup();
    writeLineBreak();
}

protected void checkNumericControlWord(MutableAttributeSet currentAttributes,
                                       AttributeSet newAttributes,
                                       Object attrName,
                                       String controlWord,
                                       float dflt, float scale)
    throws IOException
{
    Object parm;

    if ((parm = attrDiff(currentAttributes, newAttributes,
                         attrName, MagicToken)) != null) {
        float targ;
        if (parm == MagicToken)
            targ = dflt;
        else
            targ = ((Number)parm).floatValue();
        writeControlWord(controlWord, Math.round(targ * scale));
    }
}

protected void checkControlWord(MutableAttributeSet currentAttributes,
                                AttributeSet newAttributes,
                                RTFAttribute word)
    throws IOException
{
    Object parm;

    if ((parm = attrDiff(currentAttributes, newAttributes,
                         word.swingName(), MagicToken)) != null) {
        if (parm == MagicToken)
            parm = null;
        word.writeValue(parm, this, true);
    }
}

protected void checkControlWords(MutableAttributeSet currentAttributes,
                                 AttributeSet newAttributes,
                                 RTFAttribute words[],
                                 int domain)
    throws IOException
{
    int wordIndex;
    int wordCount = words.length;
    for(wordIndex = 0; wordIndex < wordCount; wordIndex++) {
        RTFAttribute attr = words[wordIndex];
        if (attr.domain() == domain)
            checkControlWord(currentAttributes, newAttributes, attr);
    }
}

void updateSectionAttributes(MutableAttributeSet current,
                             AttributeSet newAttributes,
                             boolean emitStyleChanges)
    throws IOException
{
    if (emitStyleChanges) {
        Object oldStyle = current.getAttribute("sectionStyle");
        Object newStyle = findStyleNumber(newAttributes, Constants.STSection);
        if (oldStyle != newStyle) {
            if (oldStyle != null) {
                resetSectionAttributes(current);
            }
            if (newStyle != null) {
                writeControlWord("ds", ((Integer)newStyle).intValue());
                current.addAttribute("sectionStyle", newStyle);
            } else {
                current.removeAttribute("sectionStyle");
            }
        }
    }

    checkControlWords(current, newAttributes,
                      RTFAttributes.attributes, RTFAttribute.D_SECTION);
}

protected void resetSectionAttributes(MutableAttributeSet currentAttributes)
    throws IOException
{
    writeControlWord("sectd");

    int wordIndex;
    int wordCount = RTFAttributes.attributes.length;
    for(wordIndex = 0; wordIndex < wordCount; wordIndex++) {
        RTFAttribute attr = RTFAttributes.attributes[wordIndex];
        if (attr.domain() == RTFAttribute.D_SECTION)
            attr.setDefault(currentAttributes);
    }

    currentAttributes.removeAttribute("sectionStyle");
}

void updateParagraphAttributes(MutableAttributeSet current,
                               AttributeSet newAttributes,
                               boolean emitStyleChanges)
    throws IOException
{
    Object parm;
    Object oldStyle, newStyle;

    /* The only way to get rid of tabs or styles is with the \pard keyword,
       emitted by resetParagraphAttributes(). Ideally we should avoid
       emitting \pard if the new paragraph's tabs are a superset of the old
       paragraph's tabs. */

    if (emitStyleChanges) {
        oldStyle = current.getAttribute("paragraphStyle");
        newStyle = findStyleNumber(newAttributes, Constants.STParagraph);
        if (oldStyle != newStyle) {
            if (oldStyle != null) {
                resetParagraphAttributes(current);
                oldStyle = null;
            }
        }
    } else {
        oldStyle = null;
        newStyle = null;
    }

    Object oldTabs = current.getAttribute(Constants.Tabs);
    Object newTabs = newAttributes.getAttribute(Constants.Tabs);
    if (oldTabs != newTabs) {
        if (oldTabs != null) {
            resetParagraphAttributes(current);
            oldTabs = null;
            oldStyle = null;
        }
    }

    if (oldStyle != newStyle && newStyle != null) {
        writeControlWord("s", ((Integer)newStyle).intValue());
        current.addAttribute("paragraphStyle", newStyle);
    }

    checkControlWords(current, newAttributes,
                      RTFAttributes.attributes, RTFAttribute.D_PARAGRAPH);

    if (oldTabs != newTabs && newTabs != null) {
        TabStop tabs[] = (TabStop[])newTabs;
        int index;
        for(index = 0; index < tabs.length; index ++) {
            TabStop tab = tabs[index];
            switch (tab.getAlignment()) {
              case TabStop.ALIGN_LEFT:
              case TabStop.ALIGN_BAR:
                break;
              case TabStop.ALIGN_RIGHT:
                writeControlWord("tqr");
                break;
              case TabStop.ALIGN_CENTER:
                writeControlWord("tqc");
                break;
              case TabStop.ALIGN_DECIMAL:
                writeControlWord("tqdec");
                break;
            }
            switch (tab.getLeader()) {
              case TabStop.LEAD_NONE:
                break;
              case TabStop.LEAD_DOTS:
                writeControlWord("tldot");
                break;
              case TabStop.LEAD_HYPHENS:
                writeControlWord("tlhyph");
                break;
              case TabStop.LEAD_UNDERLINE:
                writeControlWord("tlul");
                break;
              case TabStop.LEAD_THICKLINE:
                writeControlWord("tlth");
                break;
              case TabStop.LEAD_EQUALS:
                writeControlWord("tleq");
                break;
            }
            int twips = Math.round(20f * tab.getPosition());
            if (tab.getAlignment() == TabStop.ALIGN_BAR) {
                writeControlWord("tb", twips);
            } else {
                writeControlWord("tx", twips);
            }
        }
        current.addAttribute(Constants.Tabs, tabs);
    }
}

public void writeParagraphElement(Element el)
    throws IOException
{
    updateParagraphAttributes(outputAttributes, el.getAttributes(), true);

    int sub_count = el.getElementCount();
    for(int idx = 0; idx < sub_count; idx ++) {
        writeTextElement(el.getElement(idx));
    }

    writeControlWord("par");
    writeLineBreak();  /* makes the raw file more readable */
}

/* debugging. TODO: remove.
private static String tabdump(Object tso)
{
    String buf;
    int i;

    if (tso == null)
        return "[none]";

    TabStop[] ts = (TabStop[])tso;

    buf = "[";
    for(i = 0; i < ts.length; i++) {
        buf = buf + ts[i].toString();
        if ((i+1) < ts.length)
            buf = buf + ",";
    }
    return buf + "]";
}
*/

protected void resetParagraphAttributes(MutableAttributeSet currentAttributes)
    throws IOException
{
    writeControlWord("pard");

    currentAttributes.addAttribute(StyleConstants.Alignment,       Zero);

    int wordIndex;
    int wordCount = RTFAttributes.attributes.length;
    for(wordIndex = 0; wordIndex < wordCount; wordIndex++) {
        RTFAttribute attr = RTFAttributes.attributes[wordIndex];
        if (attr.domain() == RTFAttribute.D_PARAGRAPH)
            attr.setDefault(currentAttributes);
    }

    currentAttributes.removeAttribute("paragraphStyle");
    currentAttributes.removeAttribute(Constants.Tabs);
}

void updateCharacterAttributes(MutableAttributeSet current,
                               AttributeSet newAttributes,
                               boolean updateStyleChanges)
    throws IOException
{
    Object parm;

    if (updateStyleChanges) {
        Object oldStyle = current.getAttribute("characterStyle");
        Object newStyle = findStyleNumber(newAttributes,
                                          Constants.STCharacter);
        if (oldStyle != newStyle) {
            if (oldStyle != null) {
                resetCharacterAttributes(current);
            }
            if (newStyle != null) {
                writeControlWord("cs", ((Integer)newStyle).intValue());
                current.addAttribute("characterStyle", newStyle);
            } else {
                current.removeAttribute("characterStyle");
            }
        }
    }

    if ((parm = attrDiff(current, newAttributes,
                         StyleConstants.FontFamily, null)) != null) {
        Number fontNum = (Number)fontTable.get(parm);
        writeControlWord("f", fontNum.intValue());
    }

    checkNumericControlWord(current, newAttributes,
                            StyleConstants.FontSize, "fs",
                            defaultFontSize, 2f);

    checkControlWords(current, newAttributes,
                      RTFAttributes.attributes, RTFAttribute.D_CHARACTER);

    checkNumericControlWord(current, newAttributes,
                            StyleConstants.LineSpacing, "sl",
                            0, 20f); /* TODO: sl wackiness */

    if ((parm = attrDiff(current, newAttributes,
                         StyleConstants.Background, MagicToken)) != null) {
        int colorNum;
        if (parm == MagicToken)
            colorNum = 0;
        else
            colorNum = ((Number)colorTable.get(parm)).intValue();
        writeControlWord("cb", colorNum);
    }

    if ((parm = attrDiff(current, newAttributes,
                         StyleConstants.Foreground, null)) != null) {
        int colorNum;
        if (parm == MagicToken)
            colorNum = 0;
        else
            colorNum = ((Number)colorTable.get(parm)).intValue();
        writeControlWord("cf", colorNum);
    }
}

protected void resetCharacterAttributes(MutableAttributeSet currentAttributes)
    throws IOException
{
    writeControlWord("plain");

    int wordIndex;
    int wordCount = RTFAttributes.attributes.length;
    for(wordIndex = 0; wordIndex < wordCount; wordIndex++) {
        RTFAttribute attr = RTFAttributes.attributes[wordIndex];
        if (attr.domain() == RTFAttribute.D_CHARACTER)
            attr.setDefault(currentAttributes);
    }

    StyleConstants.setFontFamily(currentAttributes, defaultFontFamily);
    currentAttributes.removeAttribute(StyleConstants.FontSize); /* =default */
    currentAttributes.removeAttribute(StyleConstants.Background);
    currentAttributes.removeAttribute(StyleConstants.Foreground);
    currentAttributes.removeAttribute(StyleConstants.LineSpacing);
    currentAttributes.removeAttribute("characterStyle");
}

public void writeTextElement(Element el)
    throws IOException
{
    updateCharacterAttributes(outputAttributes, el.getAttributes(), true);

    if (el.isLeaf()) {
        try {
            el.getDocument().getText(el.getStartOffset(),
                                     el.getEndOffset() - el.getStartOffset(),
                                     this.workingSegment);
        } catch (BadLocationException ble) {
            /* TODO is this the correct error to raise? */
            ble.printStackTrace();
            throw new InternalError(ble.getMessage());
        }
        writeText(this.workingSegment);
    } else {
        int sub_count = el.getElementCount();
        for(int idx = 0; idx < sub_count; idx ++)
            writeTextElement(el.getElement(idx));
    }
}

public void writeText(Segment s)
    throws IOException
{
    int pos, end;
    char[] array;

    pos = s.offset;
    end = pos + s.count;
    array = s.array;
    for( ; pos < end; pos ++)
        writeCharacter(array[pos]);
}

public void writeText(String s)
    throws IOException
{
    int pos, end;

    pos = 0;
    end = s.length();
    for( ; pos < end; pos ++)
        writeCharacter(s.charAt(pos));
}

public void writeRawString(String str)
    throws IOException
{
    int strlen = str.length();
    for (int offset = 0; offset < strlen; offset ++)
        outputStream.write((int)str.charAt(offset));
}

public void writeControlWord(String keyword)
    throws IOException
{
    outputStream.write('\\');
    writeRawString(keyword);
    afterKeyword = true;
}

public void writeControlWord(String keyword, int arg)
    throws IOException
{
    outputStream.write('\\');
    writeRawString(keyword);
    writeRawString(String.valueOf(arg)); /* TODO: correct in all cases? */
    afterKeyword = true;
}

public void writeBegingroup()
    throws IOException
{
    outputStream.write('{');
    afterKeyword = false;
}

public void writeEndgroup()
    throws IOException
{
    outputStream.write('}');
    afterKeyword = false;
}

public void writeCharacter(char ch)
    throws IOException
{
    /* Nonbreaking space is in most RTF encodings, but the keyword is
       preferable; same goes for tabs */
    if (ch == 0xA0) { /* nonbreaking space */
        outputStream.write(0x5C);  /* backslash */
        outputStream.write(0x7E);  /* tilde */
        afterKeyword = false; /* non-alpha keywords are self-terminating */
        return;
    }

    if (ch == 0x09) { /* horizontal tab */
        writeControlWord("tab");
        return;
    }

    if (ch == 10 || ch == 13) { /* newline / paragraph */
        /* ignore CRs, we'll write a paragraph element soon enough */
        return;
    }

    int b = convertCharacter(outputConversion, ch);
    if (b == 0) {
        /* Unicode characters which have corresponding RTF keywords */
        int i;
        for(i = 0; i < textKeywords.length; i++) {
            if (textKeywords[i].character == ch) {
                writeControlWord(textKeywords[i].keyword);
                return;
            }
        }
        /* In some cases it would be reasonable to check to see if the
           glyph being written out is in the Symbol encoding, and if so,
           to switch to the Symbol font for this character. TODO. */
        /* Currently all unrepresentable characters are written as
           Unicode escapes. */
        String approximation = approximationForUnicode(ch);
        if (approximation.length() != unicodeCount) {
            unicodeCount = approximation.length();
            writeControlWord("uc", unicodeCount);
        }
        writeControlWord("u", (int)ch);
        writeRawString(" ");
        writeRawString(approximation);
        afterKeyword = false;
        return;
    }

    if (b > 127) {
        int nybble;
        outputStream.write('\\');
        outputStream.write('\'');
        nybble = ( b & 0xF0 ) >>> 4;
        outputStream.write(hexdigits[nybble]);
        nybble = ( b & 0x0F );
        outputStream.write(hexdigits[nybble]);
        afterKeyword = false;
        return;
    }

    switch (b) {
    case '}':
    case '{':
    case '\\':
        outputStream.write(0x5C);  /* backslash */
        afterKeyword = false;  /* in a keyword, actually ... */
        /* fall through */
    default:
        if (afterKeyword) {
            outputStream.write(0x20);  /* space */
            afterKeyword = false;
        }
        outputStream.write(b);
        break;
    }
}

String approximationForUnicode(char ch)
{
    /* TODO: Find reasonable approximations for all Unicode characters
       in all RTF code pages... heh, heh... */
    return "?";
}

/** Takes a translation table (a 256-element array of characters)
 * and creates an output conversion table for use by
 * convertCharacter(). */
    /* Not very efficient at all. Could be changed to sort the table
       for binary search. TODO. (Even though this is inefficient however,
       writing RTF is still much faster than reading it.) */
static int[] outputConversionFromTranslationTable(char[] table)
{
    int[] conversion = new int[2 * table.length];

    int index;

    for(index = 0; index < table.length; index ++) {
        conversion[index * 2] = table[index];
        conversion[(index * 2) + 1] = index;
    }

    return conversion;
}

static int[] outputConversionForName(String name)
    throws IOException
{
    char[] table = (char[])RTFReader.getCharacterSet(name);
    return outputConversionFromTranslationTable(table);
}

/** Takes a char and a conversion table (an int[] in the current
 * implementation, but conversion tables should be treated as an opaque
 * type) and returns the
 * corresponding byte value (as an int, since bytes are signed).
 */
    /* Not very efficient. TODO. */
static protected int convertCharacter(int[] conversion, char ch)
{
   int index;

   for(index = 0; index < conversion.length; index += 2) {
       if(conversion[index] == ch)
           return conversion[index + 1];
   }

   return 0;  /* 0 indicates an unrepresentable character */
}

}
