1 /************************************************************************/
2 /*									*/
3 /*  Exchange of section properties with RTF.				*/
4 /*									*/
5 /************************************************************************/
6 
7 #   include	"docRtfConfig.h"
8 
9 #   include	<stdio.h>
10 #   include	<ctype.h>
11 
12 #   include	<appDebugon.h>
13 
14 #   include	<docTreeType.h>
15 #   include	<docTreeNode.h>
16 #   include	"docRtfWriterImpl.h"
17 #   include	"docRtfTags.h"
18 
19 /************************************************************************/
20 /*									*/
21 /*  Write Section Properties. For a node, or for the stylesheet.	*/
22 /*									*/
23 /************************************************************************/
24 
docRtfSaveSectionProperties(RtfWriter * rw,const PropertyMask * spMask,const SectionProperties * sp)25 void docRtfSaveSectionProperties( RtfWriter *			rw,
26 				const PropertyMask *		spMask,
27 				const SectionProperties *	sp )
28     {
29     const DocumentGeometry *	dg= &(sp->spDocumentGeometry);
30 
31     /**************/
32 
33     if  ( PROPmaskISSET( spMask, DGpropPAGE_WIDTH ) )
34 	{ docRtfWriteArgTag( rw, "pgwsxn",	dg->dgPageWideTwips );	}
35     if  ( PROPmaskISSET( spMask, DGpropPAGE_HEIGHT ) )
36 	{ docRtfWriteArgTag( rw, "pghsxn",	dg->dgPageHighTwips );	}
37     if  ( PROPmaskISSET( spMask, DGpropLEFT_MARGIN ) )
38 	{ docRtfWriteArgTag( rw, "marglsxn",dg->dgLeftMarginTwips );	}
39     if  ( PROPmaskISSET( spMask, DGpropTOP_MARGIN ) )
40 	{
41 	docRtfWriteArgTag( rw, "margtsxn",dg->dgTopMarginTwips );
42 	}
43     if  ( PROPmaskISSET( spMask, DGpropRIGHT_MARGIN ) )
44 	{
45 	docRtfWriteArgTag( rw, "margrsxn",dg->dgRightMarginTwips );
46 	}
47     if  ( PROPmaskISSET( spMask, DGpropBOTTOM_MARGIN ) )
48 	{
49 	docRtfWriteArgTag( rw, "margbsxn",dg->dgBottomMarginTwips );
50 	}
51     if  ( PROPmaskISSET( spMask, DGpropGUTTER ) )
52 	{
53 	docRtfWriteArgTag( rw, "guttersxn",dg->dgGutterTwips );
54 	}
55     if  ( PROPmaskISSET( spMask, DGpropMARGMIR ) && dg->dgMirrorMargins )
56 	{
57 	docRtfWriteTag( rw, "margmirsxn" );
58 	}
59     if  ( PROPmaskISSET( spMask, DGpropHEADER_POSITION ) )
60 	{
61 	docRtfWriteArgTag( rw, "headery", dg->dgHeaderPositionTwips );
62 	}
63     if  ( PROPmaskISSET( spMask, DGpropFOOTER_POSITION ) )
64 	{
65 	docRtfWriteArgTag( rw, "footery", dg->dgFooterPositionTwips );
66 	}
67 
68     /**************/
69 
70     if  ( PROPmaskISSET( spMask, SPpropRTOL ) )
71 	{
72 	docRtfWriteAltTag( rw, "rtlsect", "ltrsect", sp->spRToL );
73 	}
74 
75     if  ( PROPmaskISSET( spMask, SPpropSTYLE ) )
76 	{ docRtfWriteArgTag( rw, "ds",sp->spStyle );	}
77 
78     if  ( PROPmaskISSET( spMask, SPpropTITLEPG ) )
79 	{ docRtfWriteFlagTag( rw, "titlepg", sp->spHasTitlePage );	}
80 
81     if  ( PROPmaskISSET( spMask, SPpropBREAK_KIND ) )
82 	{
83 	docRtfWriteEnumTag( rw, DOCrtf_SectBreakTags, sp->spBreakKind,
84 				    DOCrtf_SectBreakTagCount, DOCibk_COUNT );
85 	}
86 
87     if  ( PROPmaskISSET( spMask, SPpropNUMBER_STYLE ) )
88 	{
89 	docRtfWriteEnumTag( rw, DOCrtf_PageNumberStyleTags,
90 			    sp->spPageNumberStyle,
91 			    DOCrtf_PageNumberStyleTagCount, DOCpgn_COUNT );
92 	}
93 
94     if  ( PROPmaskISSET( spMask, SPpropNUMBER_HYPHEN ) )
95 	{
96 	docRtfWriteEnumTag( rw, DOCrtf_PageNumberHyphenTags,
97 			    sp->spPageNumberHyphen,
98 			    DOCrtf_PageNumberHyphenTagCount, DOCpgnh_COUNT );
99 	}
100 
101     if  ( PROPmaskISSET( spMask, SPpropPAGE_RESTART ) )
102 	{
103 	docRtfWriteAltTag( rw, "pgnrestart", "pgncont",
104 						sp->spRestartPageNumbers );
105 	}
106 
107     if  ( PROPmaskISSET( spMask, SPpropSTART_PAGE ) )
108 	{
109 	docRtfWriteArgTag( rw, "pgnstarts", sp->spStartPageNumber+ 1 );
110 	}
111 
112     if  ( PROPmaskISSET( spMask, SPpropCOLUMN_COUNT ) )
113 	{ docRtfWriteArgTag( rw, "cols", sp->spColumnCount );	}
114     if  ( PROPmaskISSET( spMask, SPpropCOLUMN_SPACING ) )
115 	{ docRtfWriteArgTag( rw, "colsx", sp->spColumnSpacingTwips ); }
116 
117     if  ( PROPmaskISSET( spMask, SPpropCOLUMNS )	||
118 	  sp->spColumnCount > 1				)
119 	{
120 	int			i;
121 	const SectionColumn *	sc= sp->spColumns;
122 
123 
124 	for ( i= 0; i < sp->spColumnCount; sc++, i++ )
125 	    {
126 	    if  ( sc->scColumnWidthTwips == 0	&&
127 		  sc->scSpaceToRightTwips == 0	)
128 		{ continue;	}
129 
130 	    docRtfWriteArgTag( rw, "colno", i+ 1 );
131 
132 	    if  ( sc->scColumnWidthTwips != 0 )
133 		{
134 		docRtfWriteArgTag( rw, "colw", sc->scColumnWidthTwips );
135 		}
136 	    if  ( sc->scSpaceToRightTwips != 0 )
137 		{
138 		docRtfWriteArgTag( rw, "colsr", sc->scSpaceToRightTwips );
139 		}
140 	    }
141 	}
142 
143     if  ( PROPmaskISSET( spMask, SPpropLINEBETCOL ) )
144 	{ docRtfWriteFlagTag( rw, "linebetcol", sp->spLineBetweenColumns ); }
145 
146     docRtfWriteNextLine( rw );
147 
148     /**************/
149 
150     docRtfSaveNotesProperties( rw, spMask,
151 			    &(sp->spNotesProperties.fepFootnotesProps),
152 			    DOCsectFOOTNOTE_PROP_MAP, "sftnstart",
153 			    DOCrtf_SectFootNotesJustificationTags,
154 			    DOCrtf_SectFootNotesJustificationTagCount,
155 			    (const char **)0, 0,
156 			    DOCrtf_SectFootNotesRestartTags,
157 			    DOCrtf_SectFootNotesRestartTagCount,
158 			    DOCrtf_SectFootNotesNumberStyleTags,
159 			    DOCrtf_SectFootNotesNumberStyleTagCount );
160 
161     docRtfSaveNotesProperties( rw, spMask,
162 			    &(sp->spNotesProperties.fepEndnotesProps),
163 			    DOCsectENDNOTE_PROP_MAP, "saftnstart",
164 			    DOCrtf_SectEndNotesJustificationTags,
165 			    DOCrtf_SectEndNotesJustificationTagCount,
166 			    (const char **)0, 0,
167 			    DOCrtf_SectEndNotesRestartTags,
168 			    DOCrtf_SectEndNotesRestartTagCount,
169 			    DOCrtf_SectEndNotesNumberStyleTags,
170 			    DOCrtf_SectEndNotesNumberStyleTagCount );
171 
172     return;
173     }
174 
175 /************************************************************************/
176 /*									*/
177 /*  Write Section Properties for a node					*/
178 /*									*/
179 /*  1)  Only save geometry if it differs from that of the document.	*/
180 /*  2)  Then always start from the default for this document.		*/
181 /*									*/
182 /************************************************************************/
183 
docRtfSaveSectionPropertiesOfNode(RtfWriter * rw,const DocumentSelection * ds,const BufferItem * sectNode)184 int docRtfSaveSectionPropertiesOfNode(
185 				    RtfWriter *			rw,
186 				    const DocumentSelection *	ds,
187 				    const BufferItem *		sectNode )
188     {
189     const SectionProperties *	sp= &(sectNode->biSectProperties);
190     const DocumentProperties *	dp= &(rw->rwDocument->bdProperties);
191 
192     SectionProperties		spDef;
193     PropertyMask		dgSetMask;
194     PropertyMask		spCmpMask;
195     PropertyMask		spDifMask;
196 
197     /*  1  */
198     docInitSectionProperties( &spDef );
199 
200     utilPropMaskClear( &dgSetMask );
201     utilPropMaskFill( &dgSetMask, DGprop_COUNT );
202     PROPmaskUNSET( &dgSetMask, DGpropHEADER_POSITION );
203     PROPmaskUNSET( &dgSetMask, DGpropFOOTER_POSITION );
204 
205     utilUpdDocumentGeometry( (PropertyMask *)0, &(spDef.spDocumentGeometry),
206 						&dgSetMask, &(dp->dpGeometry) );
207 
208     spDef.spNotesProperties= dp->dpNotesProps;
209 
210     utilPropMaskClear( &spCmpMask );
211     utilPropMaskFill( &spCmpMask, SPprop_COUNT );
212 
213     utilPropMaskClear( &spDifMask );
214     docSectPropertyDifference( &spDifMask, &spDef, &spCmpMask, sp );
215 
216     if  ( ds )
217 	{ PROPmaskUNSET( &spDifMask, SPpropTITLEPG );	}
218 
219     if  ( rw->rwSpExtraMask )
220 	{ utilPropMaskOr( &spDifMask, &spDifMask, rw->rwSpExtraMask );	}
221 
222     docRtfWriteNextLine( rw );
223     docRtfWriteTag( rw, "sectd" );
224 
225     docRtfSaveSectionProperties( rw, &spDifMask, sp );
226 
227     rw->rwSectionPropertiesSaved= 1;
228 
229   /*ready:*/
230 
231     docCleanSectionProperties( &spDef );
232 
233     return 0;
234     }
235 
236 /************************************************************************/
237 /*									*/
238 /*  Save a header or a footer.. If it exists.				*/
239 /*									*/
240 /************************************************************************/
241 
docRtfSaveSectHeaderFooter(RtfWriter * rw,const BufferItem * sectNode,const BufferItem * prevBi,const char * tag,int treeType)242 static int docRtfSaveSectHeaderFooter(	RtfWriter *		rw,
243 					const BufferItem *	sectNode,
244 					const BufferItem *	prevBi,
245 					const char *		tag,
246 					int			treeType )
247     {
248     const int			forcePar= 1;
249     DocumentTree *		dt;
250     int				evenIfAbsent= 0;
251     unsigned char		applies= 1;
252 
253     dt= docSectionHeaderFooter( sectNode, &applies,
254 				&(rw->rwDocument->bdProperties), treeType );
255 
256     if  ( prevBi )
257 	{
258 	const DocumentTree *	prevDt;
259 
260 	prevDt= docSectionHeaderFooter( prevBi, (unsigned char *)0,
261 				&(rw->rwDocument->bdProperties), treeType );
262 	if  ( prevDt && prevDt->dtRoot )
263 	    { evenIfAbsent= 1;	}
264 	}
265 
266     if  ( dt )
267 	{
268 	if  ( docRtfSaveDocumentTree( rw, tag, dt, evenIfAbsent, forcePar ) )
269 	    { LSDEB(treeType,tag); return -1;	}
270 	}
271 
272     return 0;
273     }
274 
275 /************************************************************************/
276 
277 typedef struct HeaderFooterType
278     {
279     const char *	hftTag;
280     int			htfTreeType;
281     } HeaderFooterType;
282 
283 static const HeaderFooterType	HeaderFooterTypes[]=
284 {
285     { "headerf", DOCinFIRST_HEADER,	},
286     { "headerl", DOCinLEFT_HEADER,	},
287     { "headerr", DOCinRIGHT_HEADER,	},
288     { "footerf", DOCinFIRST_FOOTER,	},
289     { "footerl", DOCinLEFT_FOOTER,	},
290     { "footerr", DOCinRIGHT_FOOTER,	},
291 };
292 
293 static const int HeaderFooterTypeCount=
294 			    sizeof(HeaderFooterTypes)/sizeof(HeaderFooterType);
295 
296 /************************************************************************/
297 /*									*/
298 /*  Save the headers and footers of a Section.				*/
299 /*									*/
300 /************************************************************************/
301 
docRtfSaveSectHeadersFooters(RtfWriter * rw,const BufferItem * sectNode)302 int docRtfSaveSectHeadersFooters(	RtfWriter *		rw,
303 					const BufferItem *	sectNode )
304     {
305     const BufferItem *		prevBi= (const BufferItem *)0;
306     const DocumentProperties *	dp= &(rw->rwDocument->bdProperties);
307 
308     int				hdft;
309 
310     if  ( sectNode->biParent				&&
311 	  sectNode->biNumberInParent > 0			)
312 	{ prevBi= sectNode->biParent->biChildren[ sectNode->biNumberInParent- 1]; }
313 
314     /*  Word 11+ uses right header/footer anyway. For compatibility: */
315     if  ( ! dp->dpHasFacingPages )
316 	{
317 	if  ( docRtfSaveSectHeaderFooter( rw, sectNode, prevBi,
318 					    "header", DOCinRIGHT_HEADER ) )
319 	    { LDEB(1); return -1;	}
320 	}
321 
322     /*  Word 11+ uses right header/footer anyway. For compatibility: */
323     if  ( ! dp->dpHasFacingPages )
324 	{
325 	if  ( docRtfSaveSectHeaderFooter( rw, sectNode, prevBi,
326 					    "footer", DOCinRIGHT_FOOTER ) )
327 	    { LDEB(1); return -1;	}
328 	}
329 
330     for ( hdft= 0; hdft < HeaderFooterTypeCount; hdft++ )
331 	{
332 	const HeaderFooterType* hft= HeaderFooterTypes+ hdft;
333 
334 	if  ( docRtfSaveSectHeaderFooter( rw, sectNode, prevBi,
335 					    hft->hftTag, hft->htfTreeType ) )
336 	    { SDEB(hft->hftTag); return -1;	}
337 	}
338 
339     return 0;
340     }
341 
342 /************************************************************************/
343 /*									*/
344 /*  Save an individial header or footer.				*/
345 /*  Used to trace just this header or footer.				*/
346 /*									*/
347 /************************************************************************/
348 
docRtfSaveHeaderFooter(RtfWriter * rw,const DocumentTree * dt)349 int docRtfSaveHeaderFooter(	RtfWriter *		rw,
350 				const DocumentTree *	dt )
351     {
352     const int			forcePar= 1;
353     const int			evenIfAbsent= 0;
354 
355     int				hdft;
356 
357     if  ( ! dt->dtRoot )
358 	{ XDEB(dt->dtRoot); return -1;	}
359 
360     for ( hdft= 0; hdft < HeaderFooterTypeCount; hdft++ )
361 	{
362 	const HeaderFooterType* hft= HeaderFooterTypes+ hdft;
363 
364 	if  ( hft->htfTreeType != dt->dtRoot->biTreeType )
365 	    { continue;	}
366 
367 	if  ( docRtfSaveDocumentTree( rw, hft->hftTag, dt,
368 						    evenIfAbsent, forcePar ) )
369 	    { SDEB(hft->hftTag); return -1;	}
370 
371 	return 0;
372 	}
373 
374     SDEB(docTreeTypeStr(dt->dtRoot->biTreeType));
375     return -1;
376     }
377