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