Added some tests for win-format metafiles.
[wine/dcerpc.git] / dlls / richedit / text-writer.c
blobc050202746000c60a8cc387c9ef8f95e3d0630f8
1 /*
2 * text-writer -- RTF-to-text translation writer code.
4 * Read RTF input, write text of document (text extraction).
6 * Wrapper must call WriterInit() once before processing any files,
7 * then set up input and call BeginFile() for each input file.
9 * This installs callbacks for the text and control token classes.
10 * The control class is necessary so that special characters such as
11 * \par, \tab, \sect, etc. can be converted.
13 * It's problematic what to do with text in headers and footers, and
14 * what to do about tables.
16 * This really is quite a stupid program, for instance, it could keep
17 * track of the current leader character and dump that out when a tab
18 * is encountered.
20 * 04 Feb 91 Paul DuBois dubois@primate.wisc.edu
22 * This software may be redistributed without restriction and used for
23 * any purpose whatsoever.
25 * 04 Feb 91
26 * -Created.
27 * 27 Feb 91
28 * - Updated for distribution 1.05.
29 * 13 Jul 93
30 * - Updated to compile under THINK C 6.0.
31 * 31 Aug 93
32 * - Added Mike Sendall's entries for Macintosh char map.
33 * 07 Sep 93
34 * - Uses charset map and output sequence map for character translation.
35 * 11 Mar 94
36 * - Updated for 1.10 distribution.
39 #include <stdio.h>
41 #include "rtf.h"
42 #include "rtf2text.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(richedit);
47 static void TextClass (RTF_Info *info);
48 static void ControlClass (RTF_Info *info);
49 static void Destination (RTF_Info *info);
50 static void SpecialChar (RTF_Info *info);
51 static void PutStdChar (RTF_Info *info, int stdCode);
52 static void PutLitChar (RTF_Info *info, int c);
53 static void PutLitStr (RTF_Info *info, char *s);
56 * Initialize the writer.
59 void
60 WriterInit (RTF_Info *info )
62 RTFReadOutputMap (info, info->outMap,1);
66 int
67 BeginFile (RTF_Info *info )
69 /* install class callbacks */
71 RTFSetClassCallback (info, rtfText, TextClass);
72 RTFSetClassCallback (info, rtfControl, ControlClass);
74 return (1);
79 * Write out a character. rtfMajor contains the input character, rtfMinor
80 * contains the corresponding standard character code.
82 * If the input character isn't in the charset map, try to print some
83 * representation of it.
86 static void
87 TextClass (RTF_Info *info)
89 char buf[rtfBufSiz];
91 TRACE("\n");
93 if (info->rtfFormat == SF_TEXT)
94 PutLitChar (info, info->rtfMajor);
95 else if (info->rtfMinor != rtfSC_nothing)
96 PutStdChar (info, info->rtfMinor);
97 else
99 if (info->rtfMajor < 128) /* in ASCII range */
100 sprintf (buf, "[[%c]]", info->rtfMajor);
101 else
102 sprintf (buf, "[[\\'%02x]]", info->rtfMajor);
103 PutLitStr (info, buf);
108 static void
109 ControlClass (RTF_Info *info)
111 TRACE("\n");
112 switch (info->rtfMajor)
114 case rtfDestination:
115 Destination (info);
116 break;
117 case rtfSpecialChar:
118 SpecialChar (info);
119 break;
125 * This function notices destinations that should be ignored
126 * and skips to their ends. This keeps, for instance, picture
127 * data from being considered as plain text.
130 static void
131 Destination (RTF_Info *info)
134 TRACE("\n");
136 switch (info->rtfMinor)
138 case rtfPict:
139 case rtfFNContSep:
140 case rtfFNContNotice:
141 case rtfInfo:
142 case rtfIndexRange:
143 case rtfITitle:
144 case rtfISubject:
145 case rtfIAuthor:
146 case rtfIOperator:
147 case rtfIKeywords:
148 case rtfIComment:
149 case rtfIVersion:
150 case rtfIDoccomm:
151 RTFSkipGroup (info);
152 break;
158 * The reason these use the rtfSC_xxx thingies instead of just writing
159 * out ' ', '-', '"', etc., is so that the mapping for these characters
160 * can be controlled by the text-map file.
163 void SpecialChar (RTF_Info *info)
166 TRACE("\n");
168 switch (info->rtfMinor)
170 case rtfPage:
171 case rtfSect:
172 case rtfRow:
173 case rtfLine:
174 case rtfPar:
175 PutLitChar (info, '\n');
176 break;
177 case rtfCell:
178 PutStdChar (info, rtfSC_space); /* make sure cells are separated */
179 break;
180 case rtfNoBrkSpace:
181 PutStdChar (info, rtfSC_nobrkspace);
182 break;
183 case rtfTab:
184 PutLitChar (info, '\t');
185 break;
186 case rtfNoBrkHyphen:
187 PutStdChar (info, rtfSC_nobrkhyphen);
188 break;
189 case rtfBullet:
190 PutStdChar (info, rtfSC_bullet);
191 break;
192 case rtfEmDash:
193 PutStdChar (info, rtfSC_emdash);
194 break;
195 case rtfEnDash:
196 PutStdChar (info, rtfSC_endash);
197 break;
198 case rtfLQuote:
199 PutStdChar (info, rtfSC_quoteleft);
200 break;
201 case rtfRQuote:
202 PutStdChar (info, rtfSC_quoteright);
203 break;
204 case rtfLDblQuote:
205 PutStdChar (info, rtfSC_quotedblleft);
206 break;
207 case rtfRDblQuote:
208 PutStdChar (info, rtfSC_quotedblright);
209 break;
215 * Eventually this should keep track of the destination of the
216 * current state and only write text when in the initial state.
218 * If the output sequence is unspecified in the output map, write
219 * the character's standard name instead. This makes map deficiencies
220 * obvious and provides incentive to fix it. :-)
223 void PutStdChar (RTF_Info *info, int stdCode)
226 char *oStr = (char *) NULL;
227 char buf[rtfBufSiz];
229 /* if (stdCode == rtfSC_nothing)
230 RTFPanic ("Unknown character code, logic error\n");
232 TRACE("\n");
234 oStr = info->outMap[stdCode];
235 if (oStr == (char *) NULL) /* no output sequence in map */
237 sprintf (buf, "[[%s]]", RTFStdCharName (info, stdCode));
238 oStr = buf;
240 PutLitStr (info, oStr);
243 void PutLitChar (RTF_Info *info, int c)
245 if( info->dwOutputCount >= ( sizeof info->OutputBuffer - 1 ) )
246 RTFFlushOutputBuffer( info );
247 info->OutputBuffer[info->dwOutputCount++] = c;
250 void RTFFlushOutputBuffer( RTF_Info *info )
252 info->OutputBuffer[info->dwOutputCount] = 0;
253 SendMessageA( info->hwndEdit, EM_REPLACESEL, FALSE, (LPARAM) info->OutputBuffer );
254 info->dwOutputCount = 0;
257 static void PutLitStr (RTF_Info *info, char *str )
259 int len = strlen( str );
260 if( ( len + info->dwOutputCount + 1 ) > sizeof info->OutputBuffer )
261 RTFFlushOutputBuffer( info );
262 if( ( len + 1 ) >= sizeof info->OutputBuffer )
264 SendMessageA( info->hwndEdit, EM_REPLACESEL, FALSE, (LPARAM) str );
265 return;
267 strcpy( &info->OutputBuffer[info->dwOutputCount], str );
268 info->dwOutputCount += len;