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