1 /************************************************************************/
2 /*									*/
3 /*  Read footnotes, headers, footers, textboxes.			*/
4 /*									*/
5 /************************************************************************/
6 
7 #   include	"docRtfConfig.h"
8 
9 #   include	<string.h>
10 #   include	<stdio.h>
11 #   include	<ctype.h>
12 
13 #   include	<appDebugon.h>
14 
15 #   include	"docRtfReaderImpl.h"
16 #   include	<docParaParticules.h>
17 #   include	<docRecalculateFields.h>
18 #   include	<docTreeType.h>
19 #   include	<docNodeTree.h>
20 #   include	<docNotes.h>
21 #   include	<docDocumentNote.h>
22 
23 /************************************************************************/
24 /*									*/
25 /*  Consume Headers, Footers, Notes &c: Separate item trees that are.	*/
26 /*  embedded in the document.						*/
27 /*									*/
28 /*  1)  Save the current position.					*/
29 /*  2)  Make the header/note &c.					*/
30 /*  3)  Consume its contents.						*/
31 /*  4)  Make sure that no bookmarks protrude beyond the end of the	*/
32 /*	external item.							*/
33 /*  5)  If the external item happens to be empty, insert an empty	*/
34 /*	paragraph to avoid problems later on.				*/
35 /*  6)  Restore the current position.					*/
36 /*									*/
37 /************************************************************************/
38 
docRtfReadDocumentTree(const RtfControlWord * rcw,DocumentTree * dt,int * pExtItKind,RtfReader * rrc,int ignoreEmpty,const SelectionScope * ss)39 int docRtfReadDocumentTree(	const RtfControlWord *	rcw,
40 				DocumentTree *		dt,
41 				int *			pExtItKind,
42 				RtfReader *		rrc,
43 				int			ignoreEmpty,
44 				const SelectionScope *	ss )
45     {
46     int				rval= 0;
47     RtfReadingState		internRrs;
48 
49     DocumentTree *		savedEi;
50     BufferItem *		savedBi;
51     int				savedLevel;
52     SelectionScope		savedSelectionScope;
53     struct RtfFieldStackLevel *	savedFieldStackLevel;
54     int				savedLastFieldNumber;
55     RowProperties		savedRowProperties;
56 
57     int				changed= 0;
58 
59     /*  1  */
60     savedEi= rrc->rrcTree;
61     savedBi= rrc->rrcNode;
62     savedLevel= rrc->rrcLevel;
63     savedSelectionScope= rrc->rrcSelectionScope;
64     savedFieldStackLevel= rrc->rrcFieldStack;
65     savedLastFieldNumber= rrc->rrcLastFieldNumber;
66     savedRowProperties= rrc->rrcRowProperties;
67 
68     docInitRowProperties( &(rrc->rrcRowProperties) );
69 
70     docRtfPushReadingState( rrc, &internRrs );
71 
72     docRtfResetParagraphProperties( &internRrs );
73     docRtfResetTextAttribute( &internRrs, rrc->rrDocument );
74 
75     if  ( ! savedBi )
76 	{ XDEB(savedBi); rval= -1; goto ready;	}
77 
78     /*  2  */
79     if  ( ! dt->dtRoot							&&
80 	  docMakeDocumentTree( rrc->rrDocument, dt,
81 				    ss, &(rrc->rrcSectionProperties) )	)
82 	{ LDEB(1); rval= -1; goto ready;	}
83 
84     /*  3  */
85     rrc->rrcTree= dt;
86     rrc->rrcNode= dt->dtRoot;
87     rrc->rrcLevel= DOClevSECT;
88     rrc->rrcSelectionScope= *ss;
89     rrc->rrcFieldStack= (struct RtfFieldStackLevel *)0;
90     rrc->rrcLastFieldNumber= -1;
91 
92     if  ( docRtfReadGroup( rcw, 0, 0, rrc,
93 			    docRtfDocumentGroups,
94 			    docRtfTextParticule, docRtfFinishCurrentNode ) )
95 	{ LDEB(1); rval= -1;	}
96 
97     /*  5  */
98     {
99     DocumentPosition	dp;
100 
101     if  ( docTailPosition( &dp, dt->dtRoot ) )
102 	{
103 	if  ( ignoreEmpty )
104 	    { docEraseDocumentTree( rrc->rrDocument, dt );	}
105 	else{
106 	    const int	textAttributeNumber= 0;
107 
108 	    if  ( ! docInsertEmptyParagraph( rrc->rrDocument, dt->dtRoot,
109 						textAttributeNumber ) )
110 		{ LDEB(textAttributeNumber);	}
111 	    }
112 	}
113     else{
114 	/********************************************************/
115 	/*  Delete empty paragraph caused by final \par		*/
116 	/********************************************************/
117 	if  ( docParaStrlen( dp.dpNode ) ==  0		&&
118 	      dp.dpNode->biParaTableNesting == 0		&&
119 	      docNumberOfParagraph( dp.dpNode ) > 1	&&
120 	      dp.dpNode->biParaParticuleCount == 1	)
121 	    {
122 	    BufferItem *	bi= dp.dpNode;
123 
124 	    while( bi->biParent && bi->biParent->biChildCount == 1 )
125 		{ bi= bi->biParent;	}
126 
127 	    docDeleteNode( rrc->rrDocument, dt, bi );
128 	    }
129 	}
130     }
131 
132     /*  4  */
133     if  ( docRtfPopScopeFromFieldStack( rrc ) )
134 	{ LDEB(1); rval= -1; goto ready;	}
135 
136     docRenumberSeqFields( &changed, rrc->rrcTree, rrc->rrDocument );
137 
138     *pExtItKind= rrc->rrcSelectionScope.ssTreeType;
139 
140   ready:
141     /*  6  */
142 
143     docCleanRowProperties( &(rrc->rrcRowProperties) );
144     rrc->rrcRowProperties= savedRowProperties;
145 
146     rrc->rrcLastFieldNumber= savedLastFieldNumber;
147     rrc->rrcFieldStack= savedFieldStackLevel;
148     rrc->rrcSelectionScope= savedSelectionScope;
149     rrc->rrcLevel= savedLevel;
150     rrc->rrcNode= savedBi;
151     rrc->rrcTree= savedEi;
152 
153     docRtfPopReadingState( rrc );
154 
155     return rval;
156     }
157 
docRtfReadExtTree(const RtfControlWord * rcw,int arg,RtfReader * rrc)158 int docRtfReadExtTree(		const RtfControlWord *	rcw,
159 				int			arg,
160 				RtfReader *	rrc )
161     {
162     BufferItem *	sectNode;
163     BufferDocument *	bd= rrc->rrDocument;
164     DocumentTree *	dt;
165 
166     SelectionScope	ss;
167     int			treeType;
168     int			ignoreEmpty= 0;
169 
170     docInitSelectionScope( &ss );
171     ss.ssSectNr= 0;
172 
173     switch( rcw->rcwID )
174 	{
175 	case DOCinFIRST_HEADER:
176 	case DOCinLEFT_HEADER:
177 	case DOCinRIGHT_HEADER:
178 
179 	case DOCinFIRST_FOOTER:
180 	case DOCinLEFT_FOOTER:
181 	case DOCinRIGHT_FOOTER:
182 
183 	    sectNode= docRtfGetSectNode( rrc );
184 	    if  ( ! sectNode )
185 		{ XDEB(sectNode); return -1;	}
186 
187 	    dt= docSectionHeaderFooter( sectNode, (unsigned char *)0,
188 			    &(rrc->rrDocument->bdProperties), rcw->rcwID );
189 	    if  ( ! dt )
190 		{ LXDEB(rcw->rcwID,dt); return -1;	}
191 
192 	    ss.ssOwnerSectNr= sectNode->biNumberInParent;
193 	    ignoreEmpty= 1;
194 	    break;
195 
196 	case DOCinFTNSEP:
197 	case DOCinFTNSEPC:
198 	case DOCinFTNCN:
199 	case DOCinAFTNSEP:
200 	case DOCinAFTNSEPC:
201 	case DOCinAFTNCN:
202 
203 	    if  ( ! bd )
204 		{ XDEB(bd); return -1;	}
205 
206 	    dt= docDocumentNoteSeparator( bd, rcw->rcwID );
207 	    if  ( ! dt )
208 		{ LXDEB(rcw->rcwID,dt); return -1;	}
209 
210 	    ignoreEmpty= 1;
211 	    break;
212 
213 	default:
214 	    SDEB(rcw->rcwWord); return -1;
215 	}
216 
217     if  ( dt->dtRoot )
218 	{ docEraseDocumentTree( bd, dt );	}
219 
220     ss.ssTreeType= rcw->rcwID;
221     ss.ssOwnerNumber= -1;
222 
223     if  ( docRtfReadDocumentTree( rcw, dt, &treeType, rrc, ignoreEmpty, &ss ) )
224 	{ SDEB(rcw->rcwWord); return -1;	}
225 
226     return 0;
227     }
228 
229 /************************************************************************/
230 
docExtractFixedTextNote(DocumentNote * dn,BufferDocument * bd,BufferItem * ownerNode,int fixedStroff,int fixedStrlen,const char * fieldinst,int fieldsize)231 static int docExtractFixedTextNote(	DocumentNote *		dn,
232 					BufferDocument *	bd,
233 					BufferItem *		ownerNode,
234 					int			fixedStroff,
235 					int			fixedStrlen,
236 					const char *		fieldinst,
237 					int			fieldsize )
238 
239     {
240     DocumentSelection	dsField;
241     BufferItem *	noteBi;
242     const int		part0= 0;
243 
244     if  ( utilMemoryBufferSetBytes( &(dn->dnNoteProperties.npFixedText),
245 		    docParaString( ownerNode,  fixedStroff ), fixedStrlen ) )
246 	{ LDEB(fixedStrlen);	}
247 
248     if  ( docHeadPosition( &(dsField.dsHead),
249 					dn->dnDocumentTree.dtRoot ) )
250 	{ LDEB(1); return -1;	}
251     noteBi= dsField.dsHead.dpNode;
252     docSetDocumentPosition( &(dsField.dsTail), noteBi, fixedStrlen );
253 
254     if  ( docParaStrlen( noteBi ) >= fixedStrlen			&&
255 	  ! memcmp( docParaString( noteBi, 0 ),
256 		docParaString( ownerNode, fixedStroff ), fixedStrlen )	)
257 	{
258 	int			part1;
259 	TextParticule *		tp1;
260 	DocumentField *		df;
261 
262 	if  ( docFindParticuleOfPosition( &part1, (int *)0,
263 					&(dsField.dsTail), PARAfindFIRST ) )
264 	    { LDEB(fixedStroff); return -1; }
265 	tp1= noteBi->biParaParticules+ part1;
266 
267 	if  ( tp1->tpStroff+ tp1->tpStrlen > fixedStrlen )
268 	    {
269 	    if  ( docSplitTextParticule( &tp1, (TextParticule **)0,
270 					    noteBi, part1, fixedStrlen ) )
271 		{ LDEB(part1); return -1;	}
272 	    }
273 
274 	part1++;
275 
276 	df= docMakeField( bd, &(dn->dnDocumentTree), &dsField,
277 		    part0, part1, tp1->tpTextAttrNr, tp1->tpTextAttrNr );
278 	if  ( ! df )
279 	    { XDEB(df); return -1;	}
280 
281 	df->dfKind= DOCfkCHFTN;
282 	if  ( docSetFieldInst( df, fieldinst, fieldsize ) )
283 	    { LDEB(1);	}
284 	}
285 
286     return 0;
287     }
288 
289 /************************************************************************/
290 /*									*/
291 /*  Consume a footnote.							*/
292 /*									*/
293 /************************************************************************/
294 
docRtfReadFootnote(const RtfControlWord * rcw,int arg,RtfReader * rrc)295 int docRtfReadFootnote(		const RtfControlWord *	rcw,
296 				int			arg,
297 				RtfReader *		rrc )
298     {
299     int			rval= 0;
300     BufferDocument *	bd= rrc->rrDocument;
301 
302     DocumentField *	dfNote;
303     DocumentNote *	dn;
304     int			noteIndex;
305 
306     BufferItem *	ownerNode;
307     BufferItem *	sectNode;
308     SelectionScope	ss;
309 
310     int			treeType;
311     int			autoNumber= 0;
312     const int		ignoreEmpty= 0;
313 
314     int			fixedStroff= 0;
315     int			fixedStrlen= 0;
316 
317     const char *	fieldinst= " -CHFTN ";
318     int			fieldsize= 8;
319 
320     docInitSelectionScope( &ss );
321 
322     ownerNode= docRtfGetParaNode( rrc );
323     if  ( ! ownerNode )
324 	{ XDEB(ownerNode); rval= -1; goto ready;	}
325     sectNode= docGetSectNode( ownerNode );
326     if  ( ! sectNode )
327 	{ XDEB(sectNode); rval= -1; goto ready;	}
328 
329     if  ( rrc->rrcAfterNoteref )
330 	{ autoNumber= 1;	}
331     else{
332 	const char *		fieldRslt= (const char *)0;
333 
334 	DocumentPosition	dp;
335 	int			part0;
336 
337 	dfNote= docRtfSpecialField( DOCfkCHFTN,
338 				    fieldinst, fieldsize, fieldRslt, rrc );
339 	if  ( ! dfNote )
340 	    { SDEB(rcw->rcwWord); rval= -1; goto ready; }
341 
342 	docSetDocumentPosition( &dp, ownerNode,
343 					dfNote->dfHeadPosition.epStroff );
344 	if  ( docFindParticuleOfPosition( &part0, (int *)0,
345 						    &dp, PARAfindFIRST ) )
346 	    { LDEB(dfNote->dfHeadPosition.epStroff); rval= -1; goto ready; }
347 
348 	/* Move the fixed text into the note field */
349 	if  ( ownerNode->biParaParticules[part0   ].tpKind == DOCkindSPAN	&&
350 	      ownerNode->biParaParticules[part0+ 1].tpKind == DOCkindFIELDHEAD )
351 	    {
352 	    fixedStroff= ownerNode->biParaParticules[part0   ].tpStroff;
353 	    fixedStrlen= ownerNode->biParaParticules[part0   ].tpStrlen;
354 
355 	    dfNote->dfHeadPosition.epStroff= fixedStroff;
356 
357 	    ownerNode->biParaParticules[part0+ 1].tpKind= DOCkindSPAN;
358 	    ownerNode->biParaParticules[part0+ 1].tpObjectNumber= -1;
359 	    ownerNode->biParaParticules[part0+ 1].tpStroff= fixedStroff;
360 	    ownerNode->biParaParticules[part0+ 1].tpStrlen= fixedStrlen;
361 
362 	    ownerNode->biParaParticules[part0   ].tpKind= DOCkindFIELDHEAD;
363 	    ownerNode->biParaParticules[part0   ].tpObjectNumber=
364 						    dfNote->dfFieldNumber;
365 	    ownerNode->biParaParticules[part0   ].tpStrlen= 0;
366 	    }
367 
368 	autoNumber= 0;
369 	if  ( fixedStrlen > 0 )
370 	    {
371 	    PROPmaskADD( &(rrc->rrcNotePropertyMask), NOTEpropFIXED_TEXT );
372 	    }
373 	}
374 
375     dfNote= docGetFieldByNumber( &(bd->bdFieldList), rrc->rrcLastFieldNumber );
376     if  ( ! dfNote )
377 	{ LPDEB(rrc->rrcLastFieldNumber,dfNote); return -1;	}
378 
379     noteIndex= docInsertNote( &dn, bd, dfNote, autoNumber );
380     if  ( noteIndex < 0 )
381 	{ LDEB(noteIndex); rval= -1; goto ready;	}
382 
383     rrc->rrcAfterNoteref= 0;
384     rrc->rrAfterParaHeadField= 0;
385 
386     ss.ssTreeType= DOCinFOOTNOTE;
387     ss.ssSectNr= 0;
388     ss.ssOwnerSectNr= sectNode->biNumberInParent;
389     ss.ssOwnerNumber= dfNote->dfFieldNumber;
390 
391     if  ( docRtfReadDocumentTree( rcw, &(dn->dnDocumentTree), &treeType,
392 						rrc, ignoreEmpty, &ss ) )
393 	{ SDEB(rcw->rcwWord); rval= -1; goto ready;	}
394 
395     dn->dnNoteProperties.npAutoNumber= autoNumber;
396     dn->dnNoteProperties.npTreeType= treeType;
397     docSetTreeTypeOfNode( dn->dnDocumentTree.dtRoot, treeType );
398 
399     if  ( ! autoNumber							&&
400 	  fixedStrlen > 0						&&
401 	  docExtractFixedTextNote( dn, bd, ownerNode,
402 					fixedStroff, fixedStrlen,
403 					fieldinst, fieldsize )		)
404 	{ LDEB(1); rval= -1; goto ready;	}
405 
406   ready:
407 
408     return rval;
409     }
410 
411