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