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