1 /************************************************************************/
2 /* */
3 /* Save a BufferDocument into an RTF file. */
4 /* */
5 /************************************************************************/
6
7 # include "docRtfConfig.h"
8
9 # include <stdlib.h>
10 # include <string.h>
11 # include <stdio.h>
12 # include <ctype.h>
13 # include <textConverter.h>
14 # include <textConverterImpl.h>
15
16 # include <appDebugon.h>
17
18 # include "docRtfWriterImpl.h"
19 # include "docRtfTextConverter.h"
20
21 /************************************************************************/
22
docRtfInitWritingContext(RtfWriter * rw)23 static void docRtfInitWritingContext( RtfWriter * rw )
24 {
25 rw->rwDocument= (BufferDocument *)0;
26
27 utilInitTextAttribute( &(rw->rwTextAttribute) );
28 rw->rwTextCharset= FONTcharsetANSI;
29 docInitParagraphProperties( &(rw->rwcParagraphProperties) );
30 docInitRowProperties( &(rw->rwRowProperties) );
31
32 docInitParagraphProperties( &(rw->rwcOutsideTableParagraphProperties) );
33
34 utilInitPagedList( &(rw->rwcEncodedFontList) );
35 utilStartPagedList( &(rw->rwcEncodedFontList),
36 sizeof(EncodedFont),
37 (InitPagedListItem)docRtfInitEncodedFont,
38 (CleanPagedListItem)0 );
39
40 rw->rwcPushedAttribute= (PushedAttribute *)0;
41
42 rw->rwcInFldrslt= 0;
43 rw->rwTableNesting= 0;
44 rw->rwDeepestTableNesting= 0;
45
46 rw->rwSectionPropertiesSaved= 0;
47
48 rw->rwSaveFlags= 0;
49
50 rw->rwcAfter= RTFafterTEXT;
51 rw->rwcLastNodeLevel= DOClevOUT;
52
53 rw->rwCol= 0;
54 rw->rwSosOut= (SimpleOutputStream *)0;
55
56 rw->rwRtfTextConverter= (TextConverter *)0;
57 rw->rwTextTextConverter= (TextConverter *)0;
58
59 rw->rwPpExtraMask= (const PropertyMask *)0;
60 rw->rwCpExtraMask= (const PropertyMask *)0;
61 rw->rwRpExtraMask= (const PropertyMask *)0;
62 rw->rwSpExtraMask= (const PropertyMask *)0;
63 }
64
docRtfCleanWritingContext(RtfWriter * rw)65 static void docRtfCleanWritingContext( RtfWriter * rw )
66 {
67 docCleanParagraphProperties( &rw->rwcParagraphProperties );
68 docCleanRowProperties( &rw->rwRowProperties );
69
70 docCleanParagraphProperties( &rw->rwcOutsideTableParagraphProperties );
71
72 utilCleanPagedList( &(rw->rwcEncodedFontList) );
73
74 if ( rw->rwRtfTextConverter )
75 {
76 textCleanTextConverter( rw->rwRtfTextConverter );
77 free( rw->rwRtfTextConverter );
78 }
79
80 if ( rw->rwTextTextConverter )
81 {
82 textCleanTextConverter( rw->rwTextTextConverter );
83 free( rw->rwTextTextConverter );
84 }
85 }
86
87 /************************************************************************/
88 /* */
89 /* Reserve a number of columns in the output file. */
90 /* */
91 /************************************************************************/
92
docRtfReserveColumns(RtfWriter * rw,int cols)93 void docRtfReserveColumns( RtfWriter * rw,
94 int cols )
95 {
96 if ( rw->rwCol > 0 && rw->rwCol+ cols > 72 )
97 { docRtfWriteNextLine( rw ); }
98
99 return;
100 }
101
102 /************************************************************************/
103 /* */
104 /* Save a tag with an argument. */
105 /* */
106 /************************************************************************/
107
docRtfWriteNextLine(RtfWriter * rw)108 void docRtfWriteNextLine( RtfWriter * rw )
109 {
110 if ( rw->rwCol > 0 )
111 {
112 sioOutPutString( "\r\n", rw->rwSosOut );
113
114 rw->rwCol= 0;
115 rw->rwcAfter= RTFafterTEXT;
116 }
117
118 return;
119 }
120
docRtfWriteTag(RtfWriter * rw,const char * tag)121 int docRtfWriteTag( RtfWriter * rw,
122 const char * tag )
123 {
124 int len= strlen( tag );
125
126 rw->rwCol += 1+ len;
127
128 if ( rw->rwCol > 72 )
129 {
130 docRtfWriteNextLine( rw );
131 rw->rwCol= len;
132 }
133
134 if ( sioOutPutByte( '\\', rw->rwSosOut ) < 0 )
135 { LDEB(1); return -1; }
136 if ( sioOutPutString( tag, rw->rwSosOut ) < 0 )
137 { LDEB(1); return -1; }
138 rw->rwcAfter= RTFafterTAG;
139
140 return 0;
141 }
142
docRtfWriteDestinationBegin(RtfWriter * rw,const char * tag)143 int docRtfWriteDestinationBegin( RtfWriter * rw,
144 const char * tag )
145 {
146 int len= strlen( tag );
147
148 rw->rwCol += 1+ len;
149
150 if ( rw->rwCol > 72 )
151 {
152 docRtfWriteNextLine( rw );
153 rw->rwCol= 1+ len;
154 }
155
156 if ( sioOutPutByte( '{', rw->rwSosOut ) < 0 )
157 { LDEB(1); return -1; }
158 if ( tag && tag[0] )
159 {
160 if ( sioOutPutByte( '\\', rw->rwSosOut ) < 0 )
161 { LDEB(1); return -1; }
162 rw->rwCol += 1;
163 if ( sioOutPutString( tag, rw->rwSosOut ) < 0 )
164 { LDEB(1); return -1; }
165 rw->rwcAfter= RTFafterTAG;
166 }
167 else{
168 rw->rwcAfter= RTFafterTEXT;
169 }
170
171 return 0;
172 }
173
docRtfWriteArgDestinationBegin(RtfWriter * rw,const char * tag,int arg)174 int docRtfWriteArgDestinationBegin( RtfWriter * rw,
175 const char * tag,
176 int arg )
177 {
178 char scratch[20];
179 int len;
180
181 sprintf( scratch, "%d", arg );
182
183 len= strlen( tag )+ strlen( scratch );
184
185 rw->rwCol += 2+ len;
186
187 if ( rw->rwCol > 72 )
188 {
189 docRtfWriteNextLine( rw );
190 rw->rwCol= 1+ len;
191 }
192
193 if ( sioOutPutByte( '{', rw->rwSosOut ) < 0 )
194 { LDEB(1); return -1; }
195 if ( sioOutPutByte( '\\', rw->rwSosOut ) < 0 )
196 { LDEB(1); return -1; }
197 if ( sioOutPutString( tag, rw->rwSosOut ) < 0 )
198 { LDEB(1); return -1; }
199 if ( sioOutPutString( scratch, rw->rwSosOut ) < 0 )
200 { LDEB(1); return -1; }
201
202 rw->rwcAfter= RTFafterARG;
203
204 return 0;
205 }
206
docRtfWriteDestinationEnd(RtfWriter * rw)207 int docRtfWriteDestinationEnd( RtfWriter * rw )
208 {
209 if ( sioOutPutByte( '}', rw->rwSosOut ) )
210 { LDEB(1); return -1; }
211
212 rw->rwCol += 1;
213 rw->rwcAfter= RTFafterTEXT;
214
215 return 0;
216 }
217
docRtfWriteArgTag(RtfWriter * rw,const char * tag,int arg)218 int docRtfWriteArgTag( RtfWriter * rw,
219 const char * tag,
220 int arg )
221 {
222 char scratch[20];
223 int len;
224
225 sprintf( scratch, "%d", arg );
226
227 len= strlen( tag )+ strlen( scratch );
228
229 rw->rwCol += 1+ len;
230
231 if ( rw->rwCol > 72 )
232 {
233 docRtfWriteNextLine( rw );
234 rw->rwCol= len;
235 }
236
237 if ( sioOutPutByte( '\\', rw->rwSosOut ) < 0 )
238 { LDEB(1); return -1; }
239 if ( sioOutPutString( tag, rw->rwSosOut ) < 0 )
240 { LDEB(1); return -1; }
241 if ( sioOutPutString( scratch, rw->rwSosOut ) < 0 )
242 { LDEB(1); return -1; }
243
244 rw->rwcAfter= RTFafterARG;
245
246 return 0;
247 }
248
docRtfWriteFlagTag(RtfWriter * rw,const char * tag,int arg)249 void docRtfWriteFlagTag( RtfWriter * rw,
250 const char * tag,
251 int arg )
252 {
253 if ( arg )
254 { docRtfWriteTag( rw, tag ); }
255 else{ docRtfWriteArgTag( rw, tag, arg ); }
256 }
257
docRtfWriteAltTag(RtfWriter * rw,const char * yesTag,const char * noTag,int arg)258 void docRtfWriteAltTag( RtfWriter * rw,
259 const char * yesTag,
260 const char * noTag,
261 int arg )
262 {
263 if ( arg )
264 { docRtfWriteTag( rw, yesTag ); }
265 else{ docRtfWriteTag( rw, noTag ); }
266 }
267
docRtfWriteEnumTag(RtfWriter * rw,const char * const * tags,int arg,int tagCount,int enumCount)268 void docRtfWriteEnumTag( RtfWriter * rw,
269 const char * const * tags,
270 int arg,
271 int tagCount,
272 int enumCount )
273 {
274 if ( tagCount != enumCount )
275 { LLSDEB(tagCount,enumCount,tags[0]); return; }
276
277 if ( arg < 0 || arg >= tagCount )
278 { LLSDEB(tagCount,arg,tags[0]); return; }
279
280 if ( tags[arg] )
281 { docRtfWriteTag( rw, tags[arg] ); }
282 }
283
docRtfWriteSemicolon(RtfWriter * rw)284 void docRtfWriteSemicolon( RtfWriter * rw )
285 {
286 sioOutPutString( ";", rw->rwSosOut );
287 rw->rwCol += 1;
288
289 rw->rwcAfter= RTFafterTEXT;
290 }
291
292 /************************************************************************/
293 /* */
294 /* Write object data. */
295 /* */
296 /************************************************************************/
297
docRtfWriteMemoryBuffer(RtfWriter * rw,const MemoryBuffer * mb)298 int docRtfWriteMemoryBuffer( RtfWriter * rw,
299 const MemoryBuffer * mb )
300 {
301 const unsigned char * s;
302 int i;
303
304 if ( rw->rwCol+ mb->mbSize > 78 )
305 { docRtfWriteNextLine( rw ); }
306
307 if ( rw->rwcAfter != RTFafterTEXT )
308 {
309 if ( sioOutPutByte( ' ', rw->rwSosOut ) < 0 )
310 { LDEB(1); return -1; }
311 rw->rwCol += 1;
312 rw->rwcAfter= RTFafterTEXT;
313 }
314
315 s= mb->mbBytes;
316 for ( i= 0; i < mb->mbSize; s++, i++ )
317 {
318 if ( rw->rwCol >= 78 )
319 { docRtfWriteNextLine( rw ); }
320
321 if ( sioOutPutByte( *s, rw->rwSosOut ) < 0 )
322 { LDEB(1); return -1; }
323
324 rw->rwCol++;
325 }
326
327 return 0;
328 }
329
330 /************************************************************************/
331 /* */
332 /* Write a word 2000 style table or cell formatting property. */
333 /* */
334 /************************************************************************/
335
docRtfSaveAutoSpace(RtfWriter * rw,const char * unitTag,int unit,const char * numberTag,int number)336 void docRtfSaveAutoSpace( RtfWriter * rw,
337 const char * unitTag,
338 int unit,
339 const char * numberTag,
340 int number )
341 {
342 if ( number != 0 || unit != TRautoNONE )
343 { docRtfWriteArgTag( rw, unitTag, unit ); }
344
345 if ( number != 0 )
346 { docRtfWriteArgTag( rw, numberTag, number ); }
347
348 return;
349 }
350
351 /************************************************************************/
352 /* */
353 /* Write an encoded destination and its contents. */
354 /* */
355 /************************************************************************/
356
docRtfWriteDocEncodedStringDestination(RtfWriter * rw,const char * tag,const char * s,int n,int addSemicolon)357 void docRtfWriteDocEncodedStringDestination(
358 RtfWriter * rw,
359 const char * tag,
360 const char * s,
361 int n,
362 int addSemicolon )
363 {
364 docRtfWriteDestinationBegin( rw, tag );
365
366 if ( n > 0 )
367 { docRtfWriteDocEncodedString( rw, s, n ); }
368
369 if ( addSemicolon )
370 { docRtfWriteSemicolon( rw ); }
371
372 docRtfWriteDestinationEnd( rw );
373
374 return;
375 }
376
377 /************************************************************************/
378 /* */
379 /* Write a destination that does not need any transcoding. */
380 /* */
381 /************************************************************************/
382
docRtfWriteRawBytesDestination(RtfWriter * rw,const char * tag,const char * s,int n)383 void docRtfWriteRawBytesDestination( RtfWriter * rw,
384 const char * tag,
385 const char * s,
386 int n )
387 {
388 docRtfWriteDestinationBegin( rw, tag );
389
390 if ( n > 0 )
391 { docRtfWriteRawBytes( rw, s, n ); }
392
393 docRtfWriteDestinationEnd( rw );
394
395 return;
396 }
397
398 /************************************************************************/
399 /* */
400 /* Open a writer. */
401 /* */
402 /************************************************************************/
403
docRtfOpenWriter(SimpleOutputStream * sos,BufferDocument * bd,int flags)404 RtfWriter * docRtfOpenWriter( SimpleOutputStream * sos,
405 BufferDocument * bd,
406 int flags )
407 {
408 RtfWriter * rval= (RtfWriter *)0;
409 RtfWriter * rw= (RtfWriter *)0;
410
411 rw= (RtfWriter *)malloc(sizeof(RtfWriter) );
412 if ( ! rw )
413 { PDEB(rw); goto ready; }
414
415 docRtfInitWritingContext( rw );
416
417 rw->rwRtfTextConverter= malloc( sizeof(TextConverter) );
418 if ( ! rw->rwRtfTextConverter )
419 { PDEB(rw->rwRtfTextConverter); goto ready; }
420 textInitTextConverter( rw->rwRtfTextConverter );
421
422 rw->rwTextTextConverter= malloc( sizeof(TextConverter) );
423 if ( ! rw->rwTextTextConverter )
424 { PDEB(rw->rwTextTextConverter); goto ready; }
425 textInitTextConverter( rw->rwTextTextConverter );
426
427 rw->rwDocument= bd;
428 rw->rwSosOut= sos;
429 rw->rwSaveFlags= flags;
430
431 docRtfWriteSetupTextConverters( rw );
432
433 rval= rw; rw= (RtfWriter *)0; /* steal */
434
435 ready:
436
437 if ( rw )
438 { docRtfCloseWriter( rw ); }
439
440 return rval;
441 }
442
443 /************************************************************************/
444 /* */
445 /* Close a writer. */
446 /* */
447 /************************************************************************/
448
docRtfCloseWriter(RtfWriter * rw)449 void docRtfCloseWriter( RtfWriter * rw )
450 {
451 docRtfCleanWritingContext( rw );
452 free( rw );
453
454 return;
455 }
456