| /* | |
| * 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 "wine/debug.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(richedit); | |
| 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); */ | |
| } |