1 /************************************************************************/
2 /* */
3 /* Trace modifications to a document. */
4 /* */
5 /************************************************************************/
6
7 # include "docEditConfig.h"
8
9 # include <stdio.h>
10 # include <ctype.h>
11 # include <string.h>
12
13 # include <appDebugon.h>
14
15 # include <sioFd.h>
16 # include <utilMD5.h>
17
18 # include "docRtfTrace.h"
19 # include "docEditCommand.h"
20
21 # include <docRtfTraceImpl.h>
22 # include <docRtfWriterImpl.h>
23 # include <docRtfFlags.h>
24 # include <docRtfTags.h>
25 # include <docTreeType.h>
26
27 /************************************************************************/
28 /* */
29 /* Save contents. */
30 /* */
31 /************************************************************************/
32
docRtfTraceContents(RtfWriter * rw,const char * tag,const DocumentSelection * ds)33 static int docRtfTraceContents( RtfWriter * rw,
34 const char * tag,
35 const DocumentSelection * ds )
36 {
37 int rval= 0;
38
39 int saveContents= 0;
40
41 if ( ! docIsIBarSelection( ds ) ||
42 ( rw->rwSaveFlags & RTFflagSAVE_SOMETHING ) )
43 { saveContents= 1; }
44
45 if ( saveContents )
46 {
47 docRtfWriteNextLine( rw );
48 docRtfWriteDestinationBegin( rw, tag );
49
50 # if 0
51 Why?
52 {
53 PropertyMask dpSaveMask;
54
55 if ( docRtfDocPropMask( &dpSaveMask,
56 &(rw->rwDocument->bdProperties) ) )
57 { LDEB(1); rval= -1; goto ready; }
58
59 if ( docRtfSaveDocumentProperties( rw, &dpSaveMask,
60 &(rw->rwDocument->bdProperties) ) )
61 { LDEB(1); rval= -1; goto ready; }
62 }
63 # endif
64
65 if ( ds )
66 {
67 docRtfWriteDestinationBegin( rw, RTFtag__SelOpen );
68 docRtfWriteDestinationEnd( rw );
69 }
70
71 docRtfWriteSwitchToPlain( rw );
72 docCleanParagraphProperties( &(rw->rwcParagraphProperties) );
73 docInitParagraphProperties( &(rw->rwcParagraphProperties) );
74
75 if ( docRtfWriteSelection( rw, ds ) )
76 { LDEB(1); rval= -1; goto ready; }
77
78 docRtfWriteNextLine( rw );
79 docRtfWriteDestinationEnd( rw );
80 }
81
82 ready:
83
84 return rval;
85 }
86
87 /************************************************************************/
88 /* */
89 /* Save the new properties of a property update. */
90 /* */
91 /************************************************************************/
92
docRtfTraceNewProperties(EditOperation * eo,const PropertyMask * taSetMask,const TextAttribute * taSet,const PropertyMask * ppSetMask,const ParagraphProperties * ppSet,const PropertyMask * cpSetMask,const CellProperties * cpSet,const PropertyMask * rpSetMask,const RowProperties * rpSet,const PropertyMask * spSetMask,const SectionProperties * spSet,const PropertyMask * dpSetMask,const DocumentProperties * dpSet)93 int docRtfTraceNewProperties( EditOperation * eo,
94 const PropertyMask * taSetMask,
95 const TextAttribute * taSet,
96
97 const PropertyMask * ppSetMask,
98 const ParagraphProperties * ppSet,
99
100 const PropertyMask * cpSetMask,
101 const CellProperties * cpSet,
102
103 const PropertyMask * rpSetMask,
104 const RowProperties * rpSet,
105
106 const PropertyMask * spSetMask,
107 const SectionProperties * spSet,
108
109 const PropertyMask * dpSetMask,
110 const DocumentProperties * dpSet )
111 {
112 RtfWriter * rw= eo->eoTraceWriter;
113
114 if ( taSetMask && utilPropMaskIsEmpty( taSetMask ) )
115 { taSetMask= (const PropertyMask *)0; }
116 if ( ppSetMask && utilPropMaskIsEmpty( ppSetMask ) )
117 { ppSetMask= (const PropertyMask *)0; }
118 if ( cpSetMask && utilPropMaskIsEmpty( cpSetMask ) )
119 { cpSetMask= (const PropertyMask *)0; }
120 if ( rpSetMask && utilPropMaskIsEmpty( rpSetMask ) )
121 { rpSetMask= (const PropertyMask *)0; }
122 if ( spSetMask && utilPropMaskIsEmpty( spSetMask ) )
123 { spSetMask= (const PropertyMask *)0; }
124 if ( dpSetMask && utilPropMaskIsEmpty( dpSetMask ) )
125 { dpSetMask= (const PropertyMask *)0; }
126
127 docRtfWriteNextLine( rw );
128 docRtfWriteDestinationBegin( rw, RTFtag_NPR );
129
130 if ( dpSetMask )
131 { docRtfSaveDocumentProperties( rw, -1, dpSetMask, dpSet ); }
132 if ( spSetMask )
133 { docRtfSaveSectionProperties( rw, spSetMask, spSet ); }
134 if ( rpSetMask )
135 {
136 const int col0= -1, col1= -1;
137
138 docRtfSaveRowProperties( rw, rpSetMask, rpSet, col0, col1 );
139 }
140 if ( cpSetMask )
141 {
142 const int shiftLeft= 0;
143
144 docRtfSaveCellProperties( rw, cpSetMask, cpSet, shiftLeft );
145 }
146
147 docRtfWriteTag( rw, RTFtag_pard );
148
149 if ( ppSetMask )
150 { docRtfSaveParagraphProperties( rw, ppSetMask, ppSet ); }
151
152 docRtfWriteTag( rw, RTFtag_plain );
153
154 if ( taSetMask )
155 { docRtfSaveTextAttribute( rw, taSetMask, taSet ); }
156
157 /* NO: just the properties docRtfWriteTag( rw, RTFtag_par ); */
158 docRtfWriteNextLine( rw );
159
160 docRtfWriteDestinationEnd( rw );
161 return 0;
162 }
163
164 /************************************************************************/
165 /* */
166 /* Keep track of image properties. */
167 /* */
168 /************************************************************************/
169
docRtfTraceImageProperties(EditOperation * eo,const char * tag,const PropertyMask * pipSetMask,const PictureProperties * pipSet)170 static int docRtfTraceImageProperties(
171 EditOperation * eo,
172 const char * tag,
173 const PropertyMask * pipSetMask,
174 const PictureProperties * pipSet )
175 {
176 RtfWriter * rw= eo->eoTraceWriter;
177
178 docRtfWriteNextLine( rw );
179 docRtfWriteDestinationBegin( rw, tag );
180 docRtfWriteDestinationBegin( rw, RTFtag_pict );
181
182 if ( docRtfSavePictureTags( rw, pipSetMask, pipSet ) )
183 { LDEB(1); return -1; }
184
185 docRtfWriteDestinationEnd( rw );
186 docRtfWriteDestinationEnd( rw );
187 return 0;
188 }
189
docRtfTraceOldImageProperties(EditOperation * eo,const PropertyMask * pipSetMask,const PictureProperties * pipSet)190 int docRtfTraceOldImageProperties(
191 EditOperation * eo,
192 const PropertyMask * pipSetMask,
193 const PictureProperties * pipSet )
194 {
195 return docRtfTraceImageProperties( eo, RTFtag_OTX,
196 pipSetMask, pipSet );
197 }
198
docRtfTraceNewImageProperties(EditOperation * eo,const PropertyMask * pipSetMask,const PictureProperties * pipSet)199 int docRtfTraceNewImageProperties(
200 EditOperation * eo,
201 const PropertyMask * pipSetMask,
202 const PictureProperties * pipSet )
203 {
204 return docRtfTraceImageProperties( eo, RTFtag_NTX,
205 pipSetMask, pipSet );
206 }
207
docRtfTraceList(EditOperation * eo,const char * tag,const DocumentList * dl)208 static int docRtfTraceList( EditOperation * eo,
209 const char * tag,
210 const DocumentList * dl )
211 {
212 RtfWriter * rw= eo->eoTraceWriter;
213
214 docRtfWriteNextLine( rw );
215 docRtfWriteDestinationBegin( rw, tag );
216
217 if ( docRtfWriteListProps( rw, dl ) )
218 { LDEB(1); return -1; }
219
220 docRtfWriteDestinationEnd( rw );
221 return 0;
222 }
223
docRtfTraceOldList(EditOperation * eo,const DocumentList * dl)224 int docRtfTraceOldList( EditOperation * eo,
225 const DocumentList * dl )
226 {
227 return docRtfTraceList( eo, RTFtag_OTX, dl );
228 }
229
docRtfTraceNewList(EditOperation * eo,const DocumentList * dl)230 int docRtfTraceNewList( EditOperation * eo,
231 const DocumentList * dl )
232 {
233 return docRtfTraceList( eo, RTFtag_NTX, dl );
234 }
235
236 /************************************************************************/
237 /* */
238 /* Keep track of note properties. */
239 /* */
240 /************************************************************************/
241
docRtfTraceNoteProperties(EditOperation * eo,const char * textTag,const PropertyMask * npSetMask,const NoteProperties * npSet)242 static int docRtfTraceNoteProperties(
243 EditOperation * eo,
244 const char * textTag,
245 const PropertyMask * npSetMask,
246 const NoteProperties * npSet )
247 {
248 RtfWriter * rw= eo->eoTraceWriter;
249
250 docRtfWriteNextLine( rw );
251 docRtfWriteDestinationBegin( rw, textTag );
252
253 if ( npSet->npAutoNumber )
254 { docRtfWriteTag( rw, "chftn" ); }
255 else{
256 docRtfWriteFontEncodedString( rw,
257 (const char *)npSet->npFixedText.mbBytes,
258 npSet->npFixedText.mbSize );
259 }
260
261 if ( PROPmaskISSET( npSetMask, NOTEpropAUTO_NUMBER ) )
262 {
263 docRtfWriteFlagTag( rw, "FtnAuto", npSet->npAutoNumber );
264 }
265
266 docRtfWriteDestinationBegin( rw, RTFtag_footnote );
267
268 if ( PROPmaskISSET( npSetMask, NOTEpropTREE_TYPE ) )
269 {
270 docRtfWriteAltTag( rw, "ftnalt", "NoFtnalt",
271 npSet->npTreeType == DOCinENDNOTE );
272 }
273
274 docRtfWriteFontEncodedString( rw, "?", 1 );
275
276 docRtfWriteDestinationEnd( rw );
277 docRtfWriteDestinationEnd( rw );
278
279 return 0;
280 }
281
docRtfTraceOldNoteProperties(EditOperation * eo,const PropertyMask * npSetMask,const NoteProperties * npSet)282 int docRtfTraceOldNoteProperties(
283 EditOperation * eo,
284 const PropertyMask * npSetMask,
285 const NoteProperties * npSet )
286 {
287 return docRtfTraceNoteProperties( eo, RTFtag_OTX,
288 npSetMask, npSet );
289 }
290
docRtfTraceNewNoteProperties(EditOperation * eo,const PropertyMask * npSetMask,const NoteProperties * npSet)291 int docRtfTraceNewNoteProperties(
292 EditOperation * eo,
293 const PropertyMask * npSetMask,
294 const NoteProperties * npSet )
295 {
296 return docRtfTraceNoteProperties( eo, RTFtag_NTX,
297 npSetMask, npSet );
298 }
299
300 /************************************************************************/
301 /* */
302 /* Save the old data before a modification. */
303 /* */
304 /************************************************************************/
305
docRtfTraceOldContentsLow(const EditOperation * eo,const DocumentSelection * ds,unsigned int flags)306 int docRtfTraceOldContentsLow( const EditOperation * eo,
307 const DocumentSelection * ds,
308 unsigned int flags )
309 {
310 int rval= 0;
311
312 const char * tag= RTFtag_OTX;
313
314 RtfWriter * rw= eo->eoTraceWriter;
315 int savedFlags= rw->rwSaveFlags;
316
317 rw->rwSaveFlags |= ( flags | RTFflagUNENCODED );
318
319 rval= docRtfTraceContents( rw, tag, ds );
320
321 rw->rwSaveFlags= savedFlags;
322
323 return rval;
324 }
325
326 /************************************************************************/
327 /* */
328 /* Save the old data before a modification. */
329 /* */
330 /************************************************************************/
331
docRtfTraceOldContents(DocumentSelection * ds,const EditOperation * eo,int level,unsigned int flags)332 int docRtfTraceOldContents( DocumentSelection * ds,
333 const EditOperation * eo,
334 int level,
335 unsigned int flags )
336 {
337 const int direction= 0;
338
339 docEditOperationGetSelection( ds, eo );
340
341 switch( level )
342 {
343 case DOClevSPAN:
344 return docRtfTraceOldContentsLow( eo, ds, flags );
345 break;
346 case DOClevPARA:
347 docSelectWholeParagraph( ds, direction );
348 return docRtfTraceOldContentsLow( eo, ds, flags );
349 break;
350
351 case DOClevCELL:
352 docSelectWholeCell( ds, direction, 0 );
353 return docRtfTraceOldContentsLow( eo, ds, flags );
354 break;
355 case DOClevCOLUMN:
356 docSelectWholeCell( ds, direction, 1 );
357 return docRtfTraceOldContentsLow( eo, ds, flags );
358 break;
359 case DOClevROW:
360 docSelectRow( ds, direction, 1 );
361 return docRtfTraceOldContentsLow( eo, ds, flags );
362 break;
363 case DOClevTABLE:
364 docSelectWholeTable( ds );
365 return docRtfTraceOldContentsLow( eo, ds, flags );
366 break;
367
368 case DOClevSECT:
369 docSelectWholeSection( ds, direction );
370 return docRtfTraceOldContentsLow( eo, ds, flags );
371 break;
372 default:
373 LDEB(level); return -1;
374 }
375 }
376
docRtfTraceOldProperties(DocumentSelection * ds,EditOperation * eo,int level,const PropertyMask * taSetMask,const PropertyMask * ppSetMask,const PropertyMask * cpSetMask,const PropertyMask * rpSetMask,const PropertyMask * spSetMask,const PropertyMask * dpSetMask)377 int docRtfTraceOldProperties( DocumentSelection * ds,
378 EditOperation * eo,
379 int level,
380 const PropertyMask * taSetMask,
381 const PropertyMask * ppSetMask,
382 const PropertyMask * cpSetMask,
383 const PropertyMask * rpSetMask,
384 const PropertyMask * spSetMask,
385 const PropertyMask * dpSetMask )
386 {
387 RtfWriter * rw= eo->eoTraceWriter;
388
389 int flags= RTFflagSAVE_SOMETHING;
390
391 if ( taSetMask && utilPropMaskIsEmpty( taSetMask ) )
392 { taSetMask= (const PropertyMask *)0; }
393 if ( ppSetMask && utilPropMaskIsEmpty( ppSetMask ) )
394 { ppSetMask= (const PropertyMask *)0; }
395 if ( cpSetMask && utilPropMaskIsEmpty( cpSetMask ) )
396 { cpSetMask= (const PropertyMask *)0; }
397 if ( rpSetMask && utilPropMaskIsEmpty( rpSetMask ) )
398 { rpSetMask= (const PropertyMask *)0; }
399 if ( spSetMask && utilPropMaskIsEmpty( spSetMask ) )
400 { spSetMask= (const PropertyMask *)0; }
401 if ( dpSetMask && utilPropMaskIsEmpty( dpSetMask ) )
402 { dpSetMask= (const PropertyMask *)0; }
403
404 if ( taSetMask )
405 { flags |= RTFflagSAVE_SOMETHING; }
406 else{
407 flags |= RTFflagOMIT_TEXT;
408
409 if ( ! ppSetMask )
410 {
411 flags |= RTFflagOMIT_PARAS;
412 }
413 }
414
415 if ( cpSetMask || rpSetMask )
416 { flags |= RTFflagEMIT_CELL; }
417
418 rw->rwPpExtraMask= ppSetMask;
419 rw->rwCpExtraMask= cpSetMask;
420 rw->rwRpExtraMask= rpSetMask;
421 rw->rwSpExtraMask= spSetMask;
422
423 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_PRL, level );
424
425 if ( docRtfTraceOldContents( ds, eo, level, flags ) )
426 { LDEB(1); return -1; }
427
428 rw->rwPpExtraMask= (const PropertyMask *)0;
429 rw->rwCpExtraMask= (const PropertyMask *)0;
430 rw->rwRpExtraMask= (const PropertyMask *)0;
431 rw->rwSpExtraMask= (const PropertyMask *)0;
432
433 return 0;
434 }
435
docRtfTraceHeaderFooter(EditOperation * eo,const DocumentTree * dt)436 int docRtfTraceHeaderFooter( EditOperation * eo,
437 const DocumentTree * dt )
438 {
439 RtfWriter * rw= eo->eoTraceWriter;
440
441 docRtfWriteNextLine( rw );
442 docRtfWriteDestinationBegin( rw, RTFtag_OTX );
443
444 if ( dt->dtPageSelectedUpon >= 0 )
445 {
446 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_OPG,
447 dt->dtPageSelectedUpon );
448 if ( dt->dtColumnSelectedIn >= 0 )
449 {
450 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_OCO,
451 dt->dtColumnSelectedIn );
452 }
453 }
454
455 if ( docRtfSaveHeaderFooter( rw, dt ) )
456 { LDEB(1); return -1; }
457
458 docRtfWriteTag( rw, RTFtag_pard );
459 docRtfWriteTag( rw, RTFtag_plain );
460 docRtfWriteTag( rw, RTFtag_par );
461 docRtfWriteNextLine( rw );
462
463 docRtfWriteDestinationEnd( rw );
464
465 return 0;
466 }
467
468 /************************************************************************/
469 /* */
470 /* Save the new data after a modification. */
471 /* */
472 /************************************************************************/
473
docRtfTraceNewContents(EditOperation * eo,int posWhere)474 int docRtfTraceNewContents( EditOperation * eo,
475 int posWhere )
476 {
477 int rval= 0;
478 EditRange * er= &(eo->eoAffectedRange);
479 DocumentSelection ds;
480
481 RtfWriter * rw= eo->eoTraceWriter;
482 int savedFlags= rw->rwSaveFlags;
483
484 docSelectionForEditPositionsInTree( &ds, eo->eoTree,
485 &(er->erHead), &(er->erTail) );
486
487 rw->rwSaveFlags |= RTFflagUNENCODED;
488
489 if ( docRtfTraceContents( eo->eoTraceWriter, RTFtag_NTX, &ds ) )
490 { LDEB(1); rval= -1; goto ready; }
491
492 docRtfTraceNewPosition( eo, (const SelectionScope *)0, posWhere );
493
494 ready:
495
496 rw->rwSaveFlags= savedFlags;
497
498 return rval;
499 }
500
501 /************************************************************************/
502 /* */
503 /* The tags that indicate where the selection was placed after the */
504 /* modification. */
505 /* */
506 /************************************************************************/
507
508 static const char * const DOCrtfSEL_TAGS[]=
509 {
510 RTFtag_SEH,
511 RTFtag_SEN,
512 RTFtag_SAL,
513 RTFtag_SET,
514 RTFtag_SEB,
515 RTFtag_SEA
516 };
517
518 static const int DOCrtfSEL_TAG_COUNT= sizeof(DOCrtfSEL_TAGS)/sizeof(char *);
519
520 /************************************************************************/
521 /* */
522 /* Trace the position at the end of the exit operation. */
523 /* If we switch tree (header,footer,note,body) rememer so. */
524 /* */
525 /************************************************************************/
526
docRtfTraceNewPosition(EditOperation * eo,const SelectionScope * ssNew,int posWhere)527 int docRtfTraceNewPosition( EditOperation * eo,
528 const SelectionScope * ssNew,
529 int posWhere )
530 {
531 EditRange * er= &(eo->eoAffectedRange);
532
533 if ( ssNew )
534 {
535 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_NTT,
536 ssNew->ssTreeType );
537 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_NSN,
538 ssNew->ssSectNr );
539 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_NOSN,
540 ssNew->ssOwnerSectNr );
541 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_NON,
542 ssNew->ssOwnerNumber );
543 }
544
545 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_NHP, er->erHead.epParaNr );
546 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_NHS, er->erHead.epStroff );
547 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_NTP, er->erTail.epParaNr );
548 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_NTS, er->erTail.epStroff );
549
550 if ( posWhere >= 0 && posWhere < DOCrtfSEL_TAG_COUNT )
551 { docRtfWriteTag( eo->eoTraceWriter, DOCrtfSEL_TAGS[posWhere] ); }
552 else{ LLDEB(posWhere,DOCrtfSEL_TAG_COUNT); }
553
554 return 0;
555 }
556
557 /************************************************************************/
558 /* */
559 /* Start a trace item. */
560 /* 1) Remember the operation. */
561 /* 2) Remember the selection scope: In what tree was the selection? */
562 /* 3) Remember the selection. */
563 /* */
564 /************************************************************************/
565
docTraceStartStepLow(EditOperation * eo,EditTrace * et,int command,int fieldKind)566 static int docTraceStartStepLow( EditOperation * eo,
567 EditTrace * et,
568 int command,
569 int fieldKind )
570 {
571 int flags= RTFflagUNENCODED;
572 const char * tag= docRtfGetTraceTag( command );
573
574 if ( ! tag )
575 { LXDEB(command,tag); return -1; }
576
577 docInitTraceStep( &(et->etThisStep) );
578 et->etThisStep.tsCommand= command;
579 et->etThisStep.tsFieldKind= fieldKind;
580 et->etThisStep.tsTraceOffset= 0;
581
582 et->etCount= et->etIndex;
583
584 if ( et->etIndex > 0 )
585 {
586 const TraceStep * ts;
587
588 ts= (const TraceStep *)utilPagedListGetItemByNumber(
589 &(et->etTraceSteps), et->etIndex- 1 );
590 if ( ! ts )
591 { LXDEB(et->etIndex,ts); return -1; }
592
593 et->etThisStep.tsTraceOffset= ts->tsTraceOffset+ ts->tsByteCount;
594 }
595
596 eo->eoTraceStream= sioOutFdOpenAt( et->etTraceFileHandle,
597 et->etThisStep.tsTraceOffset );
598 if ( ! eo->eoTraceStream )
599 { XDEB(eo->eoTraceStream); return -1; }
600 eo->eoTraceWriter= docRtfOpenWriter( eo->eoTraceStream,
601 eo->eoDocument, flags );
602 if ( ! eo->eoTraceWriter )
603 { XDEB(eo->eoTraceWriter); return -1; }
604
605 /* 1 */
606 docRtfWriteDestinationBegin( eo->eoTraceWriter, tag );
607
608 return 0;
609 }
610
docTraceStartStep(EditOperation * eo,EditTrace * et,int command,int fieldKind)611 int docTraceStartStep( EditOperation * eo,
612 EditTrace * et,
613 int command,
614 int fieldKind )
615 {
616 if ( docTraceStartStepLow( eo, et, command, fieldKind ) )
617 { LDEB(command); return -1; }
618
619 /* 2 */
620 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_OTT,
621 eo->eoSelectionScope.ssTreeType );
622 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_OSN,
623 eo->eoSelectionScope.ssSectNr );
624 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_OOSN,
625 eo->eoSelectionScope.ssOwnerSectNr );
626 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_OON,
627 eo->eoSelectionScope.ssOwnerNumber );
628
629 /* 3 */
630 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_OHP,
631 eo->eoSelectedRange.erHead.epParaNr );
632 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_OHS,
633 eo->eoSelectedRange.erHead.epStroff );
634 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_OTP,
635 eo->eoSelectedRange.erTail.epParaNr );
636 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_OTS,
637 eo->eoSelectedRange.erTail.epStroff );
638
639 if ( eo->eoCol0 >= 0 )
640 {
641 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_OHC, eo->eoCol0 );
642 }
643
644 if ( eo->eoCol1 >= 0 )
645 {
646 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_OTC, eo->eoCol1 );
647 }
648
649 return 0;
650 }
651
docTraceStartReplace(DocumentSelection * dsTraced,EditOperation * eo,EditTrace * et,int command,int level,unsigned int flags)652 int docTraceStartReplace( DocumentSelection * dsTraced,
653 EditOperation * eo,
654 EditTrace * et,
655 int command,
656 int level,
657 unsigned int flags )
658 {
659 if ( docTraceStartStep( eo, et, command, -1 ) )
660 { LDEB(1); return -1; }
661
662 if ( docRtfTraceOldContents( dsTraced, eo, level, flags ) )
663 { LDEB(1); return -1; }
664
665 return 0;
666 }
667
668 /************************************************************************/
669 /* */
670 /* Extend a replace. */
671 /* */
672 /* Replacements start with a regular replace step. If the user */
673 /* continues to type at the end of the replacement, the replace is */
674 /* extended. As long as the user types 'the same word', the extent is */
675 /* replaced with an extent that holds the whole extent. */
676 /* */
677 /************************************************************************/
678
docTraceExtendReplace(EditOperation * eo,EditTrace * et,int command,int level,unsigned int flags)679 int docTraceExtendReplace( EditOperation * eo,
680 EditTrace * et,
681 int command,
682 int level,
683 unsigned int flags )
684 {
685 int rval= 0;
686 const TraceStep * ts;
687
688 const int fieldKind= -1;
689
690 if ( et->etIndex < 1 )
691 { LDEB(et->etIndex); return -1; }
692
693 ts= (const TraceStep *)utilPagedListGetItemByNumber(
694 &(et->etTraceSteps), et->etIndex- 1 );
695 if ( ! ts )
696 { LXDEB(et->etIndex,ts); return -1; }
697
698 switch( ts->tsCommand )
699 {
700 case EDITcmdREPLACE:
701 break;
702
703 case EDITcmdEXTEND_REPLACE:
704 if ( et->etIndex < 2 )
705 { LLDEB(ts->tsCommand,et->etIndex); return -1; }
706 et->etIndex--;
707 break;
708
709 default:
710 LLDEB(command,ts->tsCommand); return -1;
711 }
712
713 if ( docTraceStartStepLow( eo, et, command, fieldKind ) )
714 { LDEB(1); return -1; }
715
716 return rval;
717 }
718
719 /************************************************************************/
720 /* */
721 /* Remember the old/new field instructions of a field. */
722 /* */
723 /************************************************************************/
724
docRtfTraceFieldImpl(EditOperation * eo,const DocumentField * df,const char * tag)725 static int docRtfTraceFieldImpl( EditOperation * eo,
726 const DocumentField * df,
727 const char * tag )
728 {
729 RtfWriter * rw= eo->eoTraceWriter;
730
731 DocumentSelection dsInsideField;
732 DocumentSelection dsAroundField;
733
734 int headPart;
735 int tailPart;
736
737 if ( docDelimitFieldInDoc( &dsInsideField, &dsAroundField,
738 &headPart, &tailPart, eo->eoDocument, df ) )
739 { LDEB(1); return -1; }
740
741 docRtfWriteNextLine( rw );
742 docRtfWriteDestinationBegin( rw, tag );
743
744 docRtfWriteTag( rw, RTFtag_pard );
745 docRtfWriteTag( rw, RTFtag_plain );
746 docRtfSaveFieldHead( rw, dsAroundField.dsHead.dpNode, headPart );
747 docRtfWriteRawBytes( rw, " ", 1 );
748 docRtfSaveFieldTail( rw, dsAroundField.dsTail.dpNode, tailPart );
749 docRtfWriteTag( rw, RTFtag_par );
750
751 docRtfWriteDestinationEnd( rw );
752
753 return 0;
754 }
755
docRtfTraceFieldKind(EditOperation * eo,int kind)756 int docRtfTraceFieldKind( EditOperation * eo,
757 int kind )
758
759 {
760 docRtfWriteArgTag( eo->eoTraceWriter, RTFtag_FLK, kind );
761 return 0;
762 }
763
docRtfTraceOldField(EditOperation * eo,const DocumentField * df)764 int docRtfTraceOldField( EditOperation * eo,
765 const DocumentField * df )
766
767 {
768 docRtfTraceFieldKind( eo, df->dfKind );
769
770 return docRtfTraceFieldImpl( eo, df, RTFtag_OTX );
771 }
772
docRtfTraceNewField(EditOperation * eo,const DocumentField * df)773 int docRtfTraceNewField( EditOperation * eo,
774 const DocumentField * df )
775 { return docRtfTraceFieldImpl( eo, df, RTFtag_NTX ); }
776
777 /************************************************************************/
778 /* */
779 /* Finish a trace step. */
780 /* */
781 /************************************************************************/
782
docRtfTraceCloseTrace(EditOperation * eo,EditTrace * et)783 int docRtfTraceCloseTrace( EditOperation * eo,
784 EditTrace * et )
785 {
786 TraceStep * ts= (TraceStep *)0;
787
788 docRtfWriteDestinationEnd( eo->eoTraceWriter );
789 docRtfWriteNextLine( eo->eoTraceWriter );
790
791 docRtfCloseWriter( eo->eoTraceWriter );
792 eo->eoTraceWriter= (RtfWriter *)0;
793
794 et->etThisStep.tsByteCount= sioOutGetBytesWritten( eo->eoTraceStream );
795
796 sioOutClose( eo->eoTraceStream );
797 eo->eoTraceStream= (SimpleOutputStream *)0;
798
799 ts= utilPagedListClaimItem( &(et->etTraceSteps), et->etIndex );
800 if ( ! ts )
801 { LXDEB(et->etIndex,ts); return -1; }
802 et->etIndex++;
803 et->etCount++;
804
805 *ts= et->etThisStep;
806
807 utilPagedListSetSize( &(et->etTraceSteps), et->etCount );
808
809 return 0;
810 }
811
812 /************************************************************************/
813 /* */
814 /* Start a trace: Store the digest and the current date and time. */
815 /* */
816 /************************************************************************/
817
docRtfTraceVersion(int command,const MemoryBuffer * filename,const char * digest64,const struct tm * revtim,EditTrace * et)818 int docRtfTraceVersion( int command,
819 const MemoryBuffer * filename,
820 const char * digest64,
821 const struct tm * revtim,
822 EditTrace * et )
823 {
824 int rval= 0;
825
826 EditOperation eo;
827 RtfWriter * rw;
828
829 const int fieldKind= -1;
830 const int addSemicolon= 0;
831
832 docInitEditOperation( &eo );
833
834 if ( docTraceStartStepLow( &eo, et, command, fieldKind ) )
835 { LDEB(command); rval= -1; goto ready; }
836
837 rw= eo.eoTraceWriter;
838
839 /* HACK: Must go to the props.. not the document */
840 docRtfWriteDestinationBegin( rw, RTFtag_NPR );
841
842 docRtfSaveDate( rw, RTFtag_revtim, revtim );
843
844 if ( digest64 )
845 {
846 docRtfWriteDocEncodedStringDestination( rw, RTFtag__generator,
847 digest64, strlen(digest64), addSemicolon );
848 }
849
850 if ( filename && ! utilMemoryBufferIsEmpty( filename ) )
851 {
852 const char * fn= utilMemoryBufferGetString( filename );
853
854 docRtfWriteDocEncodedStringDestination( rw, RTFtag_hlinkbase,
855 fn, strlen(fn), addSemicolon );
856 }
857
858 docRtfWriteDestinationEnd( rw );
859
860 if ( docRtfTraceCloseTrace( &eo, et ) )
861 { LDEB(command); rval= -1; goto ready; }
862
863 ready:
864
865 docCleanEditOperation( &eo );
866
867 return rval;
868 }
869
870