< prev index next >

src/java.desktop/share/classes/javax/swing/text/rtf/RTFReader.java

Print this page




  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package javax.swing.text.rtf;
  26 
  27 import java.lang.*;
  28 import java.util.*;
  29 import java.io.*;
  30 import java.awt.Color;
  31 import java.security.AccessController;
  32 import java.security.PrivilegedAction;
  33 import javax.swing.text.*;
  34 
  35 /**
  36  * Takes a sequence of RTF tokens and text and appends the text
  37  * described by the RTF to a <code>StyledDocument</code> (the <em>target</em>).
  38  * The RTF is lexed
  39  * from the character stream by the <code>RTFParser</code> which is this class's
  40  * superclass.
  41  *
  42  * This class is an indirect subclass of OutputStream. It must be closed
  43  * in order to guarantee that all of the text has been sent to
  44  * the text acceptor.
  45  *
  46  *   @see RTFParser
  47  *   @see java.io.OutputStream
  48  */
  49 class RTFReader extends RTFParser
  50 {
  51   /** The object to which the parsed text is sent. */
  52   StyledDocument target;
  53 
  54   /** Miscellaneous information about the parser's state. This
  55    *  dictionary is saved and restored when an RTF group begins
  56    *  or ends. */
  57   Dictionary<Object, Object> parserState;   /* Current parser state */
  58   /** This is the "dst" item from parserState. rtfDestination
  59    *  is the current rtf destination. It is cached in an instance
  60    *  variable for speed. */
  61   Destination rtfDestination;
  62   /** This holds the current document attributes. */
  63   MutableAttributeSet documentAttributes;
  64 
  65   /** This Dictionary maps Integer font numbers to String font names. */
  66   Dictionary<Integer, String> fontTable;
  67   /** This array maps color indices to Color objects. */
  68   Color[] colorTable;
  69   /** This array maps character style numbers to Style objects. */
  70   Style[] characterStyles;
  71   /** This array maps paragraph style numbers to Style objects. */
  72   Style[] paragraphStyles;
  73   /** This array maps section style numbers to Style objects. */
  74   Style[] sectionStyles;
  75 
  76   /** This is the RTF version number, extracted from the \rtf keyword.
  77    *  The version information is currently not used. */
  78   int rtfversion;
  79 
  80   /** <code>true</code> to indicate that if the next keyword is unknown,
  81    *  the containing group should be ignored. */
  82   boolean ignoreGroupIfUnknownKeyword;
  83 
  84   /** The parameter of the most recently parsed \\ucN keyword,
  85    *  used for skipping alternative representations after a
  86    *  Unicode character. */
  87   int skippingCharacters;
  88 
  89   private static Dictionary<String, RTFAttribute> straightforwardAttributes;
  90   static {
  91       straightforwardAttributes = RTFAttributes.attributesByKeyword();
  92   }
  93 
  94   private MockAttributeSet mockery;
  95 
  96   /* this should be final, but there's a bug in javac... */
  97   /** textKeywords maps RTF keywords to single-character strings,
  98    *  for those keywords which simply insert some text. */
  99   static Dictionary<String, String> textKeywords = null;
 100   static {


 187             text = text.substring(skippingCharacters);
 188             skippingCharacters = 0;
 189         }
 190     }
 191 
 192     if (rtfDestination != null) {
 193         rtfDestination.handleText(text);
 194         return;
 195     }
 196 
 197     warning("Text with no destination. oops.");
 198 }
 199 
 200 /** The default color for text which has no specified color. */
 201 Color defaultColor()
 202 {
 203     return Color.black;
 204 }
 205 
 206 /** Called by the superclass when a new RTF group is begun.
 207  *  This implementation saves the current <code>parserState</code>, and gives
 208  *  the current destination a chance to save its own state.
 209  * @see RTFParser#begingroup
 210  */
 211 public void begingroup()
 212 {
 213     if (skippingCharacters > 0) {
 214         /* TODO this indicates an error in the RTF. Log it? */
 215         skippingCharacters = 0;
 216     }
 217 
 218     /* we do this little dance to avoid cloning the entire state stack and
 219        immediately throwing it away. */
 220     Object oldSaveState = parserState.get("_savedState");
 221     if (oldSaveState != null)
 222         parserState.remove("_savedState");
 223     @SuppressWarnings("unchecked")
 224     Dictionary<String, Object> saveState = (Dictionary<String, Object>)((Hashtable)parserState).clone();
 225     if (oldSaveState != null)
 226         saveState.put("_savedState", oldSaveState);
 227     parserState.put("_savedState", saveState);
 228 
 229     if (rtfDestination != null)
 230         rtfDestination.begingroup();
 231 }
 232 
 233 /** Called by the superclass when the current RTF group is closed.
 234  *  This restores the parserState saved by <code>begingroup()</code>
 235  *  as well as invoking the endgroup method of the current
 236  *  destination.
 237  * @see RTFParser#endgroup
 238  */
 239 public void endgroup()
 240 {
 241     if (skippingCharacters > 0) {
 242         /* NB this indicates an error in the RTF. Log it? */
 243         skippingCharacters = 0;
 244     }
 245 
 246     @SuppressWarnings("unchecked")
 247     Dictionary<Object, Object> restoredState = (Dictionary<Object, Object>)parserState.get("_savedState");
 248     Destination restoredDestination = (Destination)restoredState.get("dst");
 249     if (restoredDestination != rtfDestination) {
 250         rtfDestination.close(); /* allow the destination to clean up */
 251         rtfDestination = restoredDestination;
 252     }
 253     Dictionary<Object, Object> oldParserState = parserState;
 254     parserState = restoredState;


1516                 attr.setDefault(characterAttributes);
1517         }
1518 
1519         parserState.remove("sectionStyle");
1520     }
1521 }
1522 
1523 /** RTFReader.TextHandlingDestination provides basic text handling
1524  *  functionality. Subclasses must implement: <dl>
1525  *  <dt>deliverText()<dd>to handle a run of text with the same
1526  *                       attributes
1527  *  <dt>finishParagraph()<dd>to end the current paragraph and
1528  *                           set the paragraph's attributes
1529  *  <dt>endSection()<dd>to end the current section
1530  *  </dl>
1531  */
1532 abstract class TextHandlingDestination
1533     extends AttributeTrackingDestination
1534     implements Destination
1535 {
1536     /** <code>true</code> if the reader has not just finished
1537      *  a paragraph; false upon startup */
1538     boolean inParagraph;
1539 
1540     public TextHandlingDestination()
1541     {
1542         super();
1543         inParagraph = false;
1544     }
1545 
1546     public void handleText(String text)
1547     {
1548         if (! inParagraph)
1549             beginParagraph();
1550 
1551         deliverText(text, currentTextAttributes());
1552     }
1553 
1554     abstract void deliverText(String text, AttributeSet characterAttributes);
1555 
1556     public void close()


1585     protected void beginParagraph()
1586     {
1587         inParagraph = true;
1588     }
1589 
1590     protected void endParagraph()
1591     {
1592         AttributeSet pgfAttributes = currentParagraphAttributes();
1593         AttributeSet chrAttributes = currentTextAttributes();
1594         finishParagraph(pgfAttributes, chrAttributes);
1595         inParagraph = false;
1596     }
1597 
1598     abstract void finishParagraph(AttributeSet pgfA, AttributeSet chrA);
1599 
1600     abstract void endSection();
1601 }
1602 
1603 /** RTFReader.DocumentDestination is a concrete subclass of
1604  *  TextHandlingDestination which appends the text to the
1605  *  StyledDocument given by the <code>target</code> ivar of the
1606  *  containing RTFReader.
1607  */
1608 class DocumentDestination
1609     extends TextHandlingDestination
1610     implements Destination
1611 {
1612     public void deliverText(String text, AttributeSet characterAttributes)
1613     {
1614         try {
1615             target.insertString(target.getLength(),
1616                                 text,
1617                                 currentTextAttributes());
1618         } catch (BadLocationException ble) {
1619             /* This shouldn't be able to happen, of course */
1620             /* TODO is InternalError the correct error to throw? */
1621             throw new InternalError(ble.getMessage(), ble);
1622         }
1623     }
1624 
1625     public void finishParagraph(AttributeSet pgfAttributes,


  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package javax.swing.text.rtf;
  26 
  27 import java.lang.*;
  28 import java.util.*;
  29 import java.io.*;
  30 import java.awt.Color;
  31 import java.security.AccessController;
  32 import java.security.PrivilegedAction;
  33 import javax.swing.text.*;
  34 
  35 /**
  36  * Takes a sequence of RTF tokens and text and appends the text
  37  * described by the RTF to a {@code StyledDocument} (the <em>target</em>).
  38  * The RTF is lexed
  39  * from the character stream by the {@code RTFParser} which is this class's
  40  * superclass.
  41  *
  42  * This class is an indirect subclass of OutputStream. It must be closed
  43  * in order to guarantee that all of the text has been sent to
  44  * the text acceptor.
  45  *
  46  *   @see RTFParser
  47  *   @see java.io.OutputStream
  48  */
  49 class RTFReader extends RTFParser
  50 {
  51   /** The object to which the parsed text is sent. */
  52   StyledDocument target;
  53 
  54   /** Miscellaneous information about the parser's state. This
  55    *  dictionary is saved and restored when an RTF group begins
  56    *  or ends. */
  57   Dictionary<Object, Object> parserState;   /* Current parser state */
  58   /** This is the "dst" item from parserState. rtfDestination
  59    *  is the current rtf destination. It is cached in an instance
  60    *  variable for speed. */
  61   Destination rtfDestination;
  62   /** This holds the current document attributes. */
  63   MutableAttributeSet documentAttributes;
  64 
  65   /** This Dictionary maps Integer font numbers to String font names. */
  66   Dictionary<Integer, String> fontTable;
  67   /** This array maps color indices to Color objects. */
  68   Color[] colorTable;
  69   /** This array maps character style numbers to Style objects. */
  70   Style[] characterStyles;
  71   /** This array maps paragraph style numbers to Style objects. */
  72   Style[] paragraphStyles;
  73   /** This array maps section style numbers to Style objects. */
  74   Style[] sectionStyles;
  75 
  76   /** This is the RTF version number, extracted from the \rtf keyword.
  77    *  The version information is currently not used. */
  78   int rtfversion;
  79 
  80   /** {@code true} to indicate that if the next keyword is unknown,
  81    *  the containing group should be ignored. */
  82   boolean ignoreGroupIfUnknownKeyword;
  83 
  84   /** The parameter of the most recently parsed \\ucN keyword,
  85    *  used for skipping alternative representations after a
  86    *  Unicode character. */
  87   int skippingCharacters;
  88 
  89   private static Dictionary<String, RTFAttribute> straightforwardAttributes;
  90   static {
  91       straightforwardAttributes = RTFAttributes.attributesByKeyword();
  92   }
  93 
  94   private MockAttributeSet mockery;
  95 
  96   /* this should be final, but there's a bug in javac... */
  97   /** textKeywords maps RTF keywords to single-character strings,
  98    *  for those keywords which simply insert some text. */
  99   static Dictionary<String, String> textKeywords = null;
 100   static {


 187             text = text.substring(skippingCharacters);
 188             skippingCharacters = 0;
 189         }
 190     }
 191 
 192     if (rtfDestination != null) {
 193         rtfDestination.handleText(text);
 194         return;
 195     }
 196 
 197     warning("Text with no destination. oops.");
 198 }
 199 
 200 /** The default color for text which has no specified color. */
 201 Color defaultColor()
 202 {
 203     return Color.black;
 204 }
 205 
 206 /** Called by the superclass when a new RTF group is begun.
 207  *  This implementation saves the current {@code parserState}, and gives
 208  *  the current destination a chance to save its own state.
 209  * @see RTFParser#begingroup
 210  */
 211 public void begingroup()
 212 {
 213     if (skippingCharacters > 0) {
 214         /* TODO this indicates an error in the RTF. Log it? */
 215         skippingCharacters = 0;
 216     }
 217 
 218     /* we do this little dance to avoid cloning the entire state stack and
 219        immediately throwing it away. */
 220     Object oldSaveState = parserState.get("_savedState");
 221     if (oldSaveState != null)
 222         parserState.remove("_savedState");
 223     @SuppressWarnings("unchecked")
 224     Dictionary<String, Object> saveState = (Dictionary<String, Object>)((Hashtable)parserState).clone();
 225     if (oldSaveState != null)
 226         saveState.put("_savedState", oldSaveState);
 227     parserState.put("_savedState", saveState);
 228 
 229     if (rtfDestination != null)
 230         rtfDestination.begingroup();
 231 }
 232 
 233 /** Called by the superclass when the current RTF group is closed.
 234  *  This restores the parserState saved by {@code begingroup()}
 235  *  as well as invoking the endgroup method of the current
 236  *  destination.
 237  * @see RTFParser#endgroup
 238  */
 239 public void endgroup()
 240 {
 241     if (skippingCharacters > 0) {
 242         /* NB this indicates an error in the RTF. Log it? */
 243         skippingCharacters = 0;
 244     }
 245 
 246     @SuppressWarnings("unchecked")
 247     Dictionary<Object, Object> restoredState = (Dictionary<Object, Object>)parserState.get("_savedState");
 248     Destination restoredDestination = (Destination)restoredState.get("dst");
 249     if (restoredDestination != rtfDestination) {
 250         rtfDestination.close(); /* allow the destination to clean up */
 251         rtfDestination = restoredDestination;
 252     }
 253     Dictionary<Object, Object> oldParserState = parserState;
 254     parserState = restoredState;


1516                 attr.setDefault(characterAttributes);
1517         }
1518 
1519         parserState.remove("sectionStyle");
1520     }
1521 }
1522 
1523 /** RTFReader.TextHandlingDestination provides basic text handling
1524  *  functionality. Subclasses must implement: <dl>
1525  *  <dt>deliverText()<dd>to handle a run of text with the same
1526  *                       attributes
1527  *  <dt>finishParagraph()<dd>to end the current paragraph and
1528  *                           set the paragraph's attributes
1529  *  <dt>endSection()<dd>to end the current section
1530  *  </dl>
1531  */
1532 abstract class TextHandlingDestination
1533     extends AttributeTrackingDestination
1534     implements Destination
1535 {
1536     /** {@code true} if the reader has not just finished
1537      *  a paragraph; false upon startup */
1538     boolean inParagraph;
1539 
1540     public TextHandlingDestination()
1541     {
1542         super();
1543         inParagraph = false;
1544     }
1545 
1546     public void handleText(String text)
1547     {
1548         if (! inParagraph)
1549             beginParagraph();
1550 
1551         deliverText(text, currentTextAttributes());
1552     }
1553 
1554     abstract void deliverText(String text, AttributeSet characterAttributes);
1555 
1556     public void close()


1585     protected void beginParagraph()
1586     {
1587         inParagraph = true;
1588     }
1589 
1590     protected void endParagraph()
1591     {
1592         AttributeSet pgfAttributes = currentParagraphAttributes();
1593         AttributeSet chrAttributes = currentTextAttributes();
1594         finishParagraph(pgfAttributes, chrAttributes);
1595         inParagraph = false;
1596     }
1597 
1598     abstract void finishParagraph(AttributeSet pgfA, AttributeSet chrA);
1599 
1600     abstract void endSection();
1601 }
1602 
1603 /** RTFReader.DocumentDestination is a concrete subclass of
1604  *  TextHandlingDestination which appends the text to the
1605  *  StyledDocument given by the {@code target} ivar of the
1606  *  containing RTFReader.
1607  */
1608 class DocumentDestination
1609     extends TextHandlingDestination
1610     implements Destination
1611 {
1612     public void deliverText(String text, AttributeSet characterAttributes)
1613     {
1614         try {
1615             target.insertString(target.getLength(),
1616                                 text,
1617                                 currentTextAttributes());
1618         } catch (BadLocationException ble) {
1619             /* This shouldn't be able to happen, of course */
1620             /* TODO is InternalError the correct error to throw? */
1621             throw new InternalError(ble.getMessage(), ble);
1622         }
1623     }
1624 
1625     public void finishParagraph(AttributeSet pgfAttributes,
< prev index next >