| /* |
| * 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); */ |
| } |