1 /************************************************************************/
2 /* */
3 /* Application, Main module. */
4 /* */
5 /************************************************************************/
6
7 # include "appFrameConfig.h"
8
9 # include <stddef.h>
10 # include <stdlib.h>
11 # include <stdio.h>
12 # include <string.h>
13 # include <locale.h>
14 # include <signal.h>
15
16 # include <appSystem.h>
17
18 # include "appFrame.h"
19 # include "appQuestion.h"
20 # include "appFileChooser.h"
21 # include <appUnit.h>
22 # include <appPaper.h>
23 # include <geoString.h>
24 # include <utilArgToX.h>
25 # include <appDebugon.h>
26
27 /************************************************************************/
28 /* */
29 /* Retrieve configurable resource values from the GUI environment. */
30 /* */
31 /* 1) This should be done wih something like the GNU message catalog */
32 /* system. For the moment, just install the default values. */
33 /* */
34 /************************************************************************/
35
appGuiGetResourceValues(int * pGotResources,EditApplication * ea,void * pValues,AppConfigurableResource * acrList,int acrCount)36 void appGuiGetResourceValues( int * pGotResources,
37 EditApplication * ea,
38 void * pValues,
39 AppConfigurableResource * acrList,
40 int acrCount )
41 {
42 AppConfigurableResource * acr;
43 char * values= (char *)pValues;
44 int i;
45
46 if ( *pGotResources )
47 { LDEB(*pGotResources); return; }
48
49 if ( ! *pGotResources )
50 { appSetResourceDefaults( ea, acrList, acrCount ); }
51
52 acr= acrList;
53 for ( i= 0; i < acrCount; acr++, i++ )
54 {
55 *((const char **)(values+acr->acrStructOffset))= acr->acrDefaultValue;
56 }
57
58 *pGotResources= 1;
59 return;
60 }
61
62 /************************************************************************/
63 /* */
64 /* Callback that is invoked when the application is closed through */
65 /* the window manager. */
66 /* */
67 /************************************************************************/
68
APP_CLOSE_CALLBACK_H(appAppWmClose,w,voidea)69 APP_CLOSE_CALLBACK_H( appAppWmClose, w, voidea )
70 {
71 EditApplication * ea= (EditApplication *)voidea;
72
73 if ( ea->eaMainVisibleAsAbout )
74 {
75 ea->eaMainVisibleAsAbout= 0;
76
77 if ( ea->eaVisibleDocumentCount > 0 )
78 { appHideShellWidget( ea->eaToplevel.atTopWidget ); }
79 }
80 else{
81 appQuitApplication( (APP_WIDGET)0,
82 ea->eaToplevel.atTopWidget, ea );
83 }
84 }
85
86 /************************************************************************/
87 /* */
88 /* Quit the application. */
89 /* */
90 /* 1) Close the documents in reverse order to avoid the subscript of */
91 /* unhandeled documents to change. */
92 /* */
93 /************************************************************************/
94
appCountChangedDocuments(EditApplication * ea)95 static int appCountChangedDocuments( EditApplication * ea )
96 {
97 int i;
98 int changedCount= 0;
99
100 for ( i= 0; i < ea->eaOpenCount; i++ )
101 {
102 EditDocument * ed= ea->eaOpenDocuments[i];
103
104 if ( ed->edHasBeenChanged )
105 { changedCount++; }
106 }
107
108 return changedCount;
109 }
110
appExitApplication(EditApplication * ea)111 static void appExitApplication( EditApplication * ea )
112 {
113 int i;
114
115 for ( i= ea->eaOpenCount- 1; i >= 0; i-- )
116 { appCloseDocument( ea->eaOpenDocuments[i] ); }
117
118 appDiscardImagePixmaps( ea );
119
120 appDestroyShellWidget( ea->eaToplevel.atTopWidget );
121
122 exit( 0 ); LDEB(1); return;
123 }
124
appAskCloseDocuments(APP_WIDGET option,EditApplication * ea)125 static void appAskCloseDocuments( APP_WIDGET option,
126 EditApplication * ea )
127 {
128 int i;
129
130 /* 1 */
131 for ( i= ea->eaOpenCount- 1; i >= 0; i-- )
132 {
133 EditDocument * ed= ea->eaOpenDocuments[i];
134
135 if ( ed->edHasBeenChanged )
136 {
137 appMakeDocVisible( ea, ed );
138 appRunReallyCloseDialog( option, ed );
139 }
140 }
141
142 return;
143 }
144
appQuitApplication(APP_WIDGET option,APP_WIDGET relative,EditApplication * ea)145 void appQuitApplication( APP_WIDGET option,
146 APP_WIDGET relative,
147 EditApplication * ea )
148 {
149 int rcc;
150 int changedCount= 0;
151
152 changedCount= appCountChangedDocuments( ea );
153 if ( changedCount == 0 )
154 { appExitApplication( ea ); LDEB(1); return; }
155
156 if ( changedCount > 1 )
157 {
158 rcc= appRunReallyQuitDialog( option, relative, ea );
159
160 switch( rcc )
161 {
162 case AQDrespCANCEL:
163 case AQDrespCLOSED:
164 return;
165 case AQDrespNO:
166 appExitApplication( ea );
167 LDEB(1); return;
168
169 default:
170 LDEB(rcc); return;
171 case AQDrespYES:
172 break;
173 }
174 }
175
176 appAskCloseDocuments( option, ea );
177
178 changedCount= appCountChangedDocuments( ea );
179 if ( changedCount == 0 )
180 { appExitApplication( ea ); LDEB(1); return; }
181
182 return;
183 }
184
APP_MENU_CALLBACK_H(appAppFileQuit,option,voidea,e)185 APP_MENU_CALLBACK_H( appAppFileQuit, option, voidea, e )
186 {
187 EditApplication * ea= (EditApplication *)voidea;
188
189 appQuitApplication( option, ea->eaToplevel.atTopWidget, ea );
190 }
191
192 /************************************************************************/
193 /* */
194 /* Open a new document. */
195 /* */
196 /************************************************************************/
197
APP_MENU_CALLBACK_H(appAppFileNew,option,voidea,e)198 APP_MENU_CALLBACK_H( appAppFileNew, option, voidea, e )
199 {
200 EditApplication * ea= (EditApplication *)voidea;
201 const MemoryBuffer * filename= (const MemoryBuffer *)0;
202
203 if ( appNewDocument( ea, filename ) )
204 { LDEB(1); }
205
206 return;
207 }
208
209 /************************************************************************/
210 /* */
211 /* Make a document the current Document. */
212 /* */
213 /************************************************************************/
214
appHighlightCurrentDocument(EditApplication * ea,EditDocument * ed,int current)215 static void appHighlightCurrentDocument( EditApplication * ea,
216 EditDocument * ed,
217 int current )
218 {
219 guiEnableWidget( ed->edMenuBar, current != 0 );
220 return;
221 }
222
appSetCurrentDocument(EditApplication * ea,EditDocument * ed)223 void appSetCurrentDocument( EditApplication * ea,
224 EditDocument * ed )
225 {
226 if ( ea->eaCurrentDocument )
227 { appHighlightCurrentDocument( ea, ea->eaCurrentDocument, 0 ); }
228
229 ea->eaCurrentDocument= ed;
230
231 appHighlightCurrentDocument( ea, ea->eaCurrentDocument, 1 );
232 }
233
234 /************************************************************************/
235 /* */
236 /* Remember whether a document has been changed. */
237 /* */
238 /************************************************************************/
239
appDocumentChanged(EditDocument * ed,int changed)240 void appDocumentChanged( EditDocument * ed,
241 int changed )
242 {
243 EditApplication * ea= ed->edApplication;
244
245 changed= changed != 0;
246
247 if ( ed->edHasBeenChanged != changed )
248 {
249 int i;
250
251 for ( i= 0; i < ea->eaOpenCount; i++ )
252 {
253 if ( ea->eaOpenDocuments[i] == ed )
254 { continue; }
255
256 appSetWindowsItemState( ea->eaOpenDocuments[i]->edWindowMenu,
257 ed, changed );
258 }
259
260 appSetWindowsItemState( ea->eaWinMenu, ed, changed );
261
262 ed->edHasBeenChanged= changed;
263 }
264 }
265
266 /************************************************************************/
267 /* */
268 /* Count the number of visible documents. */
269 /* */
270 /************************************************************************/
271
appDocVisible(EditApplication * ea,EditDocument * ed,int visible)272 void appDocVisible( EditApplication * ea,
273 EditDocument * ed,
274 int visible )
275 {
276 int from;
277
278 if ( visible )
279 { from= ea->eaVisibleDocumentCount++; }
280 else{ from= ea->eaVisibleDocumentCount--; }
281
282 if ( ea->eaVisibleDocumentCount == 0 )
283 { appShowShellWidget( ea, ea->eaToplevel.atTopWidget ); }
284 else{
285 if ( ! ea->eaMainVisibleAsAbout )
286 { appHideShellWidget( ea->eaToplevel.atTopWidget ); }
287 }
288
289 if ( ea->eaVisibleDocumentCountChanged )
290 {
291 (*ea->eaVisibleDocumentCountChanged)
292 ( ea, from, ea->eaVisibleDocumentCount );
293 }
294 }
295
296 /************************************************************************/
297 /* */
298 /* Remove a reference to a document. */
299 /* */
300 /************************************************************************/
301
appRemoveDocument(EditApplication * ea,EditDocument * ed)302 void appRemoveDocument( EditApplication * ea,
303 EditDocument * ed )
304 {
305 int i;
306 int count= 0;
307
308 for ( i= 0; i < ea->eaOpenCount; i++ )
309 {
310 if ( ea->eaOpenDocuments[i] == ed )
311 { continue; }
312
313 appRemoveWindowsOption( ea->eaOpenDocuments[i]->edWindowMenu, ed );
314 ea->eaOpenDocuments[count++]= ea->eaOpenDocuments[i];
315 }
316
317 appRemoveWindowsOption( ea->eaWinMenu, ed );
318
319 ea->eaOpenCount= count;
320
321 if ( ea->eaCurrentDocument == ed )
322 { ea->eaCurrentDocument= (EditDocument *)0; }
323
324 if ( ed->edIsVisible )
325 {
326 ed->edIsVisible= 0;
327 appDocVisible( ea, ed, ed->edIsVisible );
328 }
329
330 return;
331 }
332
appRenameDocumentOptions(EditApplication * ea,EditDocument * ed,const MemoryBuffer * title)333 void appRenameDocumentOptions( EditApplication * ea,
334 EditDocument * ed,
335 const MemoryBuffer * title )
336 {
337 int i;
338
339 for ( i= 0; i < ea->eaOpenCount; i++ )
340 {
341 if ( ea->eaOpenDocuments[i] == ed )
342 { continue; }
343
344 appRenameWindowsOption( ea->eaOpenDocuments[i]->edWindowMenu,
345 ed, title );
346 }
347
348 appRenameWindowsOption( ea->eaWinMenu, ed, title );
349
350 return;
351 }
352
353 /************************************************************************/
354 /* */
355 /* Remember a reference to a document. */
356 /* */
357 /************************************************************************/
358
appAppSetWindowsOption(APP_WIDGET menu,EditDocument * ed,const MemoryBuffer * title)359 static void appAppSetWindowsOption( APP_WIDGET menu,
360 EditDocument * ed,
361 const MemoryBuffer * title )
362 {
363 AppMenuItem ami;
364
365 if ( ed->edHasBeenChanged )
366 { ami.amiItemType= ITEMtyTOGGLE_ON; }
367 else{ ami.amiItemType= ITEMtyTOGGLE_OFF; }
368
369 ami.amiItemText= utilMemoryBufferGetString( title );
370 ami.amiKey= (char *)0;
371 ami.amiKeyText= (char *)0;
372 ami.amiCallback= (APP_MENU_CALLBACK_T)appDocToFront;
373
374 appSetToggleMenuItem( menu, &(ed->edToplevel), &ami, (void *)ed );
375 }
376
appSetDocument(EditApplication * ea,EditDocument * newEd)377 void appSetDocument( EditApplication * ea,
378 EditDocument * newEd )
379 {
380 EditDocument ** fresh;
381 int i;
382
383 fresh= (EditDocument **)realloc( ea->eaOpenDocuments,
384 ( ea->eaOpenCount+ 1 )* sizeof(EditDocument *) );
385 if ( ! fresh )
386 { XDEB(fresh); return; }
387
388 fresh[ea->eaOpenCount]= newEd;
389 ea->eaOpenDocuments= fresh;
390
391 for ( i= 0; i < ea->eaOpenCount; i++ )
392 {
393 appAppSetWindowsOption( ea->eaOpenDocuments[i]->edWindowMenu,
394 newEd, &(newEd->edTitle) );
395
396 appAppSetWindowsOption( newEd->edWindowMenu,
397 ea->eaOpenDocuments[i],
398 &(ea->eaOpenDocuments[i]->edTitle) );
399 }
400
401 appAppSetWindowsOption( ea->eaWinMenu, newEd, &(newEd->edTitle) );
402
403 ea->eaOpenCount++;
404
405 return;
406 }
407
408 /************************************************************************/
409
appDetermineBoolean(int * pIval,const char * sVal)410 int appDetermineBoolean( int * pIval,
411 const char * sVal )
412 {
413 if ( sVal &&
414 *pIval == 0 )
415 {
416 if ( ! strcmp( sVal, "0" ) )
417 { *pIval= -1; }
418 if ( ! strcmp( sVal, "1" ) )
419 { *pIval= 1; }
420
421 if ( *pIval == 0 )
422 { SDEB(sVal); }
423 }
424
425 return 0;
426 }
427
428 /************************************************************************/
429 /* */
430 /* Generic editor type application main(). */
431 /* */
432 /* 1) Make an application shell. */
433 /* 1b) Obtain resource values. */
434 /* 2) Remember X11 properties. */
435 /* 3) Remember Window manager properties. */
436 /* */
437 /************************************************************************/
438
439 static AppConfigurableResource APP_ApplicationResourceTable[]=
440 {
441 APP_RESOURCE( "unit",
442 offsetof(EditApplication,eaUnitString),
443 "inch" ),
444 APP_RESOURCE( "paper",
445 offsetof(EditApplication,eaPaperString),
446 "letter" ),
447 APP_RESOURCE( "leftMargin",
448 offsetof(EditApplication,eaLeftMarginString),
449 "90pt" ),
450 APP_RESOURCE( "rightMargin",
451 offsetof(EditApplication,eaRightMarginString),
452 "90pt" ),
453 APP_RESOURCE( "topMargin",
454 offsetof(EditApplication,eaTopMarginString),
455 "72pt" ),
456 APP_RESOURCE( "bottomMargin",
457 offsetof(EditApplication,eaBottomMarginString),
458 "72pt" ),
459 APP_RESOURCE( "magnification",
460 offsetof(EditApplication,eaMagnificationString),
461 "100%" ),
462
463 APP_RESOURCE( "usePostScriptFilters",
464 offsetof(EditApplication,eaUsePostScriptFiltersString),
465 "1" ),
466 APP_RESOURCE( "usePostScriptIndexedImages",
467 offsetof(EditApplication,eaUsePostScriptIndexedImagesString),
468 "1" ),
469 APP_RESOURCE( "sevenBitsPostScript",
470 offsetof(EditApplication,ea7BitsPostScriptString),
471 "0" ),
472
473 APP_RESOURCE( "skipEmptyPages",
474 offsetof(EditApplication,eaSkipEmptyPagesString),
475 "0" ),
476 APP_RESOURCE( "skipBlankPages",
477 offsetof(EditApplication,eaSkipBlankPagesString),
478 "0" ),
479 APP_RESOURCE( "omitHeadersOnEmptyPages",
480 offsetof(EditApplication,eaOmitHeadersOnEmptyPagesString),
481 "0" ),
482 APP_RESOURCE( "customPsSetupFilename",
483 offsetof(EditApplication,eaCustomPsSetupFilename),
484 (char *)0 ),
485
486 APP_RESOURCE( "avoidFontconfig",
487 offsetof(EditApplication,eaAvoidFontconfigString),
488 "0" ),
489 APP_RESOURCE( "preferBase35Fonts",
490 offsetof(EditApplication,eaPreferBase35FontsString),
491 "0" ),
492 APP_RESOURCE( "embedFonts",
493 offsetof(EditApplication,eaEmbedFontsString),
494 "1" ),
495 APP_RESOURCE( "useKerning",
496 offsetof(EditApplication,eaUseKerningString),
497 "1" ),
498 APP_RESOURCE( "styleTool",
499 offsetof(EditApplication,eaStyleToolString),
500 "1" ),
501
502 APP_RESOURCE( "leftRulerWidthMM",
503 offsetof(EditApplication,eaLeftRulerWidthMMString),
504 (char *)0 ),
505 APP_RESOURCE( "topRulerHeightMM",
506 offsetof(EditApplication,eaTopRulerHeightMMString),
507 (char *)0 ),
508 APP_RESOURCE( "rightRulerWidthMM",
509 offsetof(EditApplication,eaRightRulerWidthMMString),
510 (char *)0 ),
511 APP_RESOURCE( "bottomRulerHeightMM",
512 offsetof(EditApplication,eaBottomRulerHeightMMString),
513 (char *)0 ),
514
515 APP_RESOURCE( "author",
516 offsetof(EditApplication,eaAuthor),
517 (char *)0 ),
518
519 APP_RESOURCE( "afmDirectory",
520 offsetof(EditApplication,eaAfmDirectory),
521 AFMDIR ),
522 APP_RESOURCE( "fontDirectory",
523 offsetof(EditApplication,eaFontDirectory),
524 (char *)0 ),
525 APP_RESOURCE( "ghostscriptFontmap",
526 offsetof(EditApplication,eaGhostscriptFontmap),
527 (char *)0 ),
528 APP_RESOURCE( "ghostscriptFontToXmapping",
529 offsetof(EditApplication,eaGhostscriptFontToXmapping),
530 (char *)0 ),
531 APP_RESOURCE( "customPrintCommand",
532 offsetof(EditApplication,eaCustomPrintCommand),
533 (char *)0 ),
534 APP_RESOURCE( "customPrinterName",
535 offsetof(EditApplication,eaCustomPrinterName),
536 (char *)0 ),
537 APP_RESOURCE( "customPrintCommand2",
538 offsetof(EditApplication,eaCustomPrintCommand2),
539 (char *)0 ),
540 APP_RESOURCE( "customPrinterName2",
541 offsetof(EditApplication,eaCustomPrinterName2),
542 (char *)0 ),
543 };
544
545 /************************************************************************/
546 /* */
547 /* Initialize geometry related settings for the application. */
548 /* */
549 /************************************************************************/
550
appDetermineGeometrySettings(EditApplication * ea)551 static void appDetermineGeometrySettings( EditApplication * ea )
552 {
553 int paperFormat;
554
555 ea->eaUnitInt= appUnitTypeInt( ea->eaUnitString );
556 if ( ea->eaUnitInt < 0 )
557 { SDEB(ea->eaUnitString); ea->eaUnitInt= UNITtyINCH; }
558
559 ea->eaMagnification= 1.2;
560 if ( ea->eaMagnificationString )
561 {
562 double mag= 0.0;
563 char c;
564 int res;
565
566 res= sscanf( ea->eaMagnificationString, "%lg%c", &mag, &c );
567 if ( res == 1 )
568 { ea->eaMagnification= mag; }
569 if ( res == 2 && c == '%' )
570 { ea->eaMagnification= mag/100.0; }
571
572 if ( mag < 0.1 ||
573 ea->eaMagnification < 0.1 ||
574 ea->eaMagnification > 10.0 )
575 {
576 SFDEB(ea->eaMagnificationString,mag);
577 ea->eaMagnification= 1.2;
578 }
579 }
580
581 if ( utilPaperSizeFromString( &paperFormat,
582 &(ea->eaDefaultDocumentGeometry.dgPageWideTwips),
583 &(ea->eaDefaultDocumentGeometry.dgPageHighTwips),
584 ea->eaUnitInt, ea->eaPaperString ) < 0 )
585 { SDEB(ea->eaPaperString); }
586
587 if ( ea->eaLeftMarginString )
588 {
589 if ( geoLengthFromString( ea->eaLeftMarginString, ea->eaUnitInt,
590 &(ea->eaDefaultDocumentGeometry.dgLeftMarginTwips) ) )
591 { SDEB(ea->eaLeftMarginString); }
592 }
593
594 if ( ea->eaRightMarginString )
595 {
596 if ( geoLengthFromString( ea->eaRightMarginString, ea->eaUnitInt,
597 &(ea->eaDefaultDocumentGeometry.dgRightMarginTwips) ) )
598 { SDEB(ea->eaRightMarginString); }
599 }
600
601 if ( ea->eaTopMarginString )
602 {
603 if ( geoLengthFromString( ea->eaTopMarginString, ea->eaUnitInt,
604 &(ea->eaDefaultDocumentGeometry.dgTopMarginTwips) ) )
605 { SDEB(ea->eaTopMarginString); }
606 }
607
608 if ( ea->eaBottomMarginString )
609 {
610 if ( geoLengthFromString( ea->eaBottomMarginString, ea->eaUnitInt,
611 &(ea->eaDefaultDocumentGeometry.dgBottomMarginTwips) ) )
612 { SDEB(ea->eaBottomMarginString); }
613 }
614
615 if ( ea->eaLeftRulerWidthMMString )
616 {
617 utilArgToInt( &(ea->eaLeftRulerWidthMM),
618 ea->eaLeftRulerWidthMMString );
619 }
620 if ( ea->eaRightRulerWidthMMString )
621 {
622 utilArgToInt( &(ea->eaRightRulerWidthMM),
623 ea->eaRightRulerWidthMMString );
624 }
625 if ( ea->eaTopRulerHeightMMString )
626 {
627 utilArgToInt( &(ea->eaTopRulerHeightMM),
628 ea->eaTopRulerHeightMMString );
629 }
630 if ( ea->eaBottomRulerHeightMMString )
631 {
632 utilArgToInt( &(ea->eaBottomRulerHeightMM),
633 ea->eaBottomRulerHeightMMString );
634 }
635
636 return;
637 }
638
639 /************************************************************************/
640 /* */
641 /* Resolve application resources. */
642 /* */
643 /* 9) Theoretically a program could have more than one application */
644 /* object. This has never beem tested. The use of a single */
645 /* table and different flags to check for reuse here is one of the */
646 /* things to fix. */
647 /* */
648 /************************************************************************/
649
appGetApplicationResourceValues(EditApplication * ea)650 void appGetApplicationResourceValues( EditApplication * ea )
651 {
652 /* b */
653 if ( ! ea->eaGotResourceTable )
654 {
655 appGuiGetResourceValues( &(ea->eaGotResourceTable), ea,
656 ea->eaResourceData,
657 ea->eaResourceTable,
658 ea->eaResourceCount );
659 }
660
661 if ( ! ea->eaGotFileMessageResourceTable )
662 {
663 appGuiGetResourceValues( &(ea->eaGotFileMessageResourceTable), ea,
664 &(ea->eaFileMessageResources),
665 ea->eaFileMessageResourceTable,
666 ea->eaFileMessageResourceCount );
667 }
668
669 /* 9 */
670 if ( ! ea->eaGotApplicationResources )
671 {
672 appGuiGetResourceValues( &(ea->eaGotApplicationResources), ea,
673 (void *)ea,
674 APP_ApplicationResourceTable,
675 sizeof(APP_ApplicationResourceTable)/
676 sizeof(AppConfigurableResource) );
677 }
678
679 appDetermineBoolean( &(ea->eaUsePostScriptFiltersInt),
680 ea->eaUsePostScriptFiltersString );
681 appDetermineBoolean( &(ea->eaUsePostScriptIndexedImagesInt),
682 ea->eaUsePostScriptIndexedImagesString );
683 appDetermineBoolean( &(ea->ea7BitsPostScriptInt),
684 ea->ea7BitsPostScriptString );
685 appDetermineBoolean( &(ea->eaSkipEmptyPagesInt),
686 ea->eaSkipEmptyPagesString );
687 appDetermineBoolean( &(ea->eaSkipBlankPagesInt),
688 ea->eaSkipBlankPagesString );
689 appDetermineBoolean( &(ea->eaOmitHeadersOnEmptyPagesInt),
690 ea->eaOmitHeadersOnEmptyPagesString );
691 appDetermineBoolean( &(ea->eaAvoidFontconfigInt),
692 ea->eaAvoidFontconfigString );
693 appDetermineBoolean( &(ea->eaPreferBase35FontsInt),
694 ea->eaPreferBase35FontsString );
695 appDetermineBoolean( &(ea->eaEmbedFontsInt),
696 ea->eaEmbedFontsString );
697 appDetermineBoolean( &(ea->eaUseKerningInt),
698 ea->eaUseKerningString );
699 appDetermineBoolean( &(ea->eaStyleToolInt),
700 ea->eaStyleToolString );
701
702 appDetermineGeometrySettings( ea );
703
704 return;
705 }
706
707 /************************************************************************/
708 /* */
709 /* Fill the application main widget. */
710 /* */
711 /************************************************************************/
712
appFinishApplicationWindow(EditApplication * ea)713 static int appFinishApplicationWindow( EditApplication * ea )
714 {
715 APP_BITMAP_IMAGE pixmap= (APP_BITMAP_IMAGE)0;
716 APP_BITMAP_MASK mask= (APP_BITMAP_MASK)0;
717
718 APP_WIDGET pictureLabel= (APP_WIDGET)0;
719 APP_WIDGET label;
720
721 appGuiInsertColumnInWindow( &(ea->eaMainWindow),
722 ea->eaToplevel.atTopWidget );
723
724 appGuiInsertMenubarInColumn( &(ea->eaMenuBar), ea->eaMainWindow );
725
726 ea->eaFileMenu= appMakeMenu( &(ea->eaFileMenuButton),
727 &(ea->eaToplevel), ea, ea->eaMenuBar,
728 *(ea->eaAppFileMenuText), 0,
729 ea->eaAppFileMenuItems, ea->eaAppFileMenuItemCount,
730 (void *)ea );
731
732 ea->eaWinMenu= appMakeMenu( &(ea->eaWinMenuButton),
733 &(ea->eaToplevel), ea, ea->eaMenuBar,
734 *(ea->eaAppWinMenuText), 0,
735 ea->eaAppWinMenuItems, ea->eaAppWinMenuItemCount,
736 (void *)ea );
737
738 if ( ea->eaMakePrivateApplicationMenus )
739 { (*ea->eaMakePrivateApplicationMenus)( ea, ea->eaMenuBar ); }
740
741 if ( ea->eaAppHelpMenuItems )
742 {
743 ea->eaHelpMenu= appMakeMenu( &(ea->eaHelpMenuButton),
744 &(ea->eaToplevel), ea, ea->eaMenuBar,
745 *(ea->eaAppHelpMenuText), 1,
746 ea->eaAppHelpMenuItems, ea->eaAppHelpMenuItemCount,
747 (void *)ea );
748 }
749
750 # ifdef USE_MOTIF
751 /* Work around BUG in LessTif */
752 {
753 Dimension high;
754
755 XtVaGetValues( ea->eaMenuBar,
756 XmNheight, &high,
757 NULL );
758 if ( high < 8 )
759 {
760 XtWidgetGeometry preferred;
761
762 XtQueryGeometry( ea->eaMenuBar, (XtWidgetGeometry *)0, &preferred );
763
764 high= preferred.height+ preferred.border_width;
765 XtVaSetValues( ea->eaMenuBar,
766 XmNheight, high,
767 NULL );
768 }
769 }
770 # endif
771
772 if ( ea->eaMainPicture )
773 {
774 APP_BITMAP_IMAGE labelPixmap;
775 APP_BITMAP_MASK labelMask;
776
777 if ( ! appGetImagePixmap( ea, ea->eaMainPicture,
778 &labelPixmap, &labelMask ) )
779 {
780 appMakeImageInColumn( &pictureLabel, ea->eaMainWindow,
781 labelPixmap, labelMask );
782 }
783 }
784
785 if ( ea->eaNameAndVersion )
786 {
787 char * ident= (char *)0;
788
789
790 if ( 0 && ea->eaPlatformCompiled )
791 {
792 ident= malloc( strlen( ea->eaNameAndVersion )+ 3+
793 strlen( ea->eaPlatformCompiled )+ 1 );
794 if ( ! ident )
795 { XDEB(ident); }
796 else{
797 sprintf( ident, "%s - %s",
798 ea->eaNameAndVersion, ea->eaPlatformCompiled );
799 }
800 }
801 else{
802 ident= strdup( ea->eaNameAndVersion );
803 }
804
805 if ( ! ident )
806 { XDEB(ident); }
807 else{
808 appMakeLabelInColumn( &label, ea->eaMainWindow, ident );
809
810 free( ident );
811 }
812 }
813
814 if ( ea->eaReference )
815 {
816 appMakeLabelInColumn( &label, ea->eaMainWindow,
817 ea->eaReference );
818 }
819
820 if ( ea->eaMainIcon &&
821 appGetImagePixmap( ea, ea->eaMainIcon, &pixmap, &mask ) )
822 { SDEB(ea->eaMainIcon); return -1; }
823
824 if ( pixmap )
825 {
826 # ifdef USE_MOTIF
827 XtVaSetValues( ea->eaToplevel.atTopWidget,
828 XmNiconPixmap, pixmap,
829 NULL );
830 # endif
831 # ifdef USE_GTK
832 gdk_window_set_icon( ea->eaToplevel.atTopWidget->window,
833 ea->eaToplevel.atTopWidget->window,
834 pixmap, mask );
835 # endif
836 }
837
838 return 0;
839 }
840
841 /************************************************************************/
842
app_version(EditApplication * ea,const char * prog,const char * call,int argc,char ** argv)843 static int app_version( EditApplication * ea,
844 const char * prog,
845 const char * call,
846 int argc,
847 char ** argv )
848 {
849 printf( "%s\n", ea->eaNameAndVersion );
850 return 0;
851 }
852
app_platform(EditApplication * ea,const char * prog,const char * call,int argc,char ** argv)853 static int app_platform( EditApplication * ea,
854 const char * prog,
855 const char * call,
856 int argc,
857 char ** argv )
858 {
859 printf( "%s\n", ea->eaPlatformCompiled );
860 return 0;
861 }
862
app_build(EditApplication * ea,const char * prog,const char * call,int argc,char ** argv)863 static int app_build( EditApplication * ea,
864 const char * prog,
865 const char * call,
866 int argc,
867 char ** argv )
868 {
869 printf( "%s\n", ea->eaHostDateCompiled );
870 return 0;
871 }
872
app_fullVersion(EditApplication * ea,const char * prog,const char * call,int argc,char ** argv)873 static int app_fullVersion( EditApplication * ea,
874 const char * prog,
875 const char * call,
876 int argc,
877 char ** argv )
878 {
879 printf( "%s %s %s %s\n",
880 ea->eaNameAndVersion,
881 ea->eaOptionalComponents,
882 ea->eaPlatformCompiled,
883 ea->eaHostDateCompiled );
884
885 return 0;
886 }
887
app_saveTo(EditApplication * ea,const char * prog,const char * call,int argc,char ** argv)888 static int app_saveTo( EditApplication * ea,
889 const char * prog,
890 const char * call,
891 int argc,
892 char ** argv )
893 {
894 int rval= 2;
895
896 MemoryBuffer a0;
897 MemoryBuffer a1;
898
899 utilInitMemoryBuffer( &a0 );
900 utilInitMemoryBuffer( &a1 );
901
902 if ( argc < 2 )
903 { SLDEB(call,argc); rval= -1; goto ready; }
904
905 if ( utilMemoryBufferSetString( &a0, argv[0] ) )
906 { LDEB(1); rval= -1; goto ready; }
907 if ( utilMemoryBufferSetString( &a1, argv[1] ) )
908 { LDEB(1); rval= -1; goto ready; }
909
910 if ( appFileConvert( ea, &a0, &a1 ) )
911 { SSSDEB(call,argv[0],argv[1]); rval= -1; goto ready; }
912
913 ready:
914
915 utilCleanMemoryBuffer( &a0 );
916 utilCleanMemoryBuffer( &a1 );
917
918 return rval;
919 }
920
app_printToFile(EditApplication * ea,const char * prog,const char * call,int argc,char ** argv)921 static int app_printToFile( EditApplication * ea,
922 const char * prog,
923 const char * call,
924 int argc,
925 char ** argv )
926 {
927 if ( argc < 2 )
928 { SLDEB(call,argc); return -1; }
929
930 if ( appPrintToFile( ea, argv[0], argv[1], (const char *)0 ) )
931 { SSSDEB(call,argv[0],argv[1]); return -1; }
932
933 return 2;
934 }
935
app_printToFilePaper(EditApplication * ea,const char * prog,const char * call,int argc,char ** argv)936 static int app_printToFilePaper( EditApplication * ea,
937 const char * prog,
938 const char * call,
939 int argc,
940 char ** argv )
941 {
942 if ( argc < 3 )
943 { SLDEB(call,argc); return -1; }
944
945 if ( appPrintToFile( ea, argv[0], argv[1], argv[2] ) )
946 { SSSDEB(call,argv[0],argv[2]); return -1; }
947
948 return 3;
949 }
950
app_print(EditApplication * ea,const char * prog,const char * call,int argc,char ** argv)951 static int app_print( EditApplication * ea,
952 const char * prog,
953 const char * call,
954 int argc,
955 char ** argv )
956 {
957 if ( argc < 1 )
958 { SLDEB(call,argc); return -1; }
959
960 if ( appPrintToPrinter( ea, argv[0], (const char *)0, (const char *)0 ) )
961 { SSDEB(call,argv[0]); return -1; }
962
963 return 1;
964 }
965
app_printPaper(EditApplication * ea,const char * prog,const char * call,int argc,char ** argv)966 static int app_printPaper( EditApplication * ea,
967 const char * prog,
968 const char * call,
969 int argc,
970 char ** argv )
971 {
972 if ( argc < 2 )
973 { SLDEB(call,argc); return -1; }
974
975 if ( appPrintToPrinter( ea, argv[0], (const char *)0, argv[1] ) )
976 { SSDEB(call,argv[0]); return -1; }
977
978 return 2;
979 }
980
app_printToPrinter(EditApplication * ea,const char * prog,const char * call,int argc,char ** argv)981 static int app_printToPrinter( EditApplication * ea,
982 const char * prog,
983 const char * call,
984 int argc,
985 char ** argv )
986 {
987 if ( argc < 2 )
988 { SLDEB(call,argc); return -1; }
989
990 if ( appPrintToPrinter( ea, argv[0], argv[1], (const char *)0 ) )
991 { SSDEB(call,argv[0]); return -1; }
992
993 return 2;
994 }
995
app_printToPrinterPaper(EditApplication * ea,const char * prog,const char * call,int argc,char ** argv)996 static int app_printToPrinterPaper(
997 EditApplication * ea,
998 const char * prog,
999 const char * call,
1000 int argc,
1001 char ** argv )
1002 {
1003 if ( argc < 3 )
1004 { SLDEB(call,argc); return -1; }
1005
1006 if ( appPrintToPrinter( ea, argv[0], argv[1], argv[2] ) )
1007 { SSDEB(call,argv[0]); return -1; }
1008
1009 return 3;
1010 }
1011
1012 static const SpecialCall AppSpecialCalls[]=
1013 {
1014 { "version", app_version, },
1015 { "platform", app_platform, },
1016 { "build", app_build, },
1017 { "fullVersion", app_fullVersion, },
1018 { "saveTo", app_saveTo, },
1019 { "printToFile", app_printToFile, },
1020 { "printToFilePaper", app_printToFilePaper, },
1021 { "print", app_print, },
1022 { "printPaper", app_printPaper, },
1023 { "printToPrinter", app_printToPrinter, },
1024 { "printToPrinterPaper", app_printToPrinterPaper, },
1025 };
1026
1027 static const int AppSpecialCallCount= sizeof(AppSpecialCalls)/sizeof(SpecialCall);
1028
1029 /************************************************************************/
1030 /* */
1031 /* Handle Special Calls. */
1032 /* */
1033 /* 1) It is not necessary to initialize TedApplication to convert */
1034 /* files. Intercept conversion calls to prevent the program from */
1035 /* becoming interactive. NOTE that the calls differ from the calls */
1036 /* that initialize the application: They begin with -- instead of */
1037 /* ++ . To override configurable options, the ++Something calls */
1038 /* should be used. */
1039 /* */
1040 /************************************************************************/
1041
appGetSpecialCall(const SpecialCall * calls,int callCount,const char * call)1042 static const SpecialCall * appGetSpecialCall(
1043 const SpecialCall * calls,
1044 int callCount,
1045 const char * call )
1046 {
1047 int c;
1048
1049 for ( c= 0; c < callCount; calls++, c++ )
1050 {
1051 if ( ! strcmp( call, calls->scCall ) )
1052 { return calls; }
1053 }
1054
1055 return (SpecialCall *)0;
1056 }
1057
appMainHandleSpecialCalls(EditApplication * ea,const char * prefix,int getResources,const char * prog,int argc,char * argv[])1058 static int appMainHandleSpecialCalls( EditApplication * ea,
1059 const char * prefix,
1060 int getResources,
1061 const char * prog,
1062 int argc,
1063 char * argv[] )
1064 {
1065 int prefixLength= strlen( prefix );
1066 int done= 0;
1067
1068 if ( argc < 1 )
1069 { return 0; }
1070
1071 while( done < argc )
1072 {
1073 const char * call;
1074 const SpecialCall * sc;
1075 int args;
1076 int off;
1077
1078 if ( strncmp( argv[done], prefix, prefixLength ) )
1079 { break; }
1080
1081 call= argv[done]+ prefixLength;
1082 sc= appGetSpecialCall( ea->eaSpecialCalls,
1083 ea->eaSpecialCallCount, call );
1084 if ( ! sc )
1085 {
1086 sc= appGetSpecialCall( AppSpecialCalls,
1087 AppSpecialCallCount, call );
1088 }
1089 if ( ! sc )
1090 { break; }
1091
1092 if ( getResources )
1093 {
1094 appGetApplicationResourceValues( ea );
1095 getResources= 0;
1096 }
1097
1098 off= done+ 1;
1099 args= (*sc->scExecuteCall)( ea, prog, call, argc- off, argv+ off );
1100 if ( args < 0 )
1101 { SLDEB(argv[1+done],args); return -1; }
1102 done += 1+ args;
1103 }
1104
1105 return done;
1106 }
1107
1108 /************************************************************************/
1109 /* */
1110 /* Use the contents of /etc/papersize as the default papersize. */
1111 /* */
1112 /************************************************************************/
1113
appDefaultPapersize(EditApplication * ea)1114 static void appDefaultPapersize( EditApplication * ea )
1115 {
1116 const char * defsz= utilPaperDefaultSize();
1117
1118 if ( defsz )
1119 {
1120 if ( appSetSystemProperty( ea, "paper", defsz ) )
1121 { SDEB(defsz); }
1122 }
1123
1124 return;
1125 }
1126
1127 /************************************************************************/
1128
appOpenExistingDocument(EditApplication * ea,int readOnly,int formatHint,const MemoryBuffer * filename)1129 static int appOpenExistingDocument( EditApplication * ea,
1130 int readOnly,
1131 int formatHint,
1132 const MemoryBuffer * filename )
1133 {
1134 int rval= 0;
1135 const MemoryBuffer * const fileRelativeTo= (const MemoryBuffer *)0;
1136 int relativeIsFile= 1;
1137 EditDocument * ed;
1138
1139 MemoryBuffer absolute;
1140
1141 const int suggestStdin= 0;
1142
1143 utilInitMemoryBuffer( &absolute );
1144
1145 if ( appAbsoluteName( &absolute,
1146 filename, relativeIsFile, fileRelativeTo ) < 0 )
1147 {
1148 SDEB(utilMemoryBufferGetString(filename));
1149 ed= appOpenDocumentFile( ea, ea->eaToplevel.atTopWidget, (APP_WIDGET)0,
1150 readOnly, suggestStdin, formatHint, filename );
1151 }
1152 else{
1153 ed= appOpenDocumentFile( ea, ea->eaToplevel.atTopWidget, (APP_WIDGET)0,
1154 readOnly, suggestStdin, formatHint, &absolute );
1155 }
1156
1157 if ( ! ed )
1158 { XDEB(ed); rval= -1; }
1159
1160 utilCleanMemoryBuffer( &absolute );
1161
1162 return rval;
1163 }
1164
1165 /************************************************************************/
1166
appSetProperties(EditApplication * ea,int argc,char * argv[])1167 static int appSetProperties( EditApplication * ea,
1168 int argc,
1169 char * argv[] )
1170 {
1171 int arg;
1172 int argTo= 1;
1173
1174 for ( arg= 1; arg < argc; arg++ )
1175 {
1176 if ( arg+ 3 <= argc &&
1177 ! strcmp( argv[arg], "--setProperty" ) )
1178 {
1179 if ( appSetUserProperty( ea, argv[arg+ 1], argv[arg+ 2] ) )
1180 { SSDEB(argv[arg+ 1], argv[arg+ 2]); return -1; }
1181
1182 arg += 2; continue;
1183 }
1184
1185 if ( ! strncmp( argv[arg], "--", 2 ) )
1186 {
1187 char * eq= strchr( argv[arg], '=' );
1188
1189 if ( eq )
1190 {
1191 int res;
1192
1193 *eq= '\0';
1194 res= appSetUserProperty( ea, argv[arg]+ 2, eq+ 1 );
1195 *eq= '=';
1196
1197 if ( res )
1198 { SDEB(argv[arg]); return -1; }
1199
1200 continue;
1201 }
1202 }
1203
1204 argv[argTo++]= argv[arg];
1205 }
1206
1207 return argTo;
1208 }
1209
1210 /************************************************************************/
1211 /* */
1212 /* Generic main() procedure. */
1213 /* */
1214 /* 1) Connect to the GUI system. */
1215 /* 2) Retrieve resource values and derive some application wide */
1216 /* settings from them. */
1217 /* 3) Do not die too easily. */
1218 /* And try to be immune for shells that make you sensitive for */
1219 /* signals that an X11 application does not want to know about. */
1220 /* */
1221 /************************************************************************/
1222
appMain(EditApplication * ea,int argc,char * argv[])1223 int appMain( EditApplication * ea,
1224 int argc,
1225 char * argv[] )
1226 {
1227 int rval= 0;
1228
1229 int arg;
1230 int res;
1231 int didSpecial= 0;
1232 char * prog;
1233 char * locale= (char *)0;
1234
1235 MemoryBuffer filename;
1236 MemoryBuffer absolute;
1237 MemoryBuffer ext;
1238
1239 utilInitMemoryBuffer( &filename );
1240 utilInitMemoryBuffer( &absolute );
1241 utilInitMemoryBuffer( &ext );
1242
1243 locale= setlocale( LC_ALL, "" );
1244 if ( locale )
1245 {
1246 char * s= locale;
1247 while( isalpha( *s ) || *s == '_' )
1248 { s++; }
1249
1250 if ( s > locale )
1251 {
1252 int len= s- locale;
1253
1254 ea->eaLocaleName= malloc( len+ 1 );
1255 if ( ! ea->eaLocaleName )
1256 { LXDEB(len,ea->eaLocaleName); return -1; }
1257
1258 strncpy( ea->eaLocaleName, locale, len )[len]= '\0';
1259 }
1260 }
1261
1262 appDefaultPapersize( ea );
1263
1264 res= appReadUserProperties( ea );
1265 if ( res )
1266 { LDEB(res); rval= 1; goto ready; }
1267
1268 res= appReadSystemProperties( ea );
1269 if ( res )
1270 { LDEB(res); rval= 1; goto ready; }
1271
1272 res= appSetProperties( ea, argc, argv );
1273 if ( res < 0 )
1274 { LDEB(res); rval= 1; goto ready; }
1275 argc= res;
1276
1277 prog= argv[0];
1278 res= appMainHandleSpecialCalls( ea, "--", 1, prog, argc- 1, argv+ 1 );
1279 if ( res < 0 )
1280 { LDEB(res); rval= 1; goto ready; }
1281 if ( res > 0 )
1282 { didSpecial= 1; argc -= res; argv += res; argv[0]= prog; }
1283
1284 if ( argc <= 1 && didSpecial )
1285 { goto ready; }
1286
1287 utilInitDocumentGeometry( &(ea->eaDefaultDocumentGeometry) );
1288
1289 /* b */
1290 appGetApplicationResourceValues( ea );
1291
1292 /* 1 */
1293 if ( appGuiInitApplication( ea, &argc, &argv ) )
1294 { LDEB(1); rval= 1; goto ready; }
1295
1296 if ( ea->eaToplevel.atTopWidget )
1297 { appGetPixelsPerTwip( ea ); }
1298
1299 if ( appFinishApplicationWindow( ea ) )
1300 { LDEB(1); rval= -1; goto ready; }
1301
1302 appAllocateCopyPasteTargetAtoms( ea );
1303
1304 # ifdef USE_MOTIF
1305 if ( ea->eaAppSelectionTypeCount > 0 )
1306 {
1307 XtAddEventHandler( ea->eaToplevel.atTopWidget,
1308 PropertyChangeMask, True, appAppGotPasteCall, ea );
1309 }
1310 # endif
1311
1312 res= appMainHandleSpecialCalls( ea, "++", 0, prog, argc- 1, argv+ 1 );
1313 if ( res < 0 )
1314 { LDEB(res); rval= 1; goto ready; }
1315 if ( res > 0 )
1316 { didSpecial= 1; argc -= res; argv += res; argv[0]= prog; }
1317
1318 if ( argc <= 1 && didSpecial )
1319 { goto ready; }
1320
1321 /* 3 */
1322 (void) signal( SIGHUP, SIG_IGN );
1323 (void) signal( SIGINT, SIG_IGN );
1324 # ifdef SIGWINCH
1325 (void) signal( SIGWINCH, SIG_IGN );
1326 # endif
1327
1328 for ( arg= 1; arg < argc; arg++ )
1329 {
1330 const int readOnly= 0;
1331 AppFileMessageResources * afmr= &(ea->eaFileMessageResources);
1332
1333 int suggestStdin= 0;
1334 int openFormat= -1;
1335
1336 if ( utilMemoryBufferSetString( &filename, argv[arg] ) )
1337 { LDEB(1); rval= 1; goto ready; }
1338
1339 if ( ! appTestDirectory( &filename ) )
1340 {
1341 appRunOpenChooser( (APP_WIDGET)0, ea->eaToplevel.atTopWidget,
1342 ea->eaFileExtensionCount, ea->eaFileExtensions,
1343 ea->eaDefaultFileFilter, &filename,
1344 appChooserOpenDocument, ea, (void *)ea );
1345
1346 continue;
1347 }
1348
1349 openFormat= appDocumentGetOpenFormat( &suggestStdin,
1350 ea->eaFileExtensions, ea->eaFileExtensionCount,
1351 &filename, openFormat );
1352
1353 if ( appTestFileExists( &filename ) )
1354 {
1355 int createNew= ea->eaCreateNewFromCommand;
1356
1357 int saveFormat= -1;
1358 int suggestStdout= 0;
1359
1360 if ( argc == 2 && openFormat >= 0 && suggestStdin )
1361 {
1362 appOpenDocumentFile( ea,
1363 ea->eaToplevel.atTopWidget, (APP_WIDGET)0,
1364 readOnly, suggestStdin, openFormat, &filename );
1365
1366 continue;
1367 }
1368
1369 saveFormat= appDocumentGetSaveFormat( &suggestStdout, ea,
1370 &filename, (void *)0,
1371 APPFILE_CAN_SAVE, saveFormat );
1372 if ( saveFormat < 0 || suggestStdout )
1373 { createNew= 0; }
1374
1375 if ( createNew )
1376 {
1377 int ynRes;
1378
1379 ynRes= appQuestionRunSubjectYesNoDialog( ea,
1380 ea->eaToplevel.atTopWidget, (APP_WIDGET)0,
1381 argv[arg], afmr->afmrMakeItQuestion );
1382
1383 if ( ynRes == AQDrespYES )
1384 {
1385 if ( appNewDocument( ea, &filename ) )
1386 { SDEB(argv[arg]); }
1387 }
1388 }
1389 else{
1390 appQuestionRunFilenameErrorDialog( ea,
1391 ea->eaToplevel.atTopWidget, (APP_WIDGET)0,
1392 &filename, afmr->afmrNoSuchFileMessage );
1393 }
1394 }
1395 else{
1396 (void) appOpenExistingDocument( ea,
1397 readOnly, openFormat, &filename );
1398 }
1399 }
1400
1401 if ( ea->eaVisibleDocumentCount > 0 )
1402 { appHideShellWidget( ea->eaToplevel.atTopWidget ); }
1403 else{ appShowShellWidget( ea, ea->eaToplevel.atTopWidget ); }
1404
1405 # ifdef USE_MOTIF
1406 XtAppMainLoop( ea->eaContext );
1407 # endif
1408
1409 # ifdef USE_GTK
1410 gtk_main();
1411 # endif
1412
1413 # ifdef USE_QT
1414 appRunMainLoop( ea );
1415 # endif
1416
1417 ready:
1418
1419 utilCleanMemoryBuffer( &filename );
1420 utilCleanMemoryBuffer( &absolute );
1421 utilCleanMemoryBuffer( &ext );
1422
1423 return rval;
1424 }
1425