1 /************************************************************************/
2 /*									*/
3 /*  Document window application independent functionality.		*/
4 /*									*/
5 /************************************************************************/
6 
7 #   include	"appFrameConfig.h"
8 
9 #   include	<stddef.h>
10 #   include	<stdio.h>
11 #   include	<stdlib.h>
12 
13 #   include	<appSystem.h>
14 #   include	"appFrame.h"
15 #   include	"appQuestion.h"
16 #   include	"guiWidgetDrawingSurface.h"
17 #   include	"guiDrawingWidget.h"
18 #   include	"appFileChooser.h"
19 #   include	"utilMemoryBufferPrintf.h"
20 
21 #   include	<appDebugon.h>
22 
23 #   define	LOG_REDRAWS	0
24 
25 /************************************************************************/
26 /*									*/
27 /*  Callback for the file menu.						*/
28 /*									*/
29 /************************************************************************/
30 
APP_MENU_CALLBACK_H(appDocFileSave,option,voided,e)31 APP_MENU_CALLBACK_H( appDocFileSave, option, voided, e )
32     {
33     EditDocument *		ed= (EditDocument *)voided;
34     EditApplication *		ea= ed->edApplication;
35 
36     APP_WIDGET			relative= ed->edToplevel.atTopWidget;
37 
38     if  ( ! ea->eaSaveDocument )
39 	{ XDEB(ea->eaSaveDocument); return;	}
40 
41     if  ( utilMemoryBufferIsEmpty( &(ed->edFilename) )	||
42 	  ed->edFileReadOnly				||
43 	  ed->edFormat < 0				)
44 	{
45 	appRunSaveChooser( option, ed->edToplevel.atTopWidget,
46 			    APPFILE_CAN_SAVE, appDocSaveDocument,
47 			    ed, ed->edPrivateData );
48 
49 	return;
50 	}
51 
52     if  ( ! appDocSaveDocument( ed, (void *)0, relative, option,
53 					    ed->edFormat, &(ed->edFilename) ) )
54 	{ appDocumentChanged( ed, 0 ); }
55 
56     return;
57     }
58 
59 /************************************************************************/
60 /*									*/
61 /*  'Close' callback for the file menu and for the window manager menu	*/
62 /*									*/
63 /*  1)  As 'mwm' sometimes sends a 'Save yourself' when 'Close' is	*/
64 /*	selected from the window manager menu, deactivate the protocol.	*/
65 /*	B.T.W. This does not help.					*/
66 /*									*/
67 /*									*/
68 /************************************************************************/
69 
APP_MENU_CALLBACK_H(appDocFileClose,option,voided,e)70 APP_MENU_CALLBACK_H( appDocFileClose, option, voided, e )
71     {
72     EditDocument *	ed= (EditDocument *)voided;
73 
74     if  ( ed->edHasBeenChanged )
75 	{ appRunReallyCloseDialog( option, ed ); return; }
76 
77     appCloseDocument( ed );
78 
79     return;
80     }
81 
APP_CLOSE_CALLBACK_H(appDocFileCloseCallback,w,voided)82 APP_CLOSE_CALLBACK_H( appDocFileCloseCallback, w, voided )
83     {
84     EditDocument *	ed= (EditDocument *)voided;
85 
86     if  ( ed->edHasBeenChanged )
87 	{ appRunReallyCloseDialog( ed->edFileCloseOption, ed ); return; }
88 
89     appCloseDocument( ed );
90     }
91 
APP_MENU_CALLBACK_H(appDocFileNew,option,voided,e)92 APP_MENU_CALLBACK_H( appDocFileNew, option, voided, e )
93     {
94     EditDocument *		ed= (EditDocument *)voided;
95     EditApplication *		ea= ed->edApplication;
96     const MemoryBuffer *	filename= (const MemoryBuffer *)0;
97 
98     if  ( appNewDocument( ea, filename ) )
99 	{ LDEB(1); }
100 
101     return;
102     }
103 
APP_MENU_CALLBACK_H(appDocFileQuit,option,voided,e)104 APP_MENU_CALLBACK_H( appDocFileQuit, option, voided, e )
105     {
106     EditDocument *	ed= (EditDocument *)voided;
107     EditApplication *	ea= ed->edApplication;
108 
109     appQuitApplication( option, ed->edToplevel.atTopWidget, ea );
110 
111     return;
112     }
113 
appReportSaveFailure(EditApplication * ea,APP_WIDGET option,APP_WIDGET relative,const MemoryBuffer * filename)114 void appReportSaveFailure(	EditApplication *	ea,
115 				APP_WIDGET		option,
116 				APP_WIDGET		relative,
117 				const MemoryBuffer *	filename )
118     {
119     AppFileMessageResources *	afmr= &(ea->eaFileMessageResources);
120 
121     if  ( appTestFileWritable( filename ) )
122 	{
123 	appQuestionRunFilenameErrorDialog( ea, relative, option,
124 					filename, afmr->afmrFileNotWritable );
125 	}
126     else{
127 	appQuestionRunFilenameErrorDialog( ea, relative, option,
128 					filename, afmr->afmrFileNotWritable );
129 	}
130     }
131 
132 /************************************************************************/
133 /*									*/
134 /*  The user selected the 'about' option.				*/
135 /*									*/
136 /************************************************************************/
137 
APP_MENU_CALLBACK_H(appDocAbout,option,voided,e)138 APP_MENU_CALLBACK_H( appDocAbout, option, voided, e )
139     {
140     EditDocument *		ed= (EditDocument *)voided;
141     EditApplication *		ea= ed->edApplication;
142 
143     ea->eaMainVisibleAsAbout= 1;
144 
145     appShowShellWidget( ea, ea->eaToplevel.atTopWidget );
146 
147     return;
148     }
149 
150 /************************************************************************/
151 /*									*/
152 /*  Callback for the option in the files menu.				*/
153 /*									*/
154 /************************************************************************/
155 
appMakeDocVisible(EditApplication * ea,EditDocument * ed)156 void appMakeDocVisible(	EditApplication *	ea,
157 			EditDocument *		ed )
158     {
159     appShowShellWidget( ea, ed->edToplevel.atTopWidget );
160 
161     if  ( ! ed->edIsVisible )
162 	{
163 	ed->edIsVisible= 1;
164 
165 	appDocVisible( ea, ed, ed->edIsVisible );
166 	}
167     }
168 
appDocToFront(APP_WIDGET option,void * voided,void * e)169 void appDocToFront(	APP_WIDGET	option,
170 			void *		voided,
171 			void *		e )
172     {
173     EditDocument *		ed= (EditDocument *)voided;
174     EditApplication *		ea= ed->edApplication;
175 
176     appMakeDocVisible( ea, ed );
177 
178     appGuiSetToggleItemState( option, ed->edHasBeenChanged );
179 
180     return;
181     }
182 
183 /************************************************************************/
184 /*									*/
185 /*  Callbacks for the edit menu.					*/
186 /*									*/
187 /************************************************************************/
188 
APP_MENU_CALLBACK_H(appDocEditCopy,option,voided,e)189 APP_MENU_CALLBACK_H( appDocEditCopy, option, voided, e )
190     {
191     EditDocument *			ed= (EditDocument *)voided;
192     EditApplication *			ea= ed->edApplication;
193 
194     if  ( ! ea->eaDocCopy )
195 	{ XDEB(ea->eaDocCopy); return;	}
196 
197     (*ea->eaDocCopy)( ed ); return;
198     }
199 
APP_MENU_CALLBACK_H(appDocEditCut,option,voided,e)200 APP_MENU_CALLBACK_H( appDocEditCut, option, voided, e )
201     {
202     EditDocument *			ed= (EditDocument *)voided;
203     EditApplication *			ea= ed->edApplication;
204 
205     if  ( ! ea->eaDocCut )
206 	{ XDEB(ea->eaDocCut); return;	}
207 
208     (*ea->eaDocCut)( ed ); return;
209     }
210 
APP_MENU_CALLBACK_H(appDocEditSelAll,option,voided,e)211 APP_MENU_CALLBACK_H( appDocEditSelAll, option, voided, e )
212     {
213     EditDocument *			ed= (EditDocument *)voided;
214     EditApplication *			ea= ed->edApplication;
215 
216     if  ( ! ea->eaDocSelAll )
217 	{ XDEB(ea->eaDocSelAll); return;	}
218 
219     ea->eaDocSelAll( ed ); return;
220     }
221 
appSetDocumentFilename(EditDocument * ed,const MemoryBuffer * filename)222 int appSetDocumentFilename(	EditDocument *		ed,
223 				const MemoryBuffer *	filename )
224     {
225     if  ( filename )
226 	{
227 	if  ( utilCopyMemoryBuffer( &(ed->edFilename), filename ) )
228 	    { LDEB(1); return -1;	}
229 	}
230     else{ utilEmptyMemoryBuffer( &(ed->edFilename) );	}
231 
232     return 0;
233     }
234 
appFormatDocumentTitle(MemoryBuffer * windowTitle,MemoryBuffer * iconTitle,EditApplication * ea,const MemoryBuffer * title)235 int appFormatDocumentTitle(	MemoryBuffer *		windowTitle,
236 				MemoryBuffer *		iconTitle,
237 				EditApplication *	ea,
238 				const MemoryBuffer *	title )
239     {
240     int			rval= 0;
241 
242     MemoryBuffer	baseName;
243 
244     utilInitMemoryBuffer( &baseName );
245 
246     if  ( appFileGetRelativeName( &baseName, title ) < 0 )
247 	{ LDEB(1); rval= -1; goto ready;	}
248 
249     if  ( utilMemoryBufferSetString( windowTitle, ea->eaApplicationName ) )
250 	{ LDEB(1); rval= -1; goto ready;	}
251     if  ( utilMemoryBufferAppendString( windowTitle, ": " ) )
252 	{ LDEB(1); rval= -1; goto ready;	}
253     if  ( utilMemoryAppendBuffer( windowTitle, title ) )
254 	{ LDEB(1); rval= -1; goto ready;	}
255 
256     if  ( utilMemoryBufferSetString( iconTitle, ea->eaApplicationName ) )
257 	{ LDEB(1); rval= -1; goto ready;	}
258     if  ( utilMemoryBufferAppendString( iconTitle, ": " ) )
259 	{ LDEB(1); rval= -1; goto ready;	}
260     if  ( utilMemoryAppendBuffer( iconTitle, &baseName ) )
261 	{ LDEB(1); rval= -1; goto ready;	}
262 
263   ready:
264 
265     utilCleanMemoryBuffer( &baseName );
266 
267     return rval;
268     }
269 
appSetDocumentTitle(EditDocument * ed,const MemoryBuffer * title)270 int appSetDocumentTitle(	EditDocument *		ed,
271 				const MemoryBuffer *	title )
272     {
273     int				rval= 0;
274     EditApplication *		ea= ed->edApplication;
275 
276     MemoryBuffer		fullTitle;
277     MemoryBuffer		iconName;
278 
279     utilInitMemoryBuffer( &fullTitle );
280     utilInitMemoryBuffer( &iconName );
281 
282     if  ( utilCopyMemoryBuffer( &(ed->edTitle), title ) )
283 	{ LDEB(1); rval= -1; goto ready;	}
284 
285     if  ( appFormatDocumentTitle( &fullTitle, &iconName, ea, &(ed->edTitle) ) )
286 	{ LDEB(1); rval= -1; goto ready;	}
287 
288     appGuiSetShellTitle( ed->edToplevel.atTopWidget, &fullTitle );
289     appGuiSetIconTitle( ed->edToplevel.atTopWidget, &iconName );
290 
291     appRenameDocumentOptions( ed->edApplication, ed, &(ed->edTitle) );
292 
293   ready:
294 
295     utilCleanMemoryBuffer( &fullTitle );
296     utilCleanMemoryBuffer( &iconName );
297 
298     return rval;
299     }
300 
301 
302 /************************************************************************/
303 /*									*/
304 /*  Free all resources allocated for a document.			*/
305 /*									*/
306 /************************************************************************/
307 
appCleanDocumentWidget(DocumentWidget * dw)308 static void appCleanDocumentWidget(	DocumentWidget *	dw )
309     {
310 #   ifdef USE_MOTIF
311     if  ( dw->dwInputContext )
312 	{ XDestroyIC( dw->dwInputContext ); }
313 #   endif
314 
315 #   if defined(USE_GTK) && defined(GTK_TYPE_IM_CONTEXT)
316     if  ( dw->dwInputContext )
317 	{ g_object_unref( dw->dwInputContext ); }
318 #   endif
319     }
320 
appCleanDocument(EditApplication * ea,EditDocument * ed)321 static void appCleanDocument(		EditApplication *	ea,
322 					EditDocument *		ed )
323     {
324     if  ( ed->edLeftRuler )
325 	{ (*ea->eaFreeLeftRuler)( ed->edLeftRuler ); }
326     if  ( ed->edTopRuler )
327 	{ (*ea->eaFreeTopRuler)( ed->edTopRuler ); }
328     if  ( ed->edRightRuler )
329 	{ (*ea->eaFreeRightRuler)( ed->edRightRuler ); }
330     if  ( ed->edBottomRuler )
331 	{ (*ea->eaFreeBottomRuler)( ed->edBottomRuler ); }
332 
333     utilCleanMemoryBuffer( &(ed->edFilename) );
334     utilCleanMemoryBuffer( &(ed->edTitle) );
335 
336     appCleanDocumentWidget( &(ed->edDocumentWidget) );
337     if  ( ed->edDrawingSurface )
338 	{ drawFreeDrawingSurface( ed->edDrawingSurface ); }
339 
340     return;
341     }
342 
appFreeDocument(EditApplication * ea,EditDocument * ed)343 static void appFreeDocument(		EditApplication *	ea,
344 					EditDocument *		ed )
345     {
346     appCleanDocument( ea, ed );
347     free( ed );
348 
349     return;
350     }
351 
appInitDocumentWidget(DocumentWidget * dw)352 static void appInitDocumentWidget(	DocumentWidget *	dw )
353     {
354     dw->dwWidget= (APP_WIDGET)0;
355 
356 #   ifdef USE_MOTIF
357     dw->dwInputContext= (XIC)0;
358 #   endif
359 
360 #   ifdef USE_GTK
361 #	ifdef GTK_TYPE_IM_CONTEXT
362 	dw->dwInputContext= (GtkIMContext *)0;
363 #	else
364 	dw->dwInputContext= 0;
365 #	endif
366 #   endif
367     }
368 
appInitEditDocument(EditApplication * ea,EditDocument * ed)369 static void appInitEditDocument(	EditApplication *	ea,
370 					EditDocument *		ed )
371     {
372     ed->edApplication= ea;
373 
374     utilInitMemoryBuffer( &(ed->edFilename) );
375     utilInitMemoryBuffer( &(ed->edTitle) );
376 
377     ed->edFormat= -1;
378     ed->edFileReadOnly= 0;
379 
380     ed->edMenuBar= (APP_WIDGET)0;
381     ed->edMainWindow= (APP_WIDGET)0;
382 	ed->edFileMenu= (APP_WIDGET)0;
383 	ed->edFileMenuButton= (APP_WIDGET)0;
384 	    ed->edFileCloseOption= (APP_WIDGET)0;
385 	ed->edEditMenu= (APP_WIDGET)0;
386 	ed->edEditMenuButton= (APP_WIDGET)0;
387 	ed->edWindowMenu= (APP_WIDGET)0;
388 	ed->edWindowMenuButton= (APP_WIDGET)0;
389 	ed->edHelpMenu= (APP_WIDGET)0;
390 	ed->edHelpMenuButton= (APP_WIDGET)0;
391 
392     ed->edToolbar= (APP_WIDGET)0;
393     ed->edScrolledWindow= (APP_WIDGET)0;
394 	ed->edVerticalScrollbar= (APP_WIDGET)0;
395 	ed->edHorizontalScrollbar= (APP_WIDGET)0;
396 	ed->edWorkWidget= (APP_WIDGET)0;
397 	appInitDocumentWidget( &(ed->edDocumentWidget) );
398 	ed->edDrawingSurface= (DrawingSurface)0;
399 
400 	ed->edLeftRulerWidget= (APP_WIDGET)0;
401 	ed->edTopRulerWidget= (APP_WIDGET)0;
402 	ed->edRightRulerWidget= (APP_WIDGET)0;
403 	ed->edBottomRulerWidget= (APP_WIDGET)0;
404 
405 	ed->edLeftRuler= (void *)0;
406 	ed->edTopRuler= (void *)0;
407 	ed->edRightRuler= (void *)0;
408 	ed->edBottomRuler= (void *)0;
409 
410     ed->edLeftRulerWidePixels= 0;
411     ed->edTopRulerHighPixels= 0;
412     ed->edRightRulerWidePixels= 0;
413     ed->edBottomRulerHighPixels= 0;
414 
415     ed->edHasBeenChanged= 0;
416     ed->edIsReadonly= 0;
417     ed->edIsVisible= 0;
418 
419     ed->edMapped= 0;
420     ed->edNotYetDrawn= 1;
421 
422     appInitSelectRectangle( &(ed->edSelectRectangle) );
423     return;
424     }
425 
appMakeDocumentWindow(EditDocument ** pEd,EditApplication * ea,int readOnly,const MemoryBuffer * title,const MemoryBuffer * filename)426 int appMakeDocumentWindow(		EditDocument **		pEd,
427 					EditApplication *	ea,
428 					int			readOnly,
429 					const MemoryBuffer *	title,
430 					const MemoryBuffer *	filename )
431     {
432     int				rval= 0;
433     EditDocument *		ed= (EditDocument *)0;
434 
435     MemoryBuffer		scratch;
436 
437     utilInitMemoryBuffer( &scratch );
438 
439     if  ( ! title || utilMemoryBufferIsEmpty( title ) )
440 	{
441 	static int			count= 1;
442 
443 	AppFileMessageResources *	afmr= &(ea->eaFileMessageResources);
444 
445 	utilMemoryBufferPrintf( &scratch,
446 				    afmr->afmrNamelessTitleFormat, count++ );
447 	title= &scratch;
448 	}
449 
450     /*  1  */
451     ed= (EditDocument *)malloc( sizeof(EditDocument) );
452     if  ( ! ed )
453 	{ XDEB(ed); rval= -1; goto ready;	}
454 
455     appInitEditDocument( ea, ed );
456 
457     ea->eaNextDocumentId++; /* Never 0 */
458     ed->edDocumentId= ea->eaNextDocumentId;
459 
460     if  ( filename && utilCopyMemoryBuffer( &(ed->edFilename), filename ) )
461 	{ LDEB(1); rval= -1; goto ready;	}
462 
463     ed->edIsReadonly= readOnly;
464     if  ( utilCopyMemoryBuffer( &(ed->edTitle), title ) )
465 	{ LDEB(1); rval= -1; goto ready;	}
466 
467     if  ( ea->eaMakePrivateData	)
468 	{
469 	ed->edPrivateData= (*ea->eaMakePrivateData)();
470 	if  ( ! ed->edPrivateData )
471 	    { XDEB(ed->edPrivateData); rval= -1; goto ready; }
472 	}
473 
474     if  ( appFinishDocumentWindow( ed ) )
475 	{ LDEB(1); rval= -1; goto ready; }
476 
477     *pEd= ed; ed= (EditDocument *)0; /* steal */
478 
479   ready:
480 
481     utilCleanMemoryBuffer( &scratch );
482 
483     if  ( ed )
484 	{ appFreeDocument( ea, ed ); }
485 
486     return rval;
487     }
488 
appSetupDocument(EditApplication * ea,EditDocument * ed)489 int appSetupDocument(	EditApplication *	ea,
490 			EditDocument *		ed )
491     {
492     DocumentWidget *		dw= &(ed->edDocumentWidget);
493 
494     int				wide;
495     int				high;
496 
497 #   ifdef USE_MOTIF
498     XtRealizeWidget( ed->edToplevel.atTopWidget );
499 #   endif
500 
501 #   ifdef USE_GTK
502     gtk_widget_realize( ed->edToplevel.atTopWidget );
503 #   endif
504 
505     ed->edDrawingSurface= guiDrawingSurfaceForNativeWidget(
506 					    ed->edDocumentWidget.dwWidget,
507 					    ea->eaAvoidFontconfigInt > 0 );
508     if  ( ! ed->edDrawingSurface )
509 	{ PDEB(ed->edDrawingSurface); appFreeDocument( ea, ed ); return -1; }
510 
511     if  ( (*ea->eaLayoutDocument)( &(ed->edFullRect),
512 					&(ed->edVisibleRect),
513 					ed->edPrivateData, ed->edFormat,
514 					ed->edDrawingSurface,
515 					&(ea->eaPostScriptFontList),
516 					&(ea->eaDefaultDocumentGeometry) ) )
517 	{ LDEB(1); return -1; }
518 
519     wide= ed->edVisibleRect.drX1- ed->edVisibleRect.drX0;
520     high= ed->edVisibleRect.drY1- ed->edVisibleRect.drY0;
521 
522     if  ( wide > ( 4* ea->eaScreenPixelsWide )/ 5 )
523 	{ wide=  ( 4* ea->eaScreenPixelsWide )/ 5; }
524     if  ( high > ( 4* ea->eaScreenPixelsHigh )/ 5 )
525 	{ high=  ( 4* ea->eaScreenPixelsHigh )/ 5; }
526 
527 #   ifdef USE_MOTIF
528     {
529     Dimension docW= -1, docH= -1;
530     Dimension topW= -1, topH= -1;
531 
532     XtVaSetValues( dw->dwWidget,
533 			    XmNborderWidth,		0,
534 			    XmNshadowThickness,		0,
535 			    XmNwidth,			wide,
536 			    XmNheight,			high,
537 			    NULL );
538 
539     /*
540      * Cope with the fact that Motif performs the geometry calculations
541      * when the widget is realised (And that we need to realize the widget
542      * before we perform the layout of the document.)
543      */
544 
545     XtVaGetValues( dw->dwWidget,
546 			    XmNwidth,			&docW,
547 			    XmNheight,			&docH,
548 			    NULL );
549     XtVaGetValues( ed->edToplevel.atTopWidget,
550 			    XmNwidth,			&topW,
551 			    XmNheight,			&topH,
552 			    NULL );
553 
554     if  ( docW != wide && docH != high && topW > docW && topH > docH )
555 	{
556 	XtVaSetValues( ed->edToplevel.atTopWidget,
557 			    XmNwidth,			wide+ ( topW- docW ),
558 			    XmNheight,			high+ ( topH- docH ),
559 			    NULL );
560 	}
561     }
562 #   endif
563 
564 #   ifdef USE_GTK
565     gtk_drawing_area_size( GTK_DRAWING_AREA( ed->edTopRulerWidget ),
566 					ed->edLeftRulerWidePixels+
567 					wide+
568 					ed->edRightRulerWidePixels,
569 					ed->edTopRulerHighPixels );
570     gtk_drawing_area_size( GTK_DRAWING_AREA( ed->edLeftRulerWidget ),
571 					ed->edLeftRulerWidePixels, high );
572 
573 
574     gtk_drawing_area_size( GTK_DRAWING_AREA( dw->dwWidget ), wide, high );
575 
576     gtk_drawing_area_size( GTK_DRAWING_AREA( ed->edRightRulerWidget ),
577 					    ed->edRightRulerWidePixels, high );
578     gtk_drawing_area_size( GTK_DRAWING_AREA( ed->edBottomRulerWidget ),
579 					ed->edLeftRulerWidePixels+
580 					wide+
581 					ed->edRightRulerWidePixels,
582 					ed->edBottomRulerHighPixels );
583 
584     gtk_object_set_user_data( GTK_OBJECT( dw->dwWidget ), (void *)ed );
585 #   endif
586 
587     if  ( ea->eaSetTopRuler		&&
588 	  (*ea->eaSetTopRuler)( ed )	)
589 	{ LDEB(1);	}
590 
591     if  ( ea->eaSetLeftRuler		&&
592 	  (*ea->eaSetLeftRuler)( ed )	)
593 	{ LDEB(1);	}
594 
595     if  ( ea->eaSetRightRuler		&&
596 	  (*ea->eaSetRightRuler)( ed )	)
597 	{ LDEB(1);	}
598 
599     if  ( ea->eaSetBottomRuler		&&
600 	  (*ea->eaSetBottomRuler)( ed )	)
601 	{ LDEB(1);	}
602 
603     guiGetBackgroundColor( &(ed->edBackgroundColor), dw->dwWidget );
604 
605     appDocSetScrollbarValues( ed );
606 
607     ed->edHasBeenChanged= 0;  /*  Can be changed in eaFinishDocumentSetup */
608 
609     if  ( ea->eaFinishDocumentSetup && (*ea->eaFinishDocumentSetup)( ed ) )
610 	{ LDEB(1); return -1; }
611 
612     appShowShellWidget( ea, ed->edToplevel.atTopWidget );
613 
614     ed->edIsVisible= 1;
615 
616     appDocVisible( ea, ed, ed->edIsVisible );
617 
618     return 0;
619     }
620 
621 /************************************************************************/
622 /*									*/
623 /*  Close a a document.							*/
624 /*									*/
625 /************************************************************************/
626 
appCloseDocument(EditDocument * ed)627 void appCloseDocument(	EditDocument *		ed )
628     {
629     EditApplication *	ea= ed->edApplication;
630 
631     appRemoveDocument( ea, ed );
632 
633     /* Is done by the widget destroy callback for GTK: */
634 #   ifdef USE_MOTIF
635     if  ( ed->edPrivateData )
636 	{
637 	(*ea->eaFreeDocument)( ed->edPrivateData, ed->edFormat );
638 	ed->edPrivateData= (void *)0;
639 	}
640 #   endif
641 
642     appCleanDocument( ea, ed );
643     appDestroyShellWidget( ed->edToplevel.atTopWidget );
644 
645     /* Is done by the widget destroy callback that is called asynchronuously */
646 #   if 0
647     free( ed );
648 #   endif
649 
650     return;
651     }
652 
653 /************************************************************************/
654 /*									*/
655 /*  Destroy callback on a document widget.				*/
656 /*									*/
657 /************************************************************************/
658 
APP_DESTROY_CALLBACK_H(appDestroyEditDocument,w,voided)659 APP_DESTROY_CALLBACK_H( appDestroyEditDocument, w, voided )
660     {
661     EditDocument *		ed= (EditDocument *)voided;
662     EditApplication *		ea= ed->edApplication;
663 
664     if  ( ed->edPrivateData )
665 	{
666 	(*ea->eaFreeDocument)( ed->edPrivateData, ed->edFormat );
667 	ed->edPrivateData= (void *)0;
668 	}
669 
670     free( ed );
671 
672     return;
673     }
674 
675 /************************************************************************/
676 /*									*/
677 /*  Fill the menu of a document window.					*/
678 /*									*/
679 /************************************************************************/
680 
appDocFillMenu(EditDocument * ed)681 void appDocFillMenu(	EditDocument *		ed )
682     {
683     EditApplication *	ea= ed->edApplication;
684 
685     ed->edFileMenu= appMakeMenu( &(ed->edFileMenuButton),
686 		    &(ed->edToplevel), ea, ed->edMenuBar,
687 		    *(ea->eaDocFileMenuText), 0,
688 		    ea->eaDocFileMenuItems, ea->eaDocFileMenuItemCount,
689 		    (void *)ed );
690 
691     ed->edEditMenu= appMakeMenu( &(ed->edEditMenuButton),
692 		    &(ed->edToplevel), ea, ed->edMenuBar,
693 		    *(ea->eaDocEditMenuText), 0,
694 		    ea->eaDocEditMenuItems, ea->eaDocEditMenuItemCount,
695 		    (void *)ed );
696 
697     if  ( ea->eaMakePrivateDocumentMenus )
698 	{ (*ea->eaMakePrivateDocumentMenus)( ea, ed, ed->edMenuBar ); }
699 
700     ed->edWindowMenu= appMakeMenu( &(ed->edWindowMenuButton),
701 		    &(ed->edToplevel), ea, ed->edMenuBar,
702 		    *(ea->eaDocWindowMenuText), 0,
703 		    ea->eaDocWindowMenuItems, ea->eaDocWindowMenuItemCount,
704 		    (void *)ed );
705 
706     if  ( ea->eaDocHelpMenuItems )
707 	{
708 	ed->edHelpMenu= appMakeMenu( &(ed->edHelpMenuButton),
709 		    &(ed->edToplevel), ea, ed->edMenuBar,
710 		    *(ea->eaDocHelpMenuText), 1,
711 		    ea->eaDocHelpMenuItems, ea->eaDocHelpMenuItemCount,
712 		    (void *)ed );
713 	}
714 
715     }
716 
717 /************************************************************************/
718 /*									*/
719 /*  Open a a document.							*/
720 /*									*/
721 /*  1)  Allocate a document.						*/
722 /*  3)  Make a shell to contain everything.				*/
723 /*  4)  Make the window pane.						*/
724 /*									*/
725 /************************************************************************/
726 
appOpenDocumentFile(EditApplication * ea,APP_WIDGET relative,APP_WIDGET option,int readOnly,int suggestStdin,int formatHint,const MemoryBuffer * filename)727 EditDocument * appOpenDocumentFile(	EditApplication *	ea,
728 					APP_WIDGET		relative,
729 					APP_WIDGET		option,
730 					int			readOnly,
731 					int			suggestStdin,
732 					int			formatHint,
733 					const MemoryBuffer *	filename )
734     {
735     EditDocument *		ed;
736     int				fileReadonly= 0;
737     AppFileMessageResources *	afmr= &(ea->eaFileMessageResources);
738 
739     if  ( readOnly || suggestStdin )
740 	{ fileReadonly= 1;	}
741     else{
742 	if  ( appTestFileReadable( filename ) )
743 	    {
744 	    int			resp;
745 
746 	    resp= appQuestionRunFilenameOkCancelDialog( ea, relative, option,
747 					    filename, afmr->afmrFileReadOnly );
748 
749 	    if  ( resp != AQDrespOK )
750 		{ return (EditDocument *)0;	}
751 
752 	    fileReadonly= 1;
753 	    }
754 	}
755 
756     /*  1,3,4  */
757     if  ( appMakeDocumentWindow( &ed, ea, readOnly, filename, filename ) )
758 	{ LDEB(1); return (EditDocument *)0;	}
759 
760     ed->edFileReadOnly= fileReadonly;
761 
762     if  ( (*ea->eaOpenDocument)( ea, ed->edPrivateData, &(ed->edFormat),
763 				relative, option,
764 				readOnly, suggestStdin, formatHint, filename ) )
765 	{ return (EditDocument *)0; }
766 
767     if  ( appSetupDocument( ea, ed ) )
768 	{ LDEB(1); return (EditDocument *)0; }
769 
770     appSetDocument( ea, ed );
771 
772     return ed;
773     }
774 
appOpenDocument(EditApplication * ea,APP_WIDGET relative,APP_WIDGET option,int readOnly,const MemoryBuffer * filename)775 EditDocument * appOpenDocument(	EditApplication *	ea,
776 				APP_WIDGET		relative,
777 				APP_WIDGET		option,
778 				int			readOnly,
779 				const MemoryBuffer *	filename )
780     {
781     const int	suggestStdin= 0;
782     int		formatHint= -1;
783 
784     formatHint= appDocumentGetOpenFormat( (int *)0,
785 			ea->eaFileExtensions, ea->eaFileExtensionCount,
786 			filename, formatHint );
787 
788     return appOpenDocumentFile( ea, relative, option,
789 			    readOnly, suggestStdin, formatHint, filename );
790     }
791 
appNewDocument(EditApplication * ea,const MemoryBuffer * filename)792 int appNewDocument(	EditApplication *	ea,
793 			const MemoryBuffer *	filename )
794     {
795     const int			readOnly= 0;
796     const char *		title= (const char *)0;
797 
798     EditDocument *		ed;
799 
800     /*  1,3,4  */
801     if  ( appMakeDocumentWindow( &ed, ea, readOnly, filename, filename ) )
802 	{ LDEB(1); return -1;	}
803 
804     if  ( (*ea->eaNewDocument)( ed, filename ) )
805 	{ SDEB(title); return -1; }
806 
807     if  ( appSetupDocument( ea, ed ) )
808 	{ SDEB(title); return -1; }
809 
810     appSetDocument( ea, ed );
811 
812     return 0;
813     }
814 
815 /************************************************************************/
816 /*									*/
817 /*  Redraw a rectangle in the document widget.				*/
818 /*									*/
819 /************************************************************************/
820 
APP_EVENT_HANDLER_H(appDocExposeHandler,w,voided,exposeEvent)821 APP_EVENT_HANDLER_H( appDocExposeHandler, w, voided, exposeEvent )
822     {
823     EditDocument *		ed= (EditDocument *)voided;
824     EditApplication *		ea= ed->edApplication;
825 
826     int				ox= ed->edVisibleRect.drX0;
827     int				oy= ed->edVisibleRect.drY0;
828 
829     DocumentRectangle		drClip;
830 
831     if  ( ed->edNotYetDrawn				&&
832 	  ea->eaDocumentFirstVisible			)
833 	{ (*ea->eaDocumentFirstVisible)( ed );	}
834 
835     ed->edNotYetDrawn= 0;
836 
837     /*  1  */
838     guiCollectExposures( &drClip, ed->edDocumentWidget.dwWidget, exposeEvent );
839     drawSetClipRect( ed->edDrawingSurface, &drClip );
840 
841     geoShiftRectangle( &drClip, ox, oy );
842 
843     /*  2,3,4  */
844     (*ea->eaDrawRectangle)( ed, &drClip, ox, oy );
845 
846     drawNoClipping( ed->edDrawingSurface );
847 
848     return;
849     }
850 
851 /************************************************************************/
852 /*									*/
853 /*  Cause a rectangle to be redrawn.					*/
854 /*									*/
855 /*  Cause the smallest rectangle that contains the selection to be	*/
856 /*  redrawn.								*/
857 /*									*/
858 /*  drChanged is a rectangle in the document (pixel) coordinate system.	*/
859 /*  it is shifted to accomodate for the scrollbars.			*/
860 /*									*/
861 /************************************************************************/
862 
appDocExposeRectangle(const EditDocument * ed,const DocumentRectangle * drChanged,int scrolledX,int scrolledY)863 void appDocExposeRectangle(	const EditDocument *		ed,
864 				const DocumentRectangle *	drChanged,
865 				int				scrolledX,
866 				int				scrolledY )
867     {
868     DocumentRectangle		drExpose;
869     DocumentRectangle		drScrolled;
870 
871     const DocumentRectangle *	drVisible= &(ed->edVisibleRect);
872 
873     if  ( ! drChanged )
874 	{ guiExposeDrawingWidget( ed->edDocumentWidget.dwWidget ); return; }
875 
876     drScrolled= *drChanged;
877     geoShiftRectangle( &drScrolled, -scrolledX, -scrolledY );
878 
879     if  ( scrolledX != 0 )
880 	{
881 	drScrolled.drY0= drVisible->drY0;
882 	drScrolled.drY1= drVisible->drY1;
883 	}
884 
885     if  ( scrolledY != 0 )
886 	{
887 	drScrolled.drX0= drVisible->drX0;
888 	drScrolled.drX1= drVisible->drX1;
889 	}
890 
891     geoUnionRectangle( &drScrolled, &drScrolled, drChanged );
892 
893     drExpose= *drVisible;
894 
895     if  ( geoIntersectRectangle( &drExpose, &drExpose, &drScrolled ) )
896 	{
897 	geoShiftRectangle( &drExpose, -drVisible->drX0, -drVisible->drY0 );
898 
899 	if  ( drExpose.drX0 < 0 )
900 	    { drExpose.drX0=  0;	}
901 	if  ( drExpose.drY0 < 0 )
902 	    { drExpose.drY0=  0;	}
903 
904 #	if LOG_REDRAWS
905 	docLogRectangle( "CLEAR!", &drExpose );
906 #	endif
907 
908 	if  ( drExpose.drX1 >= drExpose.drX0 && drExpose.drY1 >= drExpose.drY0 )
909 	    {
910 	    guiExposeDrawingWidgetRectangle( ed->edDocumentWidget.dwWidget,
911 								    &drExpose );
912 	    }
913 	}
914     }
915 
appInitSelectRectangle(SelectRectangle * sr)916 void appInitSelectRectangle(	SelectRectangle *	sr )
917     {
918     sr->srDirection= DOCselNONE;
919 
920     geoInitRectangle( &(sr->srSelected) );
921     geoInitRectangle( &(sr->srLTM) );
922     geoInitRectangle( &(sr->srRBM) );
923     }
924 
925 /************************************************************************/
926 /*									*/
927 /*  Callback from the 'Save As' action of the filechooser.		*/
928 /*									*/
929 /************************************************************************/
930 
appDocSaveDocument(EditDocument * ed,void * through,APP_WIDGET relative,APP_WIDGET option,int format,const MemoryBuffer * filename)931 int appDocSaveDocument(	EditDocument *		ed,
932 			void *			through,
933 			APP_WIDGET		relative,
934 			APP_WIDGET		option,
935 			int			format,
936 			const MemoryBuffer *	filename )
937     {
938     EditApplication *	ea= ed->edApplication;
939     const int		suggestStdout= 0;
940 
941     int			canOpen= appFileCanOpen( ea, format );
942     int			isDocName= canOpen;
943 
944     if  ( (*ea->eaSaveDocument)( ea, ed->edDrawingSurface,
945 				ed->edPrivateData, format, &(ed->edTitle),
946 				suggestStdout, filename, isDocName ) )
947 	{
948 	appReportSaveFailure( ea, option, relative, filename );
949 	return -1;
950 	}
951 
952     if  ( canOpen )
953 	{
954 	appDocumentChanged( ed, 0 );
955 	ed->edFileReadOnly= 0;
956 	ed->edFormat= format;
957 
958 	if  ( ! utilEqualMemoryBuffer( &(ed->edFilename), filename ) )
959 	    {
960 	    if  ( appSetDocumentFilename( ed, filename ) )
961 		{ LDEB(1);	}
962 	    if  ( appSetDocumentTitle( ed, filename ) )
963 		{ LDEB(1);	}
964 	    }
965 	}
966 
967     return 0;
968     }
969 
970