--- /dev/null
+/*
+ * text-writer -- RTF-to-text translation writer code.
+ *
+ * Read RTF input, write text of document (text extraction).
+ *
+ * Wrapper must call WriterInit() once before processing any files,
+ * then set up input and call BeginFile() for each input file.
+ *
+ * This installs callbacks for the text and control token classes.
+ * The control class is necessary so that special characters such as
+ * \par, \tab, \sect, etc. can be converted.
+ *
+ * It's problematic what to do with text in headers and footers, and
+ * what to do about tables.
+ *
+ * This really is quite a stupid program, for instance, it could keep
+ * track of the current leader character and dump that out when a tab
+ * is encountered.
+ *
+ * 04 Feb 91 Paul DuBois dubois@primate.wisc.edu
+ *
+ * This software may be redistributed without restriction and used for
+ * any purpose whatsoever.
+ *
+ * 04 Feb 91
+ * -Created.
+ * 27 Feb 91
+ * - Updated for distribution 1.05.
+ * 13 Jul 93
+ * - Updated to compile under THINK C 6.0.
+ * 31 Aug 93
+ * - Added Mike Sendall's entries for Macintosh char map.
+ * 07 Sep 93
+ * - Uses charset map and output sequence map for character translation.
+ * 11 Mar 94
+ * - Updated for 1.10 distribution.
+ */
+
+#include <stdio.h>
+
+#include "rtf.h"
+#include "rtf2text.h"
+#include "charlist.h"
+#include "debug.h"
+
+#if 0
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(richedit);
+#else
+ #define TRACE DPRINT
+ #define WARN DPRINT
+ #define FIXME DPRINT
+#endif
+
+static void TextClass ();
+static void ControlClass ();
+static void Destination ();
+static void SpecialChar ();
+static void PutStdChar ();
+static void PutLitChar ();
+static void PutLitStr ();
+
+static char *outMap[rtfSC_MaxChar];
+
+static CHARLIST charlist = {0, NULL, NULL};
+
+int RTFToBuffer(char* pBuffer, int nBufferSize);
+int RTFToBuffer(char* pBuffer, int nBufferSize)
+{
+
+ /* check if the buffer is big enough to hold all characters */
+ /* we require one more for the '\0' */
+
+ TRACE("\n");
+
+ if(nBufferSize < charlist.nCount + 1) {
+ return charlist.nCount + CHARLIST_CountChar(&charlist, '\n') + 1;
+ }
+
+ while(charlist.nCount)
+ {
+ *pBuffer = CHARLIST_Dequeue(&charlist);
+ if(*pBuffer=='\n')
+ {
+ *pBuffer = '\r';
+ pBuffer++;
+ *pBuffer = '\n';
+ }
+ pBuffer++;
+ }
+ *pBuffer = '\0';
+
+ return 0;
+}
+
+
+/*
+ * Initialize the writer.
+ */
+
+void
+WriterInit ()
+{
+ RTFReadOutputMap (outMap,1);
+}
+
+
+int
+BeginFile ()
+{
+ /* install class callbacks */
+
+ RTFSetClassCallback (rtfText, TextClass);
+ RTFSetClassCallback (rtfControl, ControlClass);
+
+ return (1);
+}
+
+
+/*
+ * Write out a character. rtfMajor contains the input character, rtfMinor
+ * contains the corresponding standard character code.
+ *
+ * If the input character isn't in the charset map, try to print some
+ * representation of it.
+ */
+
+static void
+TextClass ()
+{
+char buf[rtfBufSiz];
+
+ TRACE("\n");
+
+ if (rtfFormat == SF_TEXT)
+ PutLitChar (rtfMajor);
+ else if (rtfMinor != rtfSC_nothing)
+ PutStdChar (rtfMinor);
+ else
+ {
+ if (rtfMajor < 128) /* in ASCII range */
+ sprintf (buf, "[[%c]]", rtfMajor);
+ else
+ sprintf (buf, "[[\\'%02x]]", rtfMajor);
+ PutLitStr (buf);
+ }
+}
+
+
+static void
+ControlClass ()
+{
+ TRACE("\n");
+ switch (rtfMajor)
+ {
+ case rtfDestination:
+ Destination ();
+ break;
+ case rtfSpecialChar:
+ SpecialChar ();
+ break;
+ }
+}
+
+
+/*
+ * This function notices destinations that should be ignored
+ * and skips to their ends. This keeps, for instance, picture
+ * data from being considered as plain text.
+ */
+
+static void
+Destination ()
+{
+
+ TRACE("\n");
+
+ switch (rtfMinor)
+ {
+ case rtfPict:
+ case rtfFNContSep:
+ case rtfFNContNotice:
+ case rtfInfo:
+ case rtfIndexRange:
+ case rtfITitle:
+ case rtfISubject:
+ case rtfIAuthor:
+ case rtfIOperator:
+ case rtfIKeywords:
+ case rtfIComment:
+ case rtfIVersion:
+ case rtfIDoccomm:
+ RTFSkipGroup ();
+ break;
+ }
+}
+
+
+/*
+ * The reason these use the rtfSC_xxx thingies instead of just writing
+ * out ' ', '-', '"', etc., is so that the mapping for these characters
+ * can be controlled by the text-map file.
+ */
+
+void SpecialChar ()
+{
+
+ TRACE("\n");
+
+ switch (rtfMinor)
+ {
+ case rtfPage:
+ case rtfSect:
+ case rtfRow:
+ case rtfLine:
+ case rtfPar:
+ PutLitChar ('\n');
+ break;
+ case rtfCell:
+ PutStdChar (rtfSC_space); /* make sure cells are separated */
+ break;
+ case rtfNoBrkSpace:
+ PutStdChar (rtfSC_nobrkspace);
+ break;
+ case rtfTab:
+ PutLitChar ('\t');
+ break;
+ case rtfNoBrkHyphen:
+ PutStdChar (rtfSC_nobrkhyphen);
+ break;
+ case rtfBullet:
+ PutStdChar (rtfSC_bullet);
+ break;
+ case rtfEmDash:
+ PutStdChar (rtfSC_emdash);
+ break;
+ case rtfEnDash:
+ PutStdChar (rtfSC_endash);
+ break;
+ case rtfLQuote:
+ PutStdChar (rtfSC_quoteleft);
+ break;
+ case rtfRQuote:
+ PutStdChar (rtfSC_quoteright);
+ break;
+ case rtfLDblQuote:
+ PutStdChar (rtfSC_quotedblleft);
+ break;
+ case rtfRDblQuote:
+ PutStdChar (rtfSC_quotedblright);
+ break;
+ }
+}
+
+
+/*
+ * Eventually this should keep track of the destination of the
+ * current state and only write text when in the initial state.
+ *
+ * If the output sequence is unspecified in the output map, write
+ * the character's standard name instead. This makes map deficiencies
+ * obvious and provides incentive to fix it. :-)
+ */
+
+void PutStdChar (int stdCode)
+{
+
+ char *oStr = (char *) NULL;
+ char buf[rtfBufSiz];
+
+/* if (stdCode == rtfSC_nothing)
+ RTFPanic ("Unknown character code, logic error\n");
+*/
+ TRACE("\n");
+
+ oStr = outMap[stdCode];
+ if (oStr == (char *) NULL) /* no output sequence in map */
+ {
+ sprintf (buf, "[[%s]]", RTFStdCharName (stdCode));
+ oStr = buf;
+ }
+ PutLitStr (oStr);
+}
+
+
+void PutLitChar (int c)
+{
+ CHARLIST_Enqueue(&charlist, (char) c);
+ /* fputc (c, ostream); */
+}
+
+
+static void PutLitStr (char *s)
+{
+ for(;*s;s++)
+ {
+ CHARLIST_Enqueue(&charlist, *s);
+ }
+ /* fputs (s, ostream); */
+}