1 /************************************************************************/
2 /* */
3 /* Evaluate fields+ the list of kinds of fields. */
4 /* */
5 /************************************************************************/
6
7 # include "docBufConfig.h"
8
9 # include <string.h>
10
11 # include <appDebugon.h>
12
13 # include "docBuf.h"
14 # include "docNotes.h"
15 # include "docField.h"
16 # include "docParaString.h"
17 # include "docEvalField.h"
18 # include "docParaParticules.h"
19 # include "docDebug.h"
20 # include <docTreeType.h>
21 # include <docDocumentNote.h>
22 # include "docTreeScanner.h"
23 # include "docDebug.h"
24 # include "docRecalculateFields.h"
25
26 /************************************************************************/
27 /* */
28 /* Manage fields. */
29 /* */
30 /************************************************************************/
31
docInitRecalculateFields(RecalculateFields * rf)32 void docInitRecalculateFields( RecalculateFields * rf )
33 {
34 rf->rfDocument= (BufferDocument *)0;
35 rf->rfTree= (DocumentTree *)0;
36 rf->rfSelectedTree= (DocumentTree *)0;
37 rf->rfMergeValueTree= (void *)0;
38 rf->rfCloseObject= (DOC_CLOSE_OBJECT)0;
39 rf->rfFieldsUpdated= 0;
40 rf->rfUpdateFlags= 0;
41
42 rf->rfBodySectNode= (const BufferItem *)0;
43 rf->rfBodySectPage= -1;
44
45 docInitEditPosition( &(rf->rfSelHead) );
46 docInitEditPosition( &(rf->rfSelTail) );
47
48 rf->rfFieldDataProvider= (FieldDataProvider)0;
49 rf->rfInstanceStreamProvider= (InstanceStreamProvider)0;
50 rf->rfMergeThrough= (void *)0;
51
52 return;
53 }
54
55 /************************************************************************/
56 /* */
57 /* Replace the previous contents of a field with new contents. */
58 /* */
59 /************************************************************************/
60
docFieldReplaceContents(int * pStroff,int * pStroffShift,int * pTextAttrNr,BufferItem * paraNode,int part,int partCount,int stroffShift,const char * addedString,int addedStrlen,const RecalculateFields * rf)61 int docFieldReplaceContents(
62 int * pStroff,
63 int * pStroffShift,
64 int * pTextAttrNr,
65 BufferItem * paraNode,
66 int part,
67 int partCount,
68 int stroffShift,
69 const char * addedString,
70 int addedStrlen,
71 const RecalculateFields * rf )
72 {
73 int i;
74 TextParticule * tp= paraNode->biParaParticules+ part;
75
76 int textAttributeNumber= tp[1].tpTextAttrNr;
77 int past= tp[1+partCount].tpStroff+ stroffShift;
78 int stroff= tp[1].tpStroff+ stroffShift;
79
80 int d= 0;
81
82 if ( docParaStringReplace( &d, paraNode, stroff, past,
83 addedString, addedStrlen ) )
84 { LDEB(addedStrlen); return -1; }
85
86 if ( partCount > 0 )
87 {
88 tp= paraNode->biParaParticules+ part+ 1;
89 for ( i= 0; i < partCount; tp++, i++ )
90 {
91 if ( rf->rfCloseObject )
92 { (*rf->rfCloseObject)( rf->rfDocument, tp ); }
93 docCleanParticuleObject( rf->rfDocument, tp );
94 }
95
96 docDeleteParticules( paraNode, part+ 1, partCount );
97 }
98
99 *pStroff= stroff;
100 *pStroffShift= d;
101 *pTextAttrNr= textAttributeNumber;
102 return 0;
103 }
104
105 /************************************************************************/
106
docRecalculateFieldParticulesFromString(int * pCalculated,int * pPartShift,int * pStroffShift,BufferItem * paraNode,int part,int partCount,const MemoryBuffer * mbResult,const RecalculateFields * rf)107 int docRecalculateFieldParticulesFromString(
108 int * pCalculated,
109 int * pPartShift,
110 int * pStroffShift,
111 BufferItem * paraNode,
112 int part,
113 int partCount,
114 const MemoryBuffer * mbResult,
115 const RecalculateFields * rf )
116 {
117 int d;
118
119 TextParticule * tp= paraNode->biParaParticules+ part;
120 int textAttributeNumber;
121
122 int past;
123 int stroff;
124 int partsMade;
125
126 int i;
127
128 if ( tp[1].tpStrlen == mbResult->mbSize &&
129 ! memcmp( docParaString( paraNode, tp[1].tpStroff+ *pStroffShift ),
130 mbResult->mbBytes, mbResult->mbSize ) )
131 {
132 *pCalculated= 0;
133 *pPartShift= 0;
134 /* NO! *pStroffShift= 0; */
135 return 0;
136 }
137
138 textAttributeNumber= tp[1].tpTextAttrNr;
139 past= tp[1+partCount].tpStroff+ *pStroffShift;
140 stroff= tp[1].tpStroff+ *pStroffShift;
141
142 if ( docParaStringReplace( &d, paraNode, stroff, past,
143 (char *)mbResult->mbBytes, mbResult->mbSize ) )
144 { LDEB(mbResult->mbSize); return -1; }
145
146 tp= paraNode->biParaParticules+ part+ 1;
147 for ( i= 0; i < partCount; tp++, i++ )
148 {
149 if ( rf->rfCloseObject )
150 { (*rf->rfCloseObject)( rf->rfDocument, tp ); }
151
152 docCleanParticuleObject( rf->rfDocument, tp );
153 }
154
155 partsMade= docRedivideStringInParticules( paraNode, stroff,
156 mbResult->mbSize,
157 part+ 1, partCount, textAttributeNumber );
158 if ( partsMade < partCount )
159 {
160 docDeleteParticules( paraNode,
161 part+ 1+ partsMade, partCount- partsMade );
162 }
163
164 *pCalculated= 1;
165 *pPartShift= partsMade- partCount;
166 *pStroffShift += d;
167
168 return 0;
169 }
170
171 /************************************************************************/
172 /* */
173 /* Substitute an individual text field in a paragraph. */
174 /* */
175 /* NOTE: This routine is not recursive. Nested fields are handeled */
176 /* by the caller. */
177 /* */
178 /************************************************************************/
179
docRecalculateParaStringTextParticules(int * pCalculated,int * pPartShift,int * pStroffShift,BufferItem * paraNode,int part,int partCount,DocumentField * df,const RecalculateFields * rf)180 int docRecalculateParaStringTextParticules(
181 int * pCalculated,
182 int * pPartShift,
183 int * pStroffShift,
184 BufferItem * paraNode,
185 int part,
186 int partCount,
187 DocumentField * df,
188 const RecalculateFields * rf )
189 {
190 int rval= 0;
191 MemoryBuffer mbResult;
192 int calculated= 0;
193
194 const FieldKindInformation * fki= DOC_FieldKinds+ df->dfKind;
195
196 utilInitMemoryBuffer( &mbResult );
197
198 if ( (*fki->fkiCalculateTextString)( &calculated, &mbResult, df, rf ) )
199 { SDEB(fki->fkiLabel); rval= -1; goto ready; }
200
201 if ( ! calculated )
202 {
203 *pCalculated= 0;
204 *pPartShift= 0;
205 /* NO! *pStroffShift= 0; */
206 goto ready;
207 }
208
209 if ( docRecalculateFieldParticulesFromString(
210 pCalculated, pPartShift, pStroffShift,
211 paraNode, part, partCount, &mbResult, rf ) )
212 { LDEB(1); rval= -1; goto ready; }
213
214 ready:
215
216 utilCleanMemoryBuffer( &mbResult );
217
218 return rval;
219 }
220
221 /************************************************************************/
222 /* */
223 /* Substitute the text fields in a paragraph. */
224 /* */
225 /* 1) For all fields in range... */
226 /* NOTE that the end of the range may have been shifted by the */
227 /* calculation of field results. */
228 /* 2) Shift this particule by what previous calculations have changed */
229 /* in size. */
230 /* 3) Not the beginning of a field.. Irrelevant. */
231 /* 4) Retrieve the field. Do some sanity checks: Only text level */
232 /* fields are evaluated here. */
233 /* 5) Count the number of particules currently in the field. */
234 /* 6) When the field is to be recalculated.. do so. */
235 /* NOTE that this may shift both the array of particules and the */
236 /* paragraph text. */
237 /* Otherwise just shift the offsets of the particules inside the */
238 /* field. */
239 /* 7) When there is sufficient space inside the field to contain */
240 /* yet another one.. go into recursion. */
241 /* NOTE that this may shift both the array of particules and the */
242 /* paragraph text. */
243 /* 8) Shift the end particule of the field. */
244 /* 9) Set the current position in the loop to the end particule. The */
245 /* loop increment will move to the particule after the field. */
246 /* */
247 /************************************************************************/
248
docRecalculateParaTextFields(RecalculateFields * rf,int * pPartShift,int * pStroffShift,BufferItem * paraNode,int part,int partUpto)249 static int docRecalculateParaTextFields(
250 RecalculateFields * rf,
251 int * pPartShift,
252 int * pStroffShift,
253 BufferItem * paraNode,
254 int part,
255 int partUpto )
256 {
257 BufferDocument * bd= rf->rfDocument;
258 int fieldsUpdated= 0;
259 int paraNr= -1;
260
261 /* 1 */
262 for ( part= part; part < partUpto+ *pPartShift; part++ )
263 {
264 TextParticule * tp= paraNode->biParaParticules+ part;
265
266 DocumentField * df;
267 const FieldKindInformation * fki;
268
269 int tailPart;
270 int partCount;
271 int closed;
272 int stroffTail;
273
274 /* 2 */
275 if ( docShiftParticuleOffsets( rf->rfDocument, paraNode, part, part+ 1,
276 *pStroffShift ) )
277 { LDEB(*pStroffShift); }
278
279 /* 3 */
280 if ( tp->tpKind != DOCkindFIELDHEAD )
281 { continue; }
282
283 if ( paraNr <= 0 &&
284 ( rf->rfSelHead.epParaNr > 0 ||
285 rf->rfSelTail.epParaNr > 0 ) )
286 { paraNr= docNumberOfParagraph( paraNode ); }
287
288 /* 4 */
289 df= docGetFieldByNumber( &(bd->bdFieldList), tp->tpObjectNumber );
290 if ( ! df )
291 {
292 LXDEB(tp->tpObjectNumber,df);
293 docListNode(0,paraNode,0);
294 docListFieldTree(rf->rfDocument,rf->rfTree);
295 continue;
296 }
297 if ( df->dfKind >= DOC_FieldKindCount )
298 { LLDEB(df->dfKind,DOC_FieldKindCount); continue; }
299
300 fki= DOC_FieldKinds+ df->dfKind;
301
302 /* 5 */
303 partCount= docCountParticulesInField( paraNode, &closed, part,
304 partUpto+ *pPartShift );
305 if ( partCount < 0 )
306 { SLDEB(docFieldKindStr(df->dfKind),partCount); continue; }
307 tailPart= part+ 1+ partCount;
308 if ( tailPart < paraNode->biParaParticuleCount )
309 { stroffTail= tp[1+partCount].tpStroff; }
310 else{ stroffTail= docParaStrlen( paraNode ); }
311
312 /* 6 */
313 if ( closed &&
314 fki->fkiLevel == DOClevSPAN &&
315 ( fki->fkiCalculateWhen & rf->rfUpdateFlags ) &&
316 fki->fkiCalculateTextParticules )
317 {
318 int partShift= 0;
319 int calculated= 0;
320 int oldStroffShift= *pStroffShift;
321
322 if ( (*fki->fkiCalculateTextParticules)( &calculated,
323 &partShift, pStroffShift,
324 paraNode, part, partCount, df, rf ) )
325 { LDEB(1); return -1; }
326
327 if ( calculated )
328 {
329 int stroffShift= *pStroffShift- oldStroffShift;
330
331 if ( rf->rfTree == rf->rfSelectedTree )
332 {
333 docAdjustEditPositionOffsetB( &(rf->rfSelHead),
334 paraNr, stroffTail, stroffShift );
335 docAdjustEditPositionOffsetE( &(rf->rfSelTail),
336 paraNr, stroffTail, stroffShift );
337 }
338
339 fieldsUpdated++; rf->rfFieldsUpdated++;
340 }
341 else{
342 if ( docShiftParticuleOffsets( rf->rfDocument, paraNode,
343 part+ 1, tailPart, *pStroffShift ) )
344 { LDEB(*pStroffShift); }
345 }
346
347 tailPart += partShift;
348 *pPartShift += partShift;
349 }
350 else{
351 if ( docShiftParticuleOffsets( rf->rfDocument, paraNode,
352 part+ 1, tailPart, *pStroffShift ) )
353 { LDEB(*pStroffShift); }
354 }
355
356 /* 7 */
357 if ( tailPart- part >= 2 )
358 {
359 int partShift= 0;
360 int stroffShift= 0;
361
362 if ( docRecalculateParaTextFields( rf,
363 &partShift, &stroffShift, paraNode, part+ 1, tailPart ) )
364 { LDEB(1); return -1; }
365
366 tailPart += partShift;
367 *pPartShift += partShift;
368 *pStroffShift += stroffShift;
369 }
370
371 /* 8 */
372 if ( closed )
373 {
374 tp= paraNode->biParaParticules+ tailPart;
375 if ( tp->tpKind != DOCkindFIELDTAIL )
376 { LDEB(tp->tpKind); }
377
378 tp->tpStroff += *pStroffShift;
379 df->dfTailPosition.epStroff= tp->tpStroff;
380 }
381
382 /* 9 */
383 part= tailPart;
384 }
385
386 if ( fieldsUpdated )
387 { docInvalidateParagraphLayout( paraNode ); }
388
389 return 0;
390 }
391
392 /************************************************************************/
393 /* */
394 /* Substitute the text fields in a document tree. */
395 /* */
396 /* 1) Unexpected recursion? */
397 /* */
398 /************************************************************************/
399
docRecalculateTextLevelFieldsInDocumentTree(RecalculateFields * rf,DocumentTree * dt,const BufferItem * bodySectNode,int page)400 int docRecalculateTextLevelFieldsInDocumentTree(
401 RecalculateFields * rf,
402 DocumentTree * dt,
403 const BufferItem * bodySectNode,
404 int page )
405 {
406 int rval= 0;
407 int ret;
408 int saveFieldsUpdated= rf->rfFieldsUpdated;
409 DocumentTree * saveTree= rf->rfTree;
410 const BufferItem * saveBodySectNode= rf->rfBodySectNode;
411 int saveBodySectPage= rf->rfBodySectPage;
412
413 if ( ! dt->dtRoot )
414 { return 0; }
415
416 if ( dt->dtRoot->biTreeType != DOCinBODY &&
417 ( ! bodySectNode ||
418 bodySectNode->biTreeType != DOCinBODY ) )
419 { XDEB(rf->rfBodySectNode); return -1; }
420
421 rf->rfBodySectNode= bodySectNode;
422 rf->rfBodySectPage= page;
423
424 rf->rfFieldsUpdated= 0;
425 rf->rfTree= dt;
426
427 ret= docRecalculateTextLevelFields( rf, dt->dtRoot );
428 if ( ret )
429 { LDEB(ret); rval= -1; }
430
431 if ( rf->rfFieldsUpdated > 0 )
432 { docInvalidateTreeLayout( dt ); }
433
434 rf->rfFieldsUpdated += saveFieldsUpdated;
435
436 rf->rfTree= saveTree;
437 rf->rfBodySectNode= saveBodySectNode;
438 rf->rfBodySectPage= saveBodySectPage;
439
440 return rval;
441 }
442
docRecalculateTextLevelFieldsInSeparators(RecalculateFields * rf,const BufferItem * bodySectNode)443 static int docRecalculateTextLevelFieldsInSeparators(
444 RecalculateFields * rf,
445 const BufferItem * bodySectNode )
446 {
447 const int page= -1;
448 BufferDocument * bd= rf->rfDocument;
449
450 if ( docRecalculateTextLevelFieldsInDocumentTree( rf,
451 &(bd->bdEiFtnsep), bodySectNode, page ) )
452 { LDEB(1); return -1; }
453
454 if ( docRecalculateTextLevelFieldsInDocumentTree( rf,
455 &(bd->bdEiFtnsepc), bodySectNode, page ) )
456 { LDEB(1); return -1; }
457
458 if ( docRecalculateTextLevelFieldsInDocumentTree( rf,
459 &(bd->bdEiFtncn), bodySectNode, page ) )
460 { LDEB(1); return -1; }
461
462 if ( docRecalculateTextLevelFieldsInDocumentTree( rf,
463 &(bd->bdEiAftnsep), bodySectNode, page ) )
464 { LDEB(1); return -1; }
465
466 if ( docRecalculateTextLevelFieldsInDocumentTree( rf,
467 &(bd->bdEiAftnsepc), bodySectNode, page ) )
468 { LDEB(1); return -1; }
469
470 if ( docRecalculateTextLevelFieldsInDocumentTree( rf,
471 &(bd->bdEiAftncn), bodySectNode, page ) )
472 { LDEB(1); return -1; }
473
474 return 0;
475 }
476
docRecalculateTextLevelFieldsInSectHdFt(RecalculateFields * rf,const BufferItem * bodySectNode)477 static int docRecalculateTextLevelFieldsInSectHdFt(
478 RecalculateFields * rf,
479 const BufferItem * bodySectNode )
480 {
481 const int page= -1;
482 SectHeadersFooters * shf= bodySectNode->biSectHeadersFooters;
483
484 rf->rfBodySectNode= bodySectNode;
485
486 if ( docRecalculateTextLevelFieldsInDocumentTree( rf,
487 &(shf->shfFirstPageHeader), bodySectNode, page ) )
488 { LDEB(1); return -1; }
489
490 if ( docRecalculateTextLevelFieldsInDocumentTree( rf,
491 &(shf->shfLeftPageHeader), bodySectNode, page ) )
492 { LDEB(1); return -1; }
493
494 if ( docRecalculateTextLevelFieldsInDocumentTree( rf,
495 &(shf->shfRightPageHeader), bodySectNode, page ) )
496 { LDEB(1); return -1; }
497
498
499 if ( docRecalculateTextLevelFieldsInDocumentTree( rf,
500 &(shf->shfFirstPageFooter), bodySectNode, page ) )
501 { LDEB(1); return -1; }
502
503 if ( docRecalculateTextLevelFieldsInDocumentTree( rf,
504 &(shf->shfLeftPageFooter), bodySectNode, page ) )
505 { LDEB(1); return -1; }
506
507 if ( docRecalculateTextLevelFieldsInDocumentTree( rf,
508 &(shf->shfRightPageFooter), bodySectNode, page ) )
509 { LDEB(1); return -1; }
510
511 return 0;
512 }
513
docRecalculateTextLevelFieldsInSectNotes(RecalculateFields * rf,const BufferItem * bodySectNode)514 static int docRecalculateTextLevelFieldsInSectNotes(
515 RecalculateFields * rf,
516 const BufferItem * bodySectNode )
517 {
518 BufferDocument * bd= rf->rfDocument;
519
520 DocumentField * dfNote;
521 DocumentNote * dn;
522 const int page= -1;
523 const int treeType= -1;
524
525 dfNote= docGetFirstNoteOfSection( &dn, bd,
526 bodySectNode->biNumberInParent, treeType );
527 while( dfNote )
528 {
529 DocumentTree * dt= &(dn->dnDocumentTree);
530
531 if ( ! dt->dtRoot )
532 { continue; }
533
534 if ( docRecalculateTextLevelFieldsInDocumentTree( rf,
535 dt, bodySectNode, page ) )
536 { LDEB(1); return -1; }
537
538 dfNote= docGetNextNoteInSection( &dn, bd,
539 bodySectNode->biNumberInParent, dfNote, treeType );
540 }
541
542 return 0;
543 }
544
docRecalculateTextLevelFieldsLeaveNode(struct BufferItem * node,const DocumentSelection * ds,const struct BufferItem * bodySectNode,void * voidrf)545 static int docRecalculateTextLevelFieldsLeaveNode(
546 struct BufferItem * node,
547 const DocumentSelection * ds,
548 const struct BufferItem * bodySectNode,
549 void * voidrf )
550 {
551 RecalculateFields * rf= (RecalculateFields *)voidrf;
552 int rval= 0;
553
554 const BufferItem * saveBodySectNode= rf->rfBodySectNode;
555
556 switch( node->biLevel )
557 {
558 case DOClevBODY:
559 if ( docRecalculateTextLevelFieldsInSeparators( rf,
560 node->biChildren[0] ) )
561 { LDEB(1); rval= -1; goto ready; }
562
563 break;
564
565 case DOClevSECT:
566 if ( node->biTreeType == DOCinBODY )
567 {
568 SectHeadersFooters * shf= node->biSectHeadersFooters;
569
570 if ( ! shf )
571 { XDEB(shf); rval= -1; goto ready; }
572
573 if ( docRecalculateTextLevelFieldsInSectHdFt( rf, node ) )
574 { LDEB(1); rval= -1; goto ready; }
575
576 if ( docRecalculateTextLevelFieldsInSectNotes( rf, node ) )
577 { LDEB(1); rval= -1; goto ready; }
578 }
579
580 break;
581
582 case DOClevPARA:
583
584 {
585 int partShift= 0;
586 int stroffShift= 0;
587
588 if ( docRecalculateParaTextFields( rf, &partShift, &stroffShift,
589 node, 0, node->biParaParticuleCount ) )
590 { LDEB(1); rval= -1; goto ready; }
591 }
592
593 break;
594
595 default:
596 break;
597 }
598
599 ready:
600
601 rf->rfBodySectNode= saveBodySectNode;
602
603 return rval;
604 }
605
docRecalculateTextLevelFields(RecalculateFields * rf,BufferItem * node)606 int docRecalculateTextLevelFields( RecalculateFields * rf,
607 BufferItem * node )
608 {
609 const int flags= 0;
610
611 if ( docScanTreeNode( rf->rfDocument, node,
612 (NodeVisitor)0, docRecalculateTextLevelFieldsLeaveNode,
613 flags, (void *)rf ) )
614 { LDEB(1); return -1; }
615
616 return 0;
617 }
618