Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / examples / dtwidget / editor.c
1 /* $TOG: editor.c /main/4 1998/04/02 18:18:47 rafi $ */
2 /*
3  *  (c) Copyright 1993, 1994 Hewlett-Packard Company
4  *  (c) Copyright 1993, 1994 International Business Machines Corp.
5  *  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
6  *  (c) Copyright 1993, 1994 Novell, Inc.
7  */
8
9 /*
10  * editor.c
11  *
12  * A simple editor based on the DtEditor widget.
13  */
14
15 #include <stdio.h>
16 #include <locale.h>
17
18 #include <Xm/XmAll.h>
19
20 #include <Dt/Editor.h>
21
22 /*
23  * Constants
24  */
25
26 #define ApplicationClass "Editor"
27
28 /*
29  * Types
30  */
31
32 typedef struct _AppData {
33         XtAppContext appContext;
34         Display *display;
35         Widget top;
36         Widget mainWindow;
37         Widget menuBar;
38         Widget editor;
39         Widget messageTextF;
40         Widget fileSelectionBox;
41         Widget cutButton;
42         Widget copyButton;
43         Widget clearButton;
44         Widget deleteButton;
45         Widget deselectButton;
46         Widget cutPopupButton;
47         Widget copyPopupButton;
48         Boolean wordWrapOn;
49         Boolean statusLineOn;
50         Boolean overstrikeModeOn;
51 } AppData;
52
53 /*
54  * Used to specify whether data is being loaded, inserted, or saved
55  * from the editor. Used used by the FSB and its callbacks.
56  */
57
58 typedef enum _LoadSaveType {
59         LOAD_DATA,
60         INSERT_DATA,
61         SAVE_DATA
62 } LoadSaveType;
63
64 /*
65  * Data
66  */
67
68 static AppData ad;
69
70
71 /*
72  * Functions
73  */
74
75 static void SetResizeHints(void);
76 static void DisplayMessage(char *);
77 static Widget CreateMenuBar(Widget);
78 static Widget CreatePopupMenu(Widget);
79 static Widget CreateEditor(Widget);
80 static Widget CreateButton(Widget, String, char, XtCallbackProc, XtPointer);
81 static Widget CreateToggle(Widget, String, char, XtCallbackProc, XtPointer, Boolean);
82 static Widget CreateCascade(Widget, String, char, Widget);
83 static void PopupHandler(Widget, XtPointer, XEvent*, Boolean*);
84 static void SetSelectionState(Boolean);
85
86
87 /*
88  * main
89  */
90
91 void main(int argc, char **argv)
92 {
93     Arg al[10];
94     int ac;
95
96     XtSetLanguageProc( (XtAppContext)NULL, (XtLanguageProc)NULL,
97                        (XtPointer)NULL );
98
99     /* Initialize the application's data */
100     ad.fileSelectionBox = (Widget) NULL;
101     ad.wordWrapOn = False;
102     ad.statusLineOn = False;
103     ad.overstrikeModeOn = False;
104
105     /* Initialize the toolkit and open the display */
106     ad.top = XtAppInitialize(&ad.appContext, ApplicationClass, NULL, 0,
107                              &argc, argv, NULL, NULL, 0);
108     ad.display = XtDisplay(ad.top);
109
110     /* Create MainWindow. */
111     ac = 0;
112     ad.mainWindow = (Widget) XmCreateMainWindow (ad.top, "main", al, ac);
113     XtManageChild (ad.mainWindow);
114
115     /* Create MenuBar in MainWindow. */
116     ad.menuBar = CreateMenuBar(ad.mainWindow);
117     XtManageChild(ad.menuBar);
118
119     /* Create editor widget in MainWindow. */
120     ad.editor = CreateEditor(ad.mainWindow);
121     XtManageChild(ad.editor);
122     ad.messageTextF = DtEditorGetMessageTextFieldID(ad.editor);
123
124     /* Create the editor popup menu */
125     CreatePopupMenu(ad.editor);
126
127     /* Set the main window widgets. */
128     XmMainWindowSetAreas(ad.mainWindow, ad.menuBar, NULL, NULL, NULL, ad.editor);
129
130     /* Realize toplevel widget */
131     XtRealizeWidget (ad.top);
132
133     /* Set the resize increment and minimum window size properties. */
134     SetResizeHints();
135
136     /* Set up menu buttons dependent on selection */
137     SetSelectionState(False);
138
139     XtAppMainLoop(ad.appContext);
140
141
142
143 /************************************************************************
144  *
145  * Callbacks
146  *
147  ************************************************************************/
148
149 /*
150  * File menu callbacks
151  */
152
153 static void ResetEditorCb(Widget w, XtPointer cd, XtPointer cb)
154 {
155    DtEditorReset(ad.editor);
156 }
157
158 static void OpenFileCb( Widget w, XtPointer cd, XtPointer cb)
159 {
160    DtEditorErrorCode error;
161    XmFileSelectionBoxCallbackStruct *fcb = (XmFileSelectionBoxCallbackStruct *) cb;
162    LoadSaveType LoadSaveFlag = (LoadSaveType)cd;
163    char *name = (char *) XtMalloc( sizeof(char) * fcb->length + 1 );
164
165    name[0] ='\0';
166
167    /*
168     *  Get the name of the file & pass it to the editor widget
169     */
170
171    name = XmStringUnparse(fcb->value, NULL, XmCHARSET_TEXT,
172                           XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
173
174    /*
175     * Load or insert the file, as specified
176     */
177    if ( LoadSaveFlag == LOAD_DATA )
178      error = DtEditorSetContentsFromFile(ad.editor, name); 
179    else
180      error = DtEditorInsertFromFile(ad.editor, name); 
181
182    switch (error)
183    {
184      case DtEDITOR_NO_ERRORS:
185      {
186        DisplayMessage("File loaded");
187        break;
188      }
189      case DtEDITOR_NULLS_REMOVED:
190      {
191         DisplayMessage( "All embedded null characters removed from the file" );
192         break;
193      }
194      case DtEDITOR_READ_ONLY_FILE:
195      {
196        DisplayMessage( "The file is write protected" );
197        break;
198      }
199      case DtEDITOR_NONEXISTENT_FILE:
200      {
201        DisplayMessage( "Could not find file" );
202        break;
203      }
204      case DtEDITOR_DIRECTORY:
205      {
206        DisplayMessage( "The name given is a directory" );
207        break;
208      }
209      case DtEDITOR_CHAR_SPECIAL_FILE:
210      {
211        DisplayMessage( "The name given is a character special device" );
212        break;
213      }
214      case DtEDITOR_BLOCK_MODE_FILE:
215      {
216        DisplayMessage( "The name given is a block mode device");
217        break;
218      }
219      case DtEDITOR_INSUFFICIENT_MEMORY:
220      {
221        DisplayMessage( "Not enough available memory to load file");
222        break;
223      }
224      case DtEDITOR_UNREADABLE_FILE:
225      default:
226      {
227        DisplayMessage( "Could not read the file" );
228        break;
229      }
230    }
231
232    /*
233     * Remove the OK callback so it can be added again with a new value for 
234     * the LoadSaveFlag flag.
235     */
236    XtRemoveCallback(w, XmNokCallback, OpenFileCb, cd);
237
238    /*
239     * Remove the FSB dialog & clean up
240     */
241    XtUnmanageChild(w);
242    XtFree (name);
243 }
244
245
246 static void SaveAsFileCb(Widget w, XtPointer cd, XtPointer cb)
247 {
248    DtEditorContentRec   cr;
249    DtEditorErrorCode    error;
250    Boolean              overWrite = False,
251                         hardCarriageReturns = True,
252                         markContentsAsSaved = True;
253    XmFileSelectionBoxCallbackStruct *fcb = (XmFileSelectionBoxCallbackStruct *)cb;
254    LoadSaveType LoadSaveFlag = (LoadSaveType) cd;
255
256    char *name = XtMalloc(sizeof(char) * fcb->length + 1 );
257    name[0] ='\0';
258    XmStringGetLtoR(fcb->value, XmFONTLIST_DEFAULT_TAG, &name);
259
260    /*
261     * Ask the widget to save its contents to the named file.
262     */
263
264    error = DtEditorSaveContentsToFile(ad.editor, name, overWrite,
265                 hardCarriageReturns, markContentsAsSaved); 
266
267    switch(error)
268    {
269      case DtEDITOR_NO_ERRORS:
270      {
271        DisplayMessage( "The file has been saved" );
272        break;
273      }
274      case DtEDITOR_UNWRITABLE_FILE:
275      {
276        DisplayMessage( "The file is read only" ); 
277        break;
278      }
279      case DtEDITOR_WRITABLE_FILE:
280      {
281        DisplayMessage( "File not saved, it already exists" ); 
282        break;
283      }
284      case DtEDITOR_DIRECTORY:
285      {
286        DisplayMessage( "The name given is a directory" );
287        break;
288      }
289      case DtEDITOR_CHAR_SPECIAL_FILE:
290      {
291        DisplayMessage( "The name given is a character special device" );
292        break;
293      }
294      case DtEDITOR_BLOCK_MODE_FILE:
295      {
296        DisplayMessage( "The name given is a block mode device");
297        break;
298      }
299      case DtEDITOR_SAVE_FAILED:
300      default:
301      {
302        DisplayMessage( "Could not save the file.  Check disc space" );
303        break;
304      }
305    }
306
307    /*
308     * Remove the OK callback so it can be added again with a new value for 
309     * the LoadSaveFlag flag.
310     */
311    XtRemoveCallback(w, XmNokCallback, SaveAsFileCb, cd);
312
313    /*
314     * Remove the FSB dialog & clean up
315     */
316    XtUnmanageChild( w );
317    XtFree (name);
318
319 }
320
321
322 static void CancelOpenCb(Widget w, XtPointer cd, XtPointer cb)
323 {
324    /* Remove the OK callback so it can be added again with a new value for 
325     * the LoadSaveFlag flag.
326     */
327    XtRemoveCallback(w, XmNokCallback, OpenFileCb, cd);
328
329    /* Remove the FSB dialog & clean up */
330    XtUnmanageChild(w);
331 }
332
333
334 static void DisplayFsbCb(Widget w, XtPointer cd, XtPointer cb)
335 {
336   Arg al[10];
337   int ac;
338   XmString tmpStr1, tmpStr2;
339
340   LoadSaveType LoadSaveFlag = (LoadSaveType) cd;
341
342   /* Create the FSB, if we need to */
343
344   if (ad.fileSelectionBox == (Widget) NULL)
345   {
346      ac = 0;
347      ad.fileSelectionBox = XmCreateFileSelectionDialog(ad.mainWindow,
348                                                     "file_sel_dlg",
349                                                     al, ac);
350      XtAddCallback(ad.fileSelectionBox, XmNcancelCallback, CancelOpenCb,        
351                                                 (XtPointer)LoadSaveFlag);
352
353   }
354
355   /*
356    * Set FSB title & label depending up whether loading, inserting, or
357    * saving a container.
358    */
359   switch ( LoadSaveFlag )
360   {
361     case LOAD_DATA:
362     {
363       tmpStr1 = XmStringCreateLocalized("Open a File");
364       tmpStr2 = XmStringCreateLocalized("File to open");
365
366       /*
367        * Add the OK callback so the curent value of the LoadSaveFlag 
368        * flag is passed in.
369        */
370       XtAddCallback(ad.fileSelectionBox, XmNokCallback, OpenFileCb,
371                                                 (XtPointer)LoadSaveFlag);
372       break;
373     }
374
375     case INSERT_DATA:
376     {
377       tmpStr1 = XmStringCreateLocalized("Include a File");
378       tmpStr2 = XmStringCreateLocalized("File to include");
379
380       /*
381        * Add the OK callback so the curent value of the LoadSaveFlag 
382        * flag is passed in.
383        */
384       XtAddCallback(ad.fileSelectionBox, XmNokCallback, OpenFileCb,
385                                                 (XtPointer)LoadSaveFlag);
386       break;
387     }
388
389     case SAVE_DATA:
390     {
391       tmpStr1 = XmStringCreateLocalized("Save to File");
392       tmpStr2 = XmStringCreateLocalized("Save to file");
393
394       /*
395        * Add the OK callback so the save as callback is called.
396        */
397       XtAddCallback(ad.fileSelectionBox, XmNokCallback, SaveAsFileCb,
398                                                 (XtPointer)LoadSaveFlag);
399       break;
400     }
401
402     default:
403     {
404         break;
405     }
406   }
407
408   XtVaSetValues(ad.fileSelectionBox,
409         XmNdialogTitle, tmpStr1,
410         XmNselectionLabelString, tmpStr1,
411         NULL);
412
413   XmStringFree(tmpStr1);
414   XmStringFree(tmpStr2);
415
416   /* Display the FSB */
417
418   XtManageChild (ad.fileSelectionBox);
419 }
420
421
422 static void ExitCb(Widget w, XtPointer cd, XtPointer cb)
423 {
424     exit(0);
425 }
426
427 /***************************************************** 
428  *
429  * Edit menu callbacks
430  *
431  */
432
433 static void UndoCb(Widget w, XtPointer cd, XtPointer cb)
434 {
435     DtEditorUndoEdit(ad.editor); 
436 }
437
438 static void CutCb(Widget w, XtPointer cd, XtPointer cb)
439 {
440     DtEditorCutToClipboard(ad.editor); 
441 }
442
443 static void CopyCb(Widget w, XtPointer cd, XtPointer cb)
444 {
445     DtEditorCopyToClipboard(ad.editor); 
446 }
447
448 static void PasteCb(Widget w, XtPointer cd, XtPointer cb)
449 {
450     DtEditorPasteFromClipboard(ad.editor); 
451 }
452
453 static void ClearCb(Widget w, XtPointer cd, XtPointer cb)
454 {
455     DtEditorClearSelection(ad.editor);
456 }
457
458 static void DeleteCb(Widget w, XtPointer cd, XtPointer cb)
459 {
460     DtEditorDeleteSelection(ad.editor);
461 }
462
463 static void SelectAllCb(Widget w, XtPointer cd, XtPointer cb)
464 {
465     DtEditorSelectAll(ad.editor); 
466 }
467
468 static void DeselectCb(Widget w, XtPointer cd, XtPointer cb)
469 {
470     DtEditorDeselect(ad.editor); 
471 }
472
473 static void FindCb(Widget w, XtPointer cd, XtPointer cb)
474 {
475     DtEditorInvokeFindChangeDialog(ad.editor); 
476 }
477
478 static void SpellCb(Widget w, XtPointer cd, XtPointer cb)
479 {
480     DtEditorInvokeSpellDialog(ad.editor); 
481 }
482
483 /***************************************************** 
484  *
485  * Format menu callbacks
486  *
487  */
488
489 static void FormatAllCb(Widget w, XtPointer cd, XtPointer cb)
490 {
491    DtEditorFormat(ad.editor, (DtEditorFormatSettings *) NULL, 
492                   DtEDITOR_FORMAT_ALL); 
493 }
494
495 static void FormatParaCb(Widget w, XtPointer cd, XtPointer cb)
496 {
497    DtEditorFormat(ad.editor, (DtEditorFormatSettings *) NULL, 
498                   DtEDITOR_FORMAT_PARAGRAPH); 
499 }
500
501 static void InvokeFormatDlgCb(Widget w, XtPointer cd, XtPointer cb)
502 {
503     DtEditorInvokeFormatDialog(ad.editor); 
504 }
505
506 /***************************************************** 
507  *
508  * Options menu callbacks
509  *
510  */
511
512 static void OverstrikeCb(Widget w, XtPointer cd, XtPointer cb)
513 {
514     ad.overstrikeModeOn = ad.overstrikeModeOn ? False : True;
515     XtVaSetValues(ad.editor, DtNoverstrike, ad.overstrikeModeOn, NULL); 
516 }
517
518 static void StatusLineCb(Widget w, XtPointer cd, XtPointer cb)
519 {
520     ad.statusLineOn = ad.statusLineOn ? False : True;
521     XtVaSetValues(ad.editor, DtNshowStatusLine, ad.statusLineOn, NULL); 
522
523     /* Reset the resize increment and minimum window size properties. */
524    SetResizeHints();
525
526 }
527
528 static void WordWrapCb(Widget w, XtPointer cd, XtPointer cb)
529 {
530     ad.wordWrapOn = ad.wordWrapOn ? False : True;
531     XtVaSetValues(ad.editor, DtNwordWrap, ad.wordWrapOn, NULL); 
532 }
533
534 /***************************************************** 
535  *
536  * Editor callbacks
537  *
538  */
539
540 static void HelpCb(Widget w, XtPointer cd, XtPointer cb)
541 {
542   DtEditorHelpCallbackStruct *ecb = (DtEditorHelpCallbackStruct *)cb;
543
544   DisplayMessage( "Received a request for help");
545 }
546
547 static void TextSelectedCb(Widget w, XtPointer cd, XtPointer cb)
548 {
549     SetSelectionState(True);
550 }
551
552 static void TextUnselectedCb(Widget w, XtPointer cd, XtPointer cb)
553 {
554     SetSelectionState(False);
555 }
556
557 static void SetSelectionState(Boolean state)
558 {
559     XtSetSensitive(ad.cutButton, state);
560     XtSetSensitive(ad.copyButton, state);
561     XtSetSensitive(ad.deleteButton, state);
562     XtSetSensitive(ad.clearButton, state);
563     XtSetSensitive(ad.deselectButton, state);
564     XtSetSensitive(ad.cutPopupButton, state);
565     XtSetSensitive(ad.copyPopupButton, state);
566 }
567
568 /************************************************************************
569  *
570  * PROCEDURES 
571  *
572  ************************************************************************/
573
574 /************************************************************************
575  *
576  * SetResizeHints - Set the resize increment properties
577  *
578  */
579
580 static void SetResizeHints(void)
581 {
582    XSizeHints  sh;
583    Dimension MBheight;
584
585    DtEditorGetSizeHints(ad.editor, &sh);
586
587    /*
588     * Add Menu Bar height to the height of the Editor widget
589     */
590    XtVaGetValues( ad.menuBar, XmNheight, &MBheight, NULL);
591    sh.min_height += MBheight;
592    sh.base_height += MBheight;
593
594    XSetWMSizeHints(ad.display, XtWindow(ad.top), &sh, XA_WM_NORMAL_HINTS);
595 }
596
597 /************************************************************************
598  *
599  * DisplayMessage - Display message in DtEditor's message area
600  *
601  */
602
603 static void DisplayMessage(char *message)
604 {
605     XmTextFieldSetString(ad.messageTextF, message);
606 }
607
608 /************************************************************************
609  *
610  * CreateFileMenu - Create the File pulldown menu
611  *
612  */
613
614 static Widget CreateFileMenu(Widget menuBar)
615 {
616     Widget fileMenu; 
617
618     fileMenu = (Widget) XmCreatePulldownMenu (menuBar, "fileMenu", NULL, 0);
619     CreateCascade(menuBar, "File", 'F', fileMenu);
620     CreateButton(fileMenu, "New", 'N', ResetEditorCb, NULL);
621     CreateButton(fileMenu, "Open...", 'O', DisplayFsbCb, (XtPointer)LOAD_DATA);
622     CreateButton(fileMenu, "Include...", 'I', DisplayFsbCb,
623                                                         (XtPointer)INSERT_DATA);
624     XtManageChild(XmCreateSeparatorGadget(fileMenu, "sep1", NULL, 0));
625     CreateButton(fileMenu, "Save As...", 'A', DisplayFsbCb, (XtPointer)SAVE_DATA);
626     XtManageChild(XmCreateSeparatorGadget(fileMenu, "sep2", NULL, 0));
627     CreateButton(fileMenu, "Exit", 'x', ExitCb, NULL);
628
629     return (fileMenu);
630 }
631
632 /************************************************************************
633  *
634  * CreateEditMenu - Create the Edit pulldown menu
635  *
636  */
637
638 static Widget CreateEditMenu(Widget menuBar)
639 {
640     Widget editMenu;
641
642     editMenu = XmCreatePulldownMenu (menuBar, "editMenu", NULL, 0);
643
644     CreateCascade(menuBar, "Edit", 'E', editMenu);
645
646     CreateButton(editMenu, "Undo", 'U', UndoCb, NULL);
647     XtManageChild(XmCreateSeparatorGadget(editMenu, "sep1", NULL, 0));
648     ad.cutButton = CreateButton(editMenu, "Cut", 't', CutCb, NULL);
649     ad.copyButton = CreateButton(editMenu, "Copy", 'C', CopyCb, NULL);
650     CreateButton(editMenu, "Paste", 'P', PasteCb, NULL);
651     ad.clearButton = CreateButton(editMenu, "Clear", 'e', ClearCb, NULL);
652     ad.deleteButton = CreateButton(editMenu, "Delete", 't', DeleteCb, NULL);
653     CreateButton(editMenu, "Select All", 'S', SelectAllCb, NULL);
654     ad.deselectButton = CreateButton(editMenu, "Deselect", 'D', DeselectCb, NULL);
655     XtManageChild(XmCreateSeparatorGadget(editMenu, "sep2", NULL, 0));
656     CreateButton(editMenu, "Find/Change...", 'F', FindCb, (XtPointer)ad.editor);
657     CreateButton(editMenu, "Check Spelling...", 'p', SpellCb, (XtPointer)ad.editor);
658
659     return (editMenu);
660 }
661
662
663 /************************************************************************
664  *
665  * CreateFormatMenu - Create the FormatEdit pulldown menu
666  *
667  */
668
669 static Widget CreateFormatMenu(Widget menuBar)
670 {
671     Widget formatMenu;
672
673     formatMenu = XmCreatePulldownMenu (menuBar, "formatMenu", NULL, 0);
674
675     CreateCascade(menuBar, "Format", 'r', formatMenu);
676
677     CreateButton(formatMenu, "Settings...", 'S', InvokeFormatDlgCb, NULL);
678     CreateButton(formatMenu, "All", 'A', FormatAllCb, NULL);
679     CreateButton(formatMenu, "Paragraph", 'P', FormatParaCb, NULL);
680
681     return (formatMenu);
682 }
683
684 /************************************************************************
685  *
686  * CreateOptionsMenu - Create the Options pulldown menu
687  *
688  */
689
690 static Widget CreateOptionsMenu(Widget menuBar)
691 {
692     Widget optionsMenu;
693
694     optionsMenu = XmCreatePulldownMenu (menuBar, "optionsMenu", NULL, 0);
695
696     CreateCascade(menuBar, "Options", 'O', optionsMenu);
697
698     CreateToggle(optionsMenu, "Overstrike", 'O', OverstrikeCb, NULL, ad.overstrikeModeOn);
699     CreateToggle(optionsMenu, "Word Wrap", 'W', WordWrapCb, NULL,ad.wordWrapOn);
700     XtManageChild(XmCreateSeparatorGadget(optionsMenu, "sep1", NULL, 0));
701     CreateToggle(optionsMenu, "Status Line", 'S', StatusLineCb, NULL, ad.statusLineOn);
702
703     return (optionsMenu);
704 }
705
706 /*
707  * CreatePopupMenu - Create popup menu in editor window
708  */
709
710 static Widget CreatePopupMenu(Widget parent)
711
712     Widget popupMenu;
713     Widget fileMenu;
714     Widget editMenu;
715
716     popupMenu = XmCreatePopupMenu(parent, "popupMenu", NULL, 0);
717
718     XtAddEventHandler(parent, ButtonPressMask, False, PopupHandler,
719                                                         (XtPointer)popupMenu);
720
721     fileMenu = XmCreatePulldownMenu (popupMenu, "fileMenu", NULL, 0);
722     CreateCascade(popupMenu, "File", 'F', fileMenu);
723     CreateButton(fileMenu, "Open...", 'O', DisplayFsbCb, (XtPointer)LOAD_DATA);
724     CreateButton(fileMenu, "Include...", 'I', DisplayFsbCb,
725                                                         (XtPointer)INSERT_DATA);
726     CreateButton(fileMenu, "Save As...", 'A', DisplayFsbCb, (XtPointer)SAVE_DATA);
727     CreateButton(fileMenu, "New", 'N', ResetEditorCb, NULL);
728
729     editMenu = XmCreatePulldownMenu (popupMenu, "editMenu", NULL, 0);
730     CreateCascade(popupMenu, "Edit", 'E', editMenu);
731     CreateButton(editMenu, "Undo", 'U', UndoCb, (XtPointer)LOAD_DATA);
732     ad.cutPopupButton = CreateButton(editMenu, "Cut", 't', CutCb, NULL);
733     ad.copyPopupButton = CreateButton(editMenu, "Copy", 'C', CopyCb, NULL);
734     CreateButton(editMenu, "Paste", 'P', PasteCb, NULL);
735
736     CreateButton(popupMenu, "Find/Change...", 'F', FindCb, (XtPointer)ad.editor);
737
738     return (popupMenu);
739 }
740
741 static void PopupHandler(Widget w, XtPointer cd, XEvent *event, Boolean *ctd)
742 {
743     if (((XButtonEvent *)event)->button != Button3) return;
744
745     XmMenuPosition((Widget)cd, (XButtonEvent *)event);
746     XtManageChild ((Widget)cd);
747 }
748
749
750 /*
751  * CreateMenuBar - Create MenuBar in MainWindow
752  */
753
754 static Widget CreateMenuBar(Widget parent)
755
756     Widget menuBar;
757
758     menuBar = XmCreateMenuBar(parent, "menuBar", NULL, 0);
759
760     CreateFileMenu(menuBar);
761     CreateEditMenu(menuBar);
762     CreateFormatMenu(menuBar);
763     CreateOptionsMenu(menuBar);
764
765     return (menuBar);
766 }
767
768
769 /*
770  * CreateEditor - Create the editor widget
771  */
772
773 static Widget CreateEditor(Widget parent)
774 {
775     Widget w;
776     Arg al[10];
777     int ac;
778
779     /* create editor widget */
780
781     ac = 0;
782     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
783     XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
784     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
785     XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
786     XtSetArg(al[ac], DtNrows, 40); ac++;
787     XtSetArg(al[ac], DtNcolumns, 80); ac++;
788     w = DtCreateEditor(parent, "editor", al, ac);
789
790     /* Add callbacks */
791
792     XtAddCallback(w, DtNtextSelectCallback, TextSelectedCb, (XtPointer) w);
793     XtAddCallback(w, DtNtextDeselectCallback, TextUnselectedCb, (XtPointer) w);
794     XtAddCallback(w, XmNhelpCallback, HelpCb, NULL);
795
796     return(w);
797 }
798
799 static Widget CreateButton(Widget parent, String label, char mnemonic, XtCallbackProc callback, XtPointer callData)
800 {
801     Widget button;
802     XmString labelString;
803     Arg al[10];
804     int ac;
805
806     labelString = XmStringCreateLocalized(label);
807
808     ac = 0;
809     XtSetArg(al[ac], XmNlabelString, labelString); ac++;
810     XtSetArg(al[ac], XmNmnemonic, mnemonic); ac++;
811     button = XmCreatePushButtonGadget(parent, label, al, ac);
812     XtAddCallback(button, XmNactivateCallback, callback, callData);
813     XtManageChild(button);
814
815     XmStringFree(labelString);
816
817     return(button);
818
819
820 static Widget CreateToggle(Widget parent, String label, char mnemonic, XtCallbackProc callback, XtPointer callData, Boolean value)
821 {
822     Widget button;
823     XmString labelString;
824     Arg al[10];
825     int ac;
826
827     labelString = XmStringCreateLocalized(label);
828
829     ac = 0;
830     XtSetArg(al[ac], XmNlabelString, labelString); ac++;
831     XtSetArg(al[ac], XmNmnemonic, mnemonic); ac++;
832     XtSetArg(al[ac], XmNvisibleWhenOff, True); ac++;
833     XtSetArg(al[ac], XmNset, value); ac++;
834     button = XmCreateToggleButtonGadget(parent, label, al, ac);
835     XtAddCallback(button, XmNvalueChangedCallback, callback, callData);
836     XtManageChild(button);
837
838     XmStringFree(labelString);
839
840     return(button);
841
842
843 static Widget CreateCascade(Widget parent, String label, char mnemonic, Widget subMenu)
844 {
845     Widget button;
846     XmString labelString;
847     Arg al[10];
848     int ac;
849
850     labelString = XmStringCreateLocalized(label);
851
852     ac = 0;
853     XtSetArg(al[ac], XmNlabelString, labelString); ac++;
854     XtSetArg(al[ac], XmNsubMenuId, subMenu); ac++;
855     XtSetArg(al[ac], XmNmnemonic, mnemonic); ac++;
856     button = XmCreateCascadeButtonGadget(parent, label, al, ac);
857     XtManageChild(button);
858
859     XmStringFree(labelString);
860
861     return(button);
862