1 # include "tedConfig.h"
2
3 # include <stddef.h>
4 # include <stdio.h>
5 # include <ctype.h>
6
7 # include <sioFileio.h>
8 # include <sioMD5.h>
9 # include <sioMemory.h>
10 # include <utilMD5.h>
11 # include <sioStdin.h>
12 # include <sioFd.h>
13 # include <appSystem.h>
14 # include <textOfficeCharset.h>
15 # include <geoUnits.h>
16 # include <appQuestion.h>
17
18 # include "tedApp.h"
19 # include "tedRuler.h"
20 # include "tedAppResources.h"
21 # include "tedDocument.h"
22 # include "tedDocFront.h"
23
24 # include <docDebug.h>
25 # include <docRtfReadWrite.h>
26 # include <docPlainReadWrite.h>
27 # include <utilMemoryBufferPrintf.h>
28 # include <docRtfFlags.h>
29
30 # include <guiDrawingWidget.h>
31 # include <docEditCommand.h>
32 # include <docRtfTrace.h>
33 # include <utilMatchFont.h>
34
35 # include <appDebugon.h>
36
37 /************************************************************************/
38
tedSetGenerator(DocumentProperties * dp,const EditApplication * ea)39 static int tedSetGenerator( DocumentProperties * dp,
40 const EditApplication * ea )
41 {
42 utilMemoryBufferPrintf( &(dp->dpGeneratorWrite),
43 "%s (%s);", ea->eaNameAndVersion, ea->eaReference );
44
45 return 0;
46 }
47
48 /************************************************************************/
49
tedSetDocumentDefaults(TedDocument * td,EditApplication * ea)50 static int tedSetDocumentDefaults( TedDocument * td,
51 EditApplication * ea )
52 {
53 TedAppResources * tar= (TedAppResources *)ea->eaResourceData;
54 double pixPerMM;
55
56
57 td->tdPixelsPerTwip= ea->eaMagnification* ea->eaPixelsPerTwip;
58 pixPerMM= TWIPS_PER_MM* td->tdPixelsPerTwip;
59 td->tdPageGapPixels= pixPerMM* tar->tarPageGapMM;
60
61 /* 2 */
62 if ( appPostScriptFontCatalog( ea ) )
63 { SDEB(ea->eaAfmDirectory); return -1; }
64
65 return 0;
66 }
67
68 /************************************************************************/
69
tedMakeDocument(EditApplication * ea)70 static BufferDocument * tedMakeDocument( EditApplication * ea )
71 {
72 const PostScriptFontList * psfl= (const PostScriptFontList *)0;
73 BufferDocument * bd= (BufferDocument *)0;
74 DocumentProperties * dp;
75
76 TextAttribute ta;
77 time_t now;
78
79 if ( ea->eaPreferBase35FontsInt <= 0 )
80 { psfl= &(ea->eaPostScriptFontList); }
81
82 bd= docNewFile( &ta, "Helvetica", 2* 12, psfl,
83 &(ea->eaDefaultDocumentGeometry) );
84 if ( ! bd )
85 { XDEB(bd); return (BufferDocument *)0; }
86
87 dp= &(bd->bdProperties);
88
89 tedSetGenerator( dp, ea );
90
91 if ( ea->eaAuthor )
92 {
93 if ( utilMemoryBufferSetString( &(dp->dpAuthor), ea->eaAuthor ) )
94 { LDEB(1); docFreeDocument( bd ); return (BufferDocument *)0; }
95 }
96
97 now= time( (time_t *)0 );
98 dp->dpCreatim= *localtime( &now );
99 dp->dpRevtim= dp->dpCreatim;
100
101 return bd;
102 }
103
104 /************************************************************************/
105 /* */
106 /* Make a new empty document. */
107 /* */
108 /************************************************************************/
109
tedNewDocument(EditDocument * ed,const MemoryBuffer * filename)110 int tedNewDocument( EditDocument * ed,
111 const MemoryBuffer * filename )
112 {
113 int rval= 0;
114 TedDocument * td= (TedDocument *)ed->edPrivateData;
115 EditTrace * et= &(td->tdEditTrace);
116 BufferDocument * bd;
117
118 EditApplication * ea= ed->edApplication;
119 TedAppResources * tar= (TedAppResources *)ea->eaResourceData;
120 int traced;
121
122 int fdTrace= FDerrOTHER;
123
124 MemoryBuffer ext;
125
126 if ( filename && utilMemoryBufferIsEmpty( filename ) )
127 { filename= (const MemoryBuffer *)0; }
128
129 utilInitMemoryBuffer( &ext );
130
131 tedDetermineDefaultSettings( tar );
132
133 traced= tar->tarTraceEditsInt > 0;
134
135 if ( tedSetDocumentDefaults( td, ea ) )
136 { LDEB(1); rval= -1; goto ready; }
137
138 bd= tedMakeDocument( ea );
139 if ( ! bd )
140 { XDEB(bd); rval= -1; goto ready; }
141
142 ed->edFormat= TEDdockindRTF; /* rtf */
143 td->tdDocument= bd;
144
145 if ( filename )
146 {
147 if ( appFileGetFileExtension( &ext, filename ) )
148 { LDEB(1); rval= -1; goto ready; }
149
150 if ( utilMemoryBufferEqualsString( &ext, "rtf" ) )
151 { ed->edFormat= TEDdockindRTF; }
152 if ( utilMemoryBufferEqualsString( &ext, "txt" ) )
153 { ed->edFormat= TEDdockindTEXT_SAVE_FOLDED; }
154
155 if ( traced )
156 {
157 fdTrace= docEditTraceTryRelative( et, filename, TedTraceExtension );
158
159 if ( fdTrace < 0 )
160 { LDEB(fdTrace); rval= -1; goto ready; }
161 }
162 }
163 else{
164 if ( traced )
165 {
166 fdTrace= docEditTraceTryAnon( et, TedTraceExtension );
167 if ( fdTrace < 0 )
168 { LDEB(fdTrace); rval= -1; goto ready; }
169 }
170 }
171
172 if ( docEditIsTraced( et->etTraceStatus ) )
173 {
174 const DocumentProperties * dp= &(td->tdDocument->bdProperties);
175
176 if ( docRtfTraceVersion( EDITcmd_NEW, filename,
177 (char *)0, &(dp->dpRevtim), et ) )
178 { LDEB(1); rval= -1; goto ready; }
179
180 et->etBase= et->etIndex- 1;
181 td->tdTraced= 1;
182 }
183 else{ td->tdTraced= 0; }
184
185 ready:
186
187 utilCleanMemoryBuffer( &ext );
188
189 return rval;
190 }
191
192 /************************************************************************/
193
tedTryRtfStdin(int * pFormat,EditApplication * ea)194 static BufferDocument * tedTryRtfStdin( int * pFormat,
195 EditApplication * ea )
196 {
197 TedAppResources * tar= (TedAppResources *)ea->eaResourceData;
198 BufferDocument * bd;
199
200 unsigned int rtfFlags= 0;
201
202 SimpleInputStream * sis= sioInStdinOpen();
203 if ( ! sis )
204 { XDEB(sis); return (BufferDocument *)0; }
205
206 if ( tar->tarLenientRtfInt > 0 )
207 { rtfFlags |= RTFflagLENIENT; }
208
209 bd= docRtfReadFile( sis, rtfFlags );
210 sioInClose( sis );
211 if ( ! bd )
212 { XDEB(bd); return (BufferDocument *)0; }
213
214 tedSetGenerator( &(bd->bdProperties), ea );
215
216 *pFormat= TEDdockindRTF;
217 return bd;
218 }
219
tedTryTxtStdin(int * pFormat,EditApplication * ea)220 static BufferDocument * tedTryTxtStdin( int * pFormat,
221 EditApplication * ea )
222 {
223 BufferDocument * bd;
224 int longestPara;
225
226 SimpleInputStream * sis= sioInStdinOpen();
227 if ( ! sis )
228 { XDEB(sis); return (BufferDocument *)0; }
229
230 bd= docPlainReadFile( sis, &longestPara, &(ea->eaDefaultDocumentGeometry) );
231 sioInClose( sis );
232 if ( ! bd )
233 { XDEB(bd); return (BufferDocument *)0; }
234
235 tedSetGenerator( &(bd->bdProperties), ea );
236
237 if ( longestPara > 76 )
238 { *pFormat= TEDdockindTEXT_SAVE_WIDE; }
239 else{ *pFormat= TEDdockindTEXT_SAVE_FOLDED; }
240
241 return bd;
242 }
243
tedTryRtfFile(unsigned char * digest,int * pFormat,int * pFailedFile,EditApplication * ea,const MemoryBuffer * filename,int complain,APP_WIDGET relative,APP_WIDGET option)244 static BufferDocument * tedTryRtfFile( unsigned char * digest,
245 int * pFormat,
246 int * pFailedFile,
247 EditApplication * ea,
248 const MemoryBuffer * filename,
249 int complain,
250 APP_WIDGET relative,
251 APP_WIDGET option )
252 {
253 TedAppResources * tar= (TedAppResources *)ea->eaResourceData;
254 BufferDocument * bd= (BufferDocument *)0;
255
256 unsigned int rtfFlags= 0;
257
258 SimpleInputStream * sisFile= (SimpleInputStream *)0;
259 SimpleInputStream * sisMD5= (SimpleInputStream *)0;
260
261 if ( tar->tarLenientRtfInt > 0 )
262 { rtfFlags |= RTFflagLENIENT; }
263
264 sisFile= sioInFileioOpen( filename );
265 if ( ! sisFile )
266 {
267 AppFileMessageResources * afmr= &(ea->eaFileMessageResources);
268
269 if ( complain )
270 {
271 appQuestionRunFilenameErrorDialog( ea, relative, option,
272 filename, afmr->afmrFileNoAccess );
273 XDEB(sisFile);
274 }
275
276 *pFailedFile= 1; goto ready;
277 }
278
279 if ( digest )
280 {
281 sisMD5= sioInMD5Open( digest, sisFile );
282 if ( ! sisMD5 )
283 { XDEB(sisMD5); goto ready; }
284
285 bd= docRtfReadFile( sisMD5, rtfFlags );
286 }
287 else{
288 bd= docRtfReadFile( sisFile, rtfFlags );
289 }
290
291 if ( ! bd )
292 {
293 int resp;
294
295 resp= appQuestionRunFilenameOkCancelDialog( ea, relative, option,
296 filename, tar->tarFileNotRtf );
297
298 if ( resp != AQDrespOK )
299 { *pFailedFile= 1; }
300
301 goto ready;
302 }
303
304 if ( docPropertiesSetFilename( &(bd->bdProperties), filename ) )
305 { LDEB(1); }
306
307 tedSetGenerator( &(bd->bdProperties), ea );
308
309 if ( pFormat )
310 { *pFormat= TEDdockindRTF; }
311
312 if ( tar->tarOverridePaperSizeInt > 0 )
313 { docOverridePaperSize( bd, &(ea->eaDefaultDocumentGeometry) ); }
314
315 ready:
316
317 if ( sisMD5 )
318 { sioInClose( sisMD5 ); }
319 if ( sisFile )
320 { sioInClose( sisFile ); }
321
322 return bd;
323 }
324
tedTryTxtFile(unsigned char * digest,int * pFormat,int * pFailedFile,EditApplication * ea,const MemoryBuffer * filename,int complain,APP_WIDGET relative,APP_WIDGET option)325 static BufferDocument * tedTryTxtFile( unsigned char * digest,
326 int * pFormat,
327 int * pFailedFile,
328 EditApplication * ea,
329 const MemoryBuffer * filename,
330 int complain,
331 APP_WIDGET relative,
332 APP_WIDGET option )
333 {
334 BufferDocument * bd= (BufferDocument *)0;
335 int longestPara;
336
337 SimpleInputStream * sisFile= (SimpleInputStream *)0;
338 SimpleInputStream * sisMD5= (SimpleInputStream *)0;
339
340 sisFile= sioInFileioOpen( filename );
341 if ( ! sisFile )
342 {
343 AppFileMessageResources * afmr= &(ea->eaFileMessageResources);
344
345 if ( complain )
346 {
347 appQuestionRunFilenameErrorDialog( ea, relative, option,
348 filename, afmr->afmrFileNoAccess );
349 XDEB(sisFile);
350 }
351
352 *pFailedFile= 1; goto ready;
353 }
354
355 if ( digest )
356 {
357 sisMD5= sioInMD5Open( digest, sisFile );
358 if ( ! sisMD5 )
359 { XDEB(sisMD5); goto ready; }
360
361 bd= docPlainReadFile( sisMD5, &longestPara,
362 &(ea->eaDefaultDocumentGeometry) );
363 }
364 else{
365 bd= docPlainReadFile( sisFile, &longestPara,
366 &(ea->eaDefaultDocumentGeometry) );
367 }
368
369 if ( ! bd )
370 { XDEB(bd); goto ready; }
371
372 if ( docPropertiesSetFilename( &(bd->bdProperties), filename ) )
373 { LDEB(1); }
374
375 tedSetGenerator( &(bd->bdProperties), ea );
376
377 if ( pFormat )
378 {
379 if ( longestPara > 76 )
380 { *pFormat= TEDdockindTEXT_SAVE_WIDE; }
381 else{ *pFormat= TEDdockindTEXT_SAVE_FOLDED; }
382 }
383
384 ready:
385
386 if ( sisMD5 )
387 { sioInClose( sisMD5 ); }
388 if ( sisFile )
389 { sioInClose( sisFile ); }
390
391 return bd;
392 }
393
394 /************************************************************************/
395 /* */
396 /* Open a document. */
397 /* */
398 /* 1) Open an input stream. */
399 /* 2) Try to read as RTF. */
400 /* 3) If this fails, try as plain text. */
401 /* */
402 /************************************************************************/
403
tedOpenDocumentFile(unsigned char * digest,int * pFormat,BufferDocument ** pBd,EditApplication * ea,int suggestStdin,int formatHint,const MemoryBuffer * filename,int complain,APP_WIDGET relative,APP_WIDGET option)404 int tedOpenDocumentFile( unsigned char * digest,
405 int * pFormat,
406 BufferDocument ** pBd,
407 EditApplication * ea,
408 int suggestStdin,
409 int formatHint,
410 const MemoryBuffer * filename,
411 int complain,
412 APP_WIDGET relative,
413 APP_WIDGET option )
414 {
415 int rval= 0;
416
417 BufferDocument * bd= (BufferDocument *)0;
418 int format= -1;
419
420 int failedFile= 0;
421 int triedRtf= 0;
422 int triedTxt= 0;
423
424 TedAppResources * tar= (TedAppResources *)ea->eaResourceData;
425
426 tedDetermineDefaultSettings( tar );
427
428 if ( appPostScriptFontCatalog( ea ) )
429 { SDEB(ea->eaAfmDirectory); rval= -1; goto ready; }
430
431 if ( ! bd && suggestStdin && formatHint == TEDdockindRTF )
432 {
433 bd= tedTryRtfStdin( &format, ea );
434 if ( ! bd )
435 { XDEB(bd); rval= -1; goto ready; }
436 }
437
438 if ( ! bd && suggestStdin && formatHint == TEDdockindTEXT_OPEN )
439 {
440 bd= tedTryTxtStdin( &format, ea );
441 if ( ! bd )
442 { XDEB(bd); rval= -1; goto ready; }
443 }
444
445 if ( ! bd && suggestStdin )
446 { XLDEB(bd,suggestStdin); rval= -1; goto ready; }
447
448 if ( ! bd && formatHint == TEDdockindRTF )
449 {
450 /* 1 */
451 bd= tedTryRtfFile( digest, &format, &failedFile,
452 ea, filename, complain, relative, option );
453 if ( ! bd )
454 {
455 if ( failedFile )
456 { rval= -1; goto ready; }
457 }
458
459 triedRtf= 1;
460 }
461
462 if ( ! bd && formatHint == TEDdockindTEXT_OPEN )
463 {
464 bd= tedTryTxtFile( digest, &format, &failedFile,
465 ea, filename, complain, relative, option );
466 if ( failedFile )
467 { rval= -1; goto ready; }
468
469 triedTxt= 1;
470 }
471
472 /* 2 */
473 if ( ! bd && ! triedRtf )
474 {
475 bd= tedTryRtfFile( digest, &format, &failedFile,
476 ea, filename, complain, relative, option );
477 if ( ! bd )
478 {
479 if ( failedFile )
480 { rval= -1; goto ready; }
481 }
482
483 triedRtf= 1;
484 }
485
486 if ( ! bd && ! triedTxt )
487 {
488 bd= tedTryTxtFile( digest, &format, &failedFile,
489 ea, filename, complain, relative, option );
490 if ( failedFile )
491 { rval= -1; goto ready; }
492
493 triedTxt= 1;
494 }
495
496 if ( ! bd )
497 { XDEB(bd); rval= -1; goto ready; }
498
499 *pBd= bd; *pFormat= format;
500
501 ready:
502
503 return rval;
504 }
505
506 /************************************************************************/
507 /* */
508 /* Find the last editing command and the (last) position in the trace */
509 /* where the current version of the document was saved. */
510 /* */
511 /************************************************************************/
512
513 typedef struct FindDigest
514 {
515 int fdBase;
516 int fdLastEdit;
517 int fdFormat;
518 EditTrace * fdEditTrace;
519 EditApplication * fdApplication;
520 MemoryBuffer fdDocumentName;
521 BufferDocument * fdDocument;
522 } FindDigest;
523
tedInitFindDigest(FindDigest * fd)524 static void tedInitFindDigest( FindDigest * fd )
525 {
526 fd->fdBase= -1;
527 fd->fdLastEdit= -1;
528 fd->fdFormat= -1;
529 fd->fdEditTrace= (EditTrace *)0;
530 fd->fdApplication= (EditApplication *)0;
531
532 utilInitMemoryBuffer( &(fd->fdDocumentName) );
533
534 fd->fdDocument= (BufferDocument *)0;
535 }
536
tedCleanFindDigest(FindDigest * fd)537 static void tedCleanFindDigest( FindDigest * fd )
538 {
539 utilCleanMemoryBuffer( &(fd->fdDocumentName) );
540
541 if ( fd->fdDocument )
542 { docFreeDocument( fd->fdDocument ); }
543 }
544
tedFindDigest(const TraceStep * ts,const EditStep * es,int step,void * voidfd)545 static int tedFindDigest( const TraceStep * ts,
546 const EditStep * es,
547 int step,
548 void * voidfd )
549 {
550 FindDigest * fd= (FindDigest *)voidfd;
551
552 if ( es->esCommand < EDITcmd_EDIT_COUNT &&
553 es->esCommand != EDITcmdEXTEND_REPLACE )
554 { fd->fdLastEdit= step; }
555
556 if ( es->esCommand != EDITcmd_OPEN &&
557 es->esCommand != EDITcmd_SAVE )
558 { return 0; }
559
560 if ( utilMemoryBufferEqualsString( &(es->esNewDocProps.dpGeneratorRead),
561 fd->fdEditTrace->etBaseMD5Digest64 ) )
562 { fd->fdBase= step; /* NO: look for the last one return 1; */ }
563
564 return 0;
565 }
566
567 /************************************************************************/
568 /* */
569 /* Remember a step in the trace. Look for the last save as well. */
570 /* */
571 /************************************************************************/
572
tedRemebmerTraceStep(const TraceStep * ts,const EditStep * es,int step,void * voidfd)573 static int tedRemebmerTraceStep( const TraceStep * ts,
574 const EditStep * es,
575 int step,
576 void * voidfd )
577 {
578 FindDigest * fd= (FindDigest *)voidfd;
579 TraceStep * tsNew;
580
581 if ( tedFindDigest( ts, es, step, voidfd ) < 0 )
582 { LDEB(step); return -1; }
583
584 tsNew= utilPagedListClaimItem( &(fd->fdEditTrace->etTraceSteps), step );
585 if ( ! tsNew )
586 { LXDEB(step,tsNew); return -1; }
587
588 *tsNew= *ts;
589
590 return 0;
591 }
592
593 /************************************************************************/
594 /* */
595 /* Scan (and record) the trace and look for the last version that */
596 /* still exists on the file system. */
597 /* */
598 /************************************************************************/
599
tedFindDocument(const TraceStep * ts,const EditStep * es,int step,void * voidfd)600 static int tedFindDocument( const TraceStep * ts,
601 const EditStep * es,
602 int step,
603 void * voidfd )
604 {
605 int rval= 0;
606 BufferDocument * bd= (BufferDocument *)0;
607 FindDigest * fd= (FindDigest *)voidfd;
608
609 unsigned char digest[MD5_DIGEST_SIZE_BYTES];
610
611 if ( tedRemebmerTraceStep( ts, es, step, voidfd ) < 0 )
612 { LDEB(step); return -1; }
613
614 if ( es->esCommand == EDITcmd_NEW )
615 {
616 bd= tedMakeDocument( fd->fdApplication );
617 if ( ! bd )
618 { XDEB(bd); rval= -1; goto ready; }
619
620 if ( fd->fdDocument )
621 { docFreeDocument( fd->fdDocument ); }
622
623 fd->fdDocument= bd; bd= (BufferDocument *)0; /* steal */
624 fd->fdBase= step;
625 }
626
627 if ( es->esCommand == EDITcmd_OPEN ||
628 es->esCommand == EDITcmd_SAVE )
629 {
630 const int complain= 0;
631 const int suggestStdin= 0;
632 int format= -1;
633
634 EditApplication * ea= fd->fdApplication;
635 const MemoryBuffer * filename= &(es->esNewDocProps.dpHlinkbase);
636
637 format= appDocumentGetOpenFormat( (int *)0,
638 ea->eaFileExtensions, ea->eaFileExtensionCount,
639 filename, format );
640
641 if ( ! tedOpenDocumentFile( digest, &format, &bd, ea,
642 suggestStdin, format, filename,
643 complain, (APP_WIDGET)0, (APP_WIDGET)0 ) )
644 {
645 char digest64[MD5_DIGEST_SIZE_BASE64];
646
647 utilMD5ToBase64( digest64, digest );
648
649 if ( utilMemoryBufferEqualsString(
650 &(es->esNewDocProps.dpGeneratorRead), digest64 ) )
651 {
652 if ( utilCopyMemoryBuffer( &(fd->fdDocumentName), filename ) )
653 { LDEB(1); rval= -1; goto ready; }
654
655 if ( fd->fdDocument )
656 { docFreeDocument( fd->fdDocument ); }
657
658 fd->fdDocument= bd; bd= (BufferDocument *)0; /* steal */
659 fd->fdBase= step;
660 fd->fdFormat= format;
661 }
662 }
663 }
664
665 ready:
666
667 if ( bd )
668 { docFreeDocument( bd ); }
669
670 return rval;
671 }
672
673 /************************************************************************/
674 /* */
675 /* Scan the trace to find the base version of the document. If we */
676 /* encounter a problem, simply report that no base version can be */
677 /* found. Failing on a defective trace would make it impossible to */
678 /* unlock the document by discarding it. */
679 /* */
680 /************************************************************************/
681
tedFindBaseVersion(EditApplication * ea,TedDocument * td)682 static int tedFindBaseVersion( EditApplication * ea,
683 TedDocument * td )
684 {
685 int rval= 0;
686
687 EditTrace * et= &(td->tdEditTrace);
688 SimpleInputStream * sisTrace= (SimpleInputStream *)0;
689
690 const int readOld= 0;
691 const int readNew= 0;
692
693 FindDigest fd;
694
695 tedInitFindDigest( &fd );
696
697 fd.fdEditTrace= et;
698 fd.fdApplication= ea;
699
700 sisTrace= sioInFileioOpen( &(et->etTraceFileName) );
701 if ( ! sisTrace )
702 { XDEB(sisTrace); rval= -1; goto ready; }
703
704 if ( docRtfScanEditTrace( et, sisTrace, tedFindDigest, (void *)&fd,
705 readOld, readNew, td->tdDocument ) )
706 { LDEB(1); fd.fdBase= -1; }
707
708 sioInClose( sisTrace ); sisTrace= (SimpleInputStream *)0;
709
710 if ( fd.fdBase >= 0 )
711 { et->etBase= fd.fdBase; }
712
713 ready:
714
715 if ( sisTrace )
716 { sioInClose( sisTrace ); }
717
718 tedCleanFindDigest( &fd );
719
720 return rval;
721 }
722
723 /************************************************************************/
724
tedOpenTraceFile(EditApplication * ea,TedDocument * td,int * pFormat,const MemoryBuffer * filename)725 static int tedOpenTraceFile( EditApplication * ea,
726 TedDocument * td,
727 int * pFormat,
728 const MemoryBuffer * filename )
729 {
730 int rval= 0;
731
732 EditTrace * et= &(td->tdEditTrace);
733 SimpleInputStream * sisTrace= (SimpleInputStream *)0;
734
735 const int read= 1;
736 const int write= 1;
737 const int append= 0;
738 const int create= 0;
739 const int exclusive= 0;
740
741 const int readOld= 0;
742 const int readNew= 0;
743
744 int fdTrace= FDerrOTHER;
745 FindDigest fd;
746
747 MemoryBuffer mbScratch;
748
749 TedAppResources * tar= (TedAppResources *)ea->eaResourceData;
750
751 utilInitMemoryBuffer( &mbScratch );
752 tedInitFindDigest( &fd );
753
754 fdTrace= sioFdOpenFile( filename, read, write, append, create, exclusive );
755 if ( fdTrace < 0 )
756 { LDEB(fdTrace); rval= -1; goto ready; }
757
758 fd.fdEditTrace= et;
759 fd.fdApplication= ea;
760
761 sisTrace= sioInFileioOpen( filename );
762 if ( ! sisTrace )
763 { XDEB(sisTrace); rval= -1; goto ready; }
764
765 if ( docRtfScanEditTrace( et, sisTrace, tedFindDocument, (void *)&fd,
766 readOld, readNew, (BufferDocument *)0 ) )
767 { LDEB(1); rval= -1; goto ready; }
768
769 sioInClose( sisTrace ); sisTrace= (SimpleInputStream *)0;
770
771 if ( fd.fdBase >= 0 && fd.fdDocument )
772 {
773 if ( utilCopyMemoryBuffer( &(et->etTraceFileName), filename ) )
774 { LDEB(1); rval= -1; goto ready; }
775 if ( utilCopyMemoryBuffer( &(td->tdRecoveredName),
776 &(fd.fdDocumentName) ) )
777 { LDEB(1); rval= -1; goto ready; }
778
779 et->etTraceFileHandle= fdTrace; fdTrace= FDerrOTHER;
780 et->etCount= et->etTraceSteps.plItemCount;
781 et->etIndex= et->etBase= fd.fdBase;
782 et->etIsRecovery= 1;
783
784 /* steal */
785 td->tdDocument= fd.fdDocument; fd.fdDocument= (BufferDocument *)0;
786 *pFormat= fd.fdFormat;
787 }
788 else{
789 int longestPara;
790
791 if ( utilMemoryBufferSetString( &mbScratch, tar->tarCannotRecover ) )
792 { LDEB(1); rval= -1; goto ready; }
793
794 sisTrace= sioInMemoryOpen( &mbScratch );
795 if ( ! sisTrace )
796 { XDEB(sisTrace); rval= -1; goto ready; }
797
798 td->tdDocument= docPlainReadFile( sisTrace, &longestPara,
799 &(ea->eaDefaultDocumentGeometry) );
800 sioInClose( sisTrace ); sisTrace= (SimpleInputStream *)0;
801 if ( ! td->tdDocument )
802 { XDEB(td->tdDocument); rval= -1; goto ready; }
803
804 tedSetGenerator( &(td->tdDocument->bdProperties), ea );
805
806 *pFormat= TEDdockindTRACE;
807 et->etTraceStatus= TRACING_EXIST;
808 }
809
810 ready:
811
812 if ( sisTrace )
813 { sioInClose( sisTrace ); }
814 if ( fdTrace >= 0 )
815 { sioFdCloseFile( fdTrace ); }
816
817 tedCleanFindDigest( &fd );
818
819 utilCleanMemoryBuffer( &mbScratch );
820
821 return rval;
822 }
823
824 /************************************************************************/
825 /* */
826 /* Open a document. */
827 /* */
828 /* 1) Read the file. */
829 /* 1b) Forget the name of document templates to force a save-as. */
830 /* Also forget it is a template, to make sure that it is saved as */
831 /* an ordinary document. */
832 /* 2) Get the list of fonts that are available on the machine. */
833 /* 3) Add them to the font list of the document. */
834 /* */
835 /************************************************************************/
836
tedOpenDocument(EditApplication * ea,void * voidtd,int * pFormat,APP_WIDGET relative,APP_WIDGET option,const int readOnly,const int suggestStdin,const int formatHint,const MemoryBuffer * filename)837 int tedOpenDocument( EditApplication * ea,
838 void * voidtd,
839 int * pFormat,
840 APP_WIDGET relative,
841 APP_WIDGET option,
842 const int readOnly,
843 const int suggestStdin,
844 const int formatHint,
845 const MemoryBuffer * filename )
846 {
847 int rval= 0;
848 TedDocument * td= (TedDocument *)voidtd;
849 EditTrace * et= &(td->tdEditTrace);
850
851 TedAppResources * tar= (TedAppResources *)ea->eaResourceData;
852
853 unsigned char digest_x[MD5_DIGEST_SIZE_BYTES];
854 unsigned char * digest= (unsigned char *)0;
855
856 const int complain= 1;
857 int traced;
858
859 MemoryBuffer ext;
860
861 utilInitMemoryBuffer( &ext );
862
863 tedDetermineDefaultSettings( tar );
864
865 traced= tar->tarTraceEditsInt > 0;
866
867 if ( appFileGetFileExtension( &ext, filename ) )
868 { LDEB(1); rval= -1; goto ready; }
869
870 if ( utilMemoryBufferEqualsString( &ext, TedTraceExtension ) )
871 {
872 if ( tedOpenTraceFile( ea, td, pFormat, filename ) )
873 { LDEB(1); rval= -1; goto ready; }
874 }
875 else{
876 if ( traced && ! readOnly )
877 {
878 int fdTrace;
879
880 if ( suggestStdin )
881 {
882 fdTrace= docEditTraceTryAnon( et, TedTraceExtension );
883 if ( fdTrace < 0 )
884 { LDEB(fdTrace); rval= -1; goto ready; }
885 }
886 else{
887 fdTrace= docEditTraceTryRelative( et,
888 filename, TedTraceExtension );
889
890 if ( fdTrace < 0 && et->etTraceStatus == TRACING_NO )
891 { LCDEB(fdTrace,et->etTraceStatus); rval= -1; goto ready; }
892
893 digest= digest_x;
894 }
895 }
896
897 /* 1,2 */
898 if ( tedOpenDocumentFile( digest, pFormat, &(td->tdDocument), ea,
899 suggestStdin, formatHint, filename,
900 complain, relative, option ) )
901 { /*SDEB(filename);*/ rval= -1; goto ready; }
902
903 if ( digest )
904 { utilMD5ToBase64( et->etBaseMD5Digest64, digest ); }
905 }
906
907 tedSetDocumentDefaults( td, ea );
908
909 {
910 DocumentProperties * dp= &(td->tdDocument->bdProperties);
911
912 /* 3 */
913 if ( ea->eaAvoidFontconfigInt <= 0 &&
914 ea->eaPreferBase35FontsInt >= 0 )
915 {
916 if ( utilAddBase35FontsToDocList( dp->dpFontList ) )
917 { LDEB(35); rval= -1; goto ready; }
918 }
919 else{
920 if ( utilAddPsFontsToDocList( dp->dpFontList,
921 &(ea->eaPostScriptFontList) ) )
922 {
923 LDEB(ea->eaPostScriptFontList.psflFamilyCount);
924 rval= -1; goto ready;
925 }
926 }
927 }
928
929 if ( et->etTraceStatus == TRACING_ACCES )
930 {
931 int fdTrace;
932
933 fdTrace= docEditTraceTryTemp( et, TedTraceExtension );
934
935 if ( fdTrace < 0 && et->etTraceStatus == TRACING_NO )
936 { LCDEB(fdTrace,et->etTraceStatus); rval= -1; goto ready; }
937 }
938
939 if ( et->etTraceStatus == TRACING_EXIST && *pFormat != TEDdockindTRACE )
940 {
941 if ( tedFindBaseVersion( ea, td ) )
942 { LDEB(1); rval= -1; goto ready; }
943 }
944
945 if ( docEditIsTraced( et->etTraceStatus ) )
946 {
947 const DocumentProperties * dp= &(td->tdDocument->bdProperties);
948
949 if ( suggestStdin )
950 {
951 if ( docRtfTraceVersion( EDITcmd_NEW, filename,
952 (char *)0, &(dp->dpRevtim), et ) )
953 { XDEB(digest); rval= -1; goto ready; }
954 }
955 else{
956 if ( docRtfTraceVersion( EDITcmd_OPEN, filename,
957 et->etBaseMD5Digest64, &(dp->dpRevtim), et ) )
958 { XDEB(digest); rval= -1; goto ready; }
959 }
960
961 et->etBase= et->etIndex- 1;
962 td->tdTraced= 1;
963 }
964 else{ td->tdTraced= 0; }
965
966 td->tdDocument->bdAutoHyphenate= tar->tarAutoHyphenateInt > 0;
967
968 ready:
969
970 if ( rval )
971 {
972 docCleanEditTrace( et );
973 docInitEditTrace( et );
974 }
975
976 utilCleanMemoryBuffer( &ext );
977
978 return rval;
979 }
980
981 /************************************************************************/
982 /* */
983 /* Recover a document. */
984 /* */
985 /************************************************************************/
986
tedDocRecover(EditDocument * ed)987 int tedDocRecover( EditDocument * ed )
988 {
989 int rval= 0;
990 TedDocument * td= (TedDocument *)ed->edPrivateData;
991 EditTrace * et= &(td->tdEditTrace);
992
993 const int restart= 0;
994 const int exclusive= 0;
995
996 const int readOld= 0;
997 const int readNew= 0;
998
999 SimpleInputStream * sisTrace= (SimpleInputStream *)0;
1000 FindDigest fd;
1001
1002 tedInitFindDigest( &fd );
1003
1004 if ( et->etTraceStatus != TRACING_EXIST )
1005 { CDEB(et->etTraceStatus); return -1; }
1006
1007 if ( docEditTraceOpenTrace( et, restart, exclusive ) < 0 )
1008 { LLDEB(restart,exclusive); rval= -1; goto ready; }
1009
1010 sisTrace= sioInFdOpen( et->etTraceFileHandle );
1011 if ( ! sisTrace )
1012 { LXDEB(et->etTraceFileHandle,sisTrace); rval= -1; goto ready; }
1013
1014 fd.fdEditTrace= et;
1015 fd.fdApplication= ed->edApplication;
1016
1017 if ( docRtfScanEditTrace( et, sisTrace, tedRemebmerTraceStep, (void *)&fd,
1018 readOld, readNew, td->tdDocument ) )
1019 { LDEB(1); rval= -1; goto ready; }
1020
1021 sioInClose( sisTrace ); sisTrace= (SimpleInputStream *)0;
1022
1023 if ( fd.fdBase < 0 )
1024 { LDEB(fd.fdBase); rval= -1; goto ready; }
1025
1026 et->etCount= et->etTraceSteps.plItemCount;
1027 et->etIndex= et->etBase= fd.fdBase;
1028
1029 while( et->etIndex < fd.fdLastEdit )
1030 {
1031 if ( tedDocRepeat( ed ) )
1032 { LLDEB(et->etIndex,fd.fdLastEdit); rval= -1; goto ready; }
1033 }
1034
1035 td->tdTraced= 1;
1036 ed->edIsReadonly= 0;
1037
1038 tedMakeDocumentReadonly( ed, ed->edIsReadonly );
1039 guiShowMenuOption( td->tdFileUnlockOption, 0 );
1040 guiShowMenuOption( td->tdFileRecoverOption, 0 );
1041
1042 tedSetTracedChangedFlag( ed );
1043
1044 tedAdaptToolsToSelection( ed );
1045
1046 ready:
1047
1048 if ( sisTrace )
1049 { sioInClose( sisTrace ); }
1050
1051 tedCleanFindDigest( &fd );
1052
1053 return rval;
1054 }
1055
1056 /************************************************************************/
1057 /* */
1058 /* Unlock a document that cannot be locked. */
1059 /* (Doing so while someone else is editing it is asking for trouble.) */
1060 /* */
1061 /************************************************************************/
1062
tedDocUnlock(EditDocument * ed)1063 int tedDocUnlock( EditDocument * ed )
1064 {
1065 TedDocument * td= (TedDocument *)ed->edPrivateData;
1066 EditTrace * et= &(td->tdEditTrace);
1067
1068 if ( et->etTraceStatus == TRACING_EXIST &&
1069 ed->edFormat == TEDdockindTRACE )
1070 {
1071 if ( appRemoveFile( &(ed->edFilename) ) )
1072 { LDEB(1); return -1; }
1073
1074 appCloseDocument( ed );
1075 return 0;
1076 }
1077
1078 if ( et->etTraceStatus == TRACING_EXIST )
1079 {
1080 const int restart= 1;
1081 const int exclusive= 0;
1082
1083 if ( docEditTraceOpenTrace( &(td->tdEditTrace), restart, exclusive ) )
1084 { LLDEB(restart,exclusive); return -1; }
1085
1086 if ( docRtfTraceVersion( EDITcmd_OPEN, &(ed->edFilename),
1087 et->etBaseMD5Digest64,
1088 &(td->tdDocument->bdProperties.dpRevtim), et ) )
1089 { LDEB(1); return -1; }
1090
1091 td->tdTraced= 1;
1092 et->etBase= et->etIndex- 1;
1093 }
1094 else{
1095 if ( et->etIsRecovery )
1096 { et->etIsRecovery= 0; }
1097 else{
1098 LLDEB(et->etTraceStatus,et->etIsRecovery);
1099 return -1;
1100 }
1101 }
1102
1103 ed->edIsReadonly= 0;
1104
1105 tedMakeDocumentReadonly( ed, ed->edIsReadonly );
1106 guiShowMenuOption( td->tdFileUnlockOption, 0 );
1107 guiShowMenuOption( td->tdFileRecoverOption, 0 );
1108
1109 tedSetTracedChangedFlag( ed );
1110
1111 tedAdaptToolsToSelection( ed );
1112
1113 return 0;
1114 }
1115
1116