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