1 /* $TOG: editor.c /main/4 1998/04/02 18:18:47 rafi $ */
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.
12 * A simple editor based on the DtEditor widget.
20 #include <Dt/Editor.h>
26 #define ApplicationClass "Editor"
32 typedef struct _AppData {
33 XtAppContext appContext;
40 Widget fileSelectionBox;
45 Widget deselectButton;
46 Widget cutPopupButton;
47 Widget copyPopupButton;
50 Boolean overstrikeModeOn;
54 * Used to specify whether data is being loaded, inserted, or saved
55 * from the editor. Used used by the FSB and its callbacks.
58 typedef enum _LoadSaveType {
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);
91 void main(int argc, char **argv)
96 XtSetLanguageProc( (XtAppContext)NULL, (XtLanguageProc)NULL,
99 /* Initialize the application's data */
100 ad.fileSelectionBox = (Widget) NULL;
101 ad.wordWrapOn = False;
102 ad.statusLineOn = False;
103 ad.overstrikeModeOn = False;
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);
110 /* Create MainWindow. */
112 ad.mainWindow = (Widget) XmCreateMainWindow (ad.top, "main", al, ac);
113 XtManageChild (ad.mainWindow);
115 /* Create MenuBar in MainWindow. */
116 ad.menuBar = CreateMenuBar(ad.mainWindow);
117 XtManageChild(ad.menuBar);
119 /* Create editor widget in MainWindow. */
120 ad.editor = CreateEditor(ad.mainWindow);
121 XtManageChild(ad.editor);
122 ad.messageTextF = DtEditorGetMessageTextFieldID(ad.editor);
124 /* Create the editor popup menu */
125 CreatePopupMenu(ad.editor);
127 /* Set the main window widgets. */
128 XmMainWindowSetAreas(ad.mainWindow, ad.menuBar, NULL, NULL, NULL, ad.editor);
130 /* Realize toplevel widget */
131 XtRealizeWidget (ad.top);
133 /* Set the resize increment and minimum window size properties. */
136 /* Set up menu buttons dependent on selection */
137 SetSelectionState(False);
139 XtAppMainLoop(ad.appContext);
143 /************************************************************************
147 ************************************************************************/
150 * File menu callbacks
153 static void ResetEditorCb(Widget w, XtPointer cd, XtPointer cb)
155 DtEditorReset(ad.editor);
158 static void OpenFileCb( Widget w, XtPointer cd, XtPointer cb)
160 DtEditorErrorCode error;
161 XmFileSelectionBoxCallbackStruct *fcb = (XmFileSelectionBoxCallbackStruct *) cb;
162 LoadSaveType LoadSaveFlag = (LoadSaveType)cd;
163 char *name = (char *) XtMalloc( sizeof(char) * fcb->length + 1 );
168 * Get the name of the file & pass it to the editor widget
171 name = XmStringUnparse(fcb->value, NULL, XmCHARSET_TEXT,
172 XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
175 * Load or insert the file, as specified
177 if ( LoadSaveFlag == LOAD_DATA )
178 error = DtEditorSetContentsFromFile(ad.editor, name);
180 error = DtEditorInsertFromFile(ad.editor, name);
184 case DtEDITOR_NO_ERRORS:
186 DisplayMessage("File loaded");
189 case DtEDITOR_NULLS_REMOVED:
191 DisplayMessage( "All embedded null characters removed from the file" );
194 case DtEDITOR_READ_ONLY_FILE:
196 DisplayMessage( "The file is write protected" );
199 case DtEDITOR_NONEXISTENT_FILE:
201 DisplayMessage( "Could not find file" );
204 case DtEDITOR_DIRECTORY:
206 DisplayMessage( "The name given is a directory" );
209 case DtEDITOR_CHAR_SPECIAL_FILE:
211 DisplayMessage( "The name given is a character special device" );
214 case DtEDITOR_BLOCK_MODE_FILE:
216 DisplayMessage( "The name given is a block mode device");
219 case DtEDITOR_INSUFFICIENT_MEMORY:
221 DisplayMessage( "Not enough available memory to load file");
224 case DtEDITOR_UNREADABLE_FILE:
227 DisplayMessage( "Could not read the file" );
233 * Remove the OK callback so it can be added again with a new value for
234 * the LoadSaveFlag flag.
236 XtRemoveCallback(w, XmNokCallback, OpenFileCb, cd);
239 * Remove the FSB dialog & clean up
246 static void SaveAsFileCb(Widget w, XtPointer cd, XtPointer cb)
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;
256 char *name = XtMalloc(sizeof(char) * fcb->length + 1 );
258 XmStringGetLtoR(fcb->value, XmFONTLIST_DEFAULT_TAG, &name);
261 * Ask the widget to save its contents to the named file.
264 error = DtEditorSaveContentsToFile(ad.editor, name, overWrite,
265 hardCarriageReturns, markContentsAsSaved);
269 case DtEDITOR_NO_ERRORS:
271 DisplayMessage( "The file has been saved" );
274 case DtEDITOR_UNWRITABLE_FILE:
276 DisplayMessage( "The file is read only" );
279 case DtEDITOR_WRITABLE_FILE:
281 DisplayMessage( "File not saved, it already exists" );
284 case DtEDITOR_DIRECTORY:
286 DisplayMessage( "The name given is a directory" );
289 case DtEDITOR_CHAR_SPECIAL_FILE:
291 DisplayMessage( "The name given is a character special device" );
294 case DtEDITOR_BLOCK_MODE_FILE:
296 DisplayMessage( "The name given is a block mode device");
299 case DtEDITOR_SAVE_FAILED:
302 DisplayMessage( "Could not save the file. Check disc space" );
308 * Remove the OK callback so it can be added again with a new value for
309 * the LoadSaveFlag flag.
311 XtRemoveCallback(w, XmNokCallback, SaveAsFileCb, cd);
314 * Remove the FSB dialog & clean up
316 XtUnmanageChild( w );
322 static void CancelOpenCb(Widget w, XtPointer cd, XtPointer cb)
324 /* Remove the OK callback so it can be added again with a new value for
325 * the LoadSaveFlag flag.
327 XtRemoveCallback(w, XmNokCallback, OpenFileCb, cd);
329 /* Remove the FSB dialog & clean up */
334 static void DisplayFsbCb(Widget w, XtPointer cd, XtPointer cb)
338 XmString tmpStr1, tmpStr2;
340 LoadSaveType LoadSaveFlag = (LoadSaveType) cd;
342 /* Create the FSB, if we need to */
344 if (ad.fileSelectionBox == (Widget) NULL)
347 ad.fileSelectionBox = XmCreateFileSelectionDialog(ad.mainWindow,
350 XtAddCallback(ad.fileSelectionBox, XmNcancelCallback, CancelOpenCb,
351 (XtPointer)LoadSaveFlag);
356 * Set FSB title & label depending up whether loading, inserting, or
357 * saving a container.
359 switch ( LoadSaveFlag )
363 tmpStr1 = XmStringCreateLocalized("Open a File");
364 tmpStr2 = XmStringCreateLocalized("File to open");
367 * Add the OK callback so the curent value of the LoadSaveFlag
370 XtAddCallback(ad.fileSelectionBox, XmNokCallback, OpenFileCb,
371 (XtPointer)LoadSaveFlag);
377 tmpStr1 = XmStringCreateLocalized("Include a File");
378 tmpStr2 = XmStringCreateLocalized("File to include");
381 * Add the OK callback so the curent value of the LoadSaveFlag
384 XtAddCallback(ad.fileSelectionBox, XmNokCallback, OpenFileCb,
385 (XtPointer)LoadSaveFlag);
391 tmpStr1 = XmStringCreateLocalized("Save to File");
392 tmpStr2 = XmStringCreateLocalized("Save to file");
395 * Add the OK callback so the save as callback is called.
397 XtAddCallback(ad.fileSelectionBox, XmNokCallback, SaveAsFileCb,
398 (XtPointer)LoadSaveFlag);
408 XtVaSetValues(ad.fileSelectionBox,
409 XmNdialogTitle, tmpStr1,
410 XmNselectionLabelString, tmpStr1,
413 XmStringFree(tmpStr1);
414 XmStringFree(tmpStr2);
416 /* Display the FSB */
418 XtManageChild (ad.fileSelectionBox);
422 static void ExitCb(Widget w, XtPointer cd, XtPointer cb)
427 /*****************************************************
429 * Edit menu callbacks
433 static void UndoCb(Widget w, XtPointer cd, XtPointer cb)
435 DtEditorUndoEdit(ad.editor);
438 static void CutCb(Widget w, XtPointer cd, XtPointer cb)
440 DtEditorCutToClipboard(ad.editor);
443 static void CopyCb(Widget w, XtPointer cd, XtPointer cb)
445 DtEditorCopyToClipboard(ad.editor);
448 static void PasteCb(Widget w, XtPointer cd, XtPointer cb)
450 DtEditorPasteFromClipboard(ad.editor);
453 static void ClearCb(Widget w, XtPointer cd, XtPointer cb)
455 DtEditorClearSelection(ad.editor);
458 static void DeleteCb(Widget w, XtPointer cd, XtPointer cb)
460 DtEditorDeleteSelection(ad.editor);
463 static void SelectAllCb(Widget w, XtPointer cd, XtPointer cb)
465 DtEditorSelectAll(ad.editor);
468 static void DeselectCb(Widget w, XtPointer cd, XtPointer cb)
470 DtEditorDeselect(ad.editor);
473 static void FindCb(Widget w, XtPointer cd, XtPointer cb)
475 DtEditorInvokeFindChangeDialog(ad.editor);
478 static void SpellCb(Widget w, XtPointer cd, XtPointer cb)
480 DtEditorInvokeSpellDialog(ad.editor);
483 /*****************************************************
485 * Format menu callbacks
489 static void FormatAllCb(Widget w, XtPointer cd, XtPointer cb)
491 DtEditorFormat(ad.editor, (DtEditorFormatSettings *) NULL,
492 DtEDITOR_FORMAT_ALL);
495 static void FormatParaCb(Widget w, XtPointer cd, XtPointer cb)
497 DtEditorFormat(ad.editor, (DtEditorFormatSettings *) NULL,
498 DtEDITOR_FORMAT_PARAGRAPH);
501 static void InvokeFormatDlgCb(Widget w, XtPointer cd, XtPointer cb)
503 DtEditorInvokeFormatDialog(ad.editor);
506 /*****************************************************
508 * Options menu callbacks
512 static void OverstrikeCb(Widget w, XtPointer cd, XtPointer cb)
514 ad.overstrikeModeOn = ad.overstrikeModeOn ? False : True;
515 XtVaSetValues(ad.editor, DtNoverstrike, ad.overstrikeModeOn, NULL);
518 static void StatusLineCb(Widget w, XtPointer cd, XtPointer cb)
520 ad.statusLineOn = ad.statusLineOn ? False : True;
521 XtVaSetValues(ad.editor, DtNshowStatusLine, ad.statusLineOn, NULL);
523 /* Reset the resize increment and minimum window size properties. */
528 static void WordWrapCb(Widget w, XtPointer cd, XtPointer cb)
530 ad.wordWrapOn = ad.wordWrapOn ? False : True;
531 XtVaSetValues(ad.editor, DtNwordWrap, ad.wordWrapOn, NULL);
534 /*****************************************************
540 static void HelpCb(Widget w, XtPointer cd, XtPointer cb)
542 DtEditorHelpCallbackStruct *ecb = (DtEditorHelpCallbackStruct *)cb;
544 DisplayMessage( "Received a request for help");
547 static void TextSelectedCb(Widget w, XtPointer cd, XtPointer cb)
549 SetSelectionState(True);
552 static void TextUnselectedCb(Widget w, XtPointer cd, XtPointer cb)
554 SetSelectionState(False);
557 static void SetSelectionState(Boolean state)
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);
568 /************************************************************************
572 ************************************************************************/
574 /************************************************************************
576 * SetResizeHints - Set the resize increment properties
580 static void SetResizeHints(void)
585 DtEditorGetSizeHints(ad.editor, &sh);
588 * Add Menu Bar height to the height of the Editor widget
590 XtVaGetValues( ad.menuBar, XmNheight, &MBheight, NULL);
591 sh.min_height += MBheight;
592 sh.base_height += MBheight;
594 XSetWMSizeHints(ad.display, XtWindow(ad.top), &sh, XA_WM_NORMAL_HINTS);
597 /************************************************************************
599 * DisplayMessage - Display message in DtEditor's message area
603 static void DisplayMessage(char *message)
605 XmTextFieldSetString(ad.messageTextF, message);
608 /************************************************************************
610 * CreateFileMenu - Create the File pulldown menu
614 static Widget CreateFileMenu(Widget menuBar)
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);
632 /************************************************************************
634 * CreateEditMenu - Create the Edit pulldown menu
638 static Widget CreateEditMenu(Widget menuBar)
642 editMenu = XmCreatePulldownMenu (menuBar, "editMenu", NULL, 0);
644 CreateCascade(menuBar, "Edit", 'E', editMenu);
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);
663 /************************************************************************
665 * CreateFormatMenu - Create the FormatEdit pulldown menu
669 static Widget CreateFormatMenu(Widget menuBar)
673 formatMenu = XmCreatePulldownMenu (menuBar, "formatMenu", NULL, 0);
675 CreateCascade(menuBar, "Format", 'r', formatMenu);
677 CreateButton(formatMenu, "Settings...", 'S', InvokeFormatDlgCb, NULL);
678 CreateButton(formatMenu, "All", 'A', FormatAllCb, NULL);
679 CreateButton(formatMenu, "Paragraph", 'P', FormatParaCb, NULL);
684 /************************************************************************
686 * CreateOptionsMenu - Create the Options pulldown menu
690 static Widget CreateOptionsMenu(Widget menuBar)
694 optionsMenu = XmCreatePulldownMenu (menuBar, "optionsMenu", NULL, 0);
696 CreateCascade(menuBar, "Options", 'O', optionsMenu);
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);
703 return (optionsMenu);
707 * CreatePopupMenu - Create popup menu in editor window
710 static Widget CreatePopupMenu(Widget parent)
716 popupMenu = XmCreatePopupMenu(parent, "popupMenu", NULL, 0);
718 XtAddEventHandler(parent, ButtonPressMask, False, PopupHandler,
719 (XtPointer)popupMenu);
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);
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);
736 CreateButton(popupMenu, "Find/Change...", 'F', FindCb, (XtPointer)ad.editor);
741 static void PopupHandler(Widget w, XtPointer cd, XEvent *event, Boolean *ctd)
743 if (((XButtonEvent *)event)->button != Button3) return;
745 XmMenuPosition((Widget)cd, (XButtonEvent *)event);
746 XtManageChild ((Widget)cd);
751 * CreateMenuBar - Create MenuBar in MainWindow
754 static Widget CreateMenuBar(Widget parent)
758 menuBar = XmCreateMenuBar(parent, "menuBar", NULL, 0);
760 CreateFileMenu(menuBar);
761 CreateEditMenu(menuBar);
762 CreateFormatMenu(menuBar);
763 CreateOptionsMenu(menuBar);
770 * CreateEditor - Create the editor widget
773 static Widget CreateEditor(Widget parent)
779 /* create editor widget */
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);
792 XtAddCallback(w, DtNtextSelectCallback, TextSelectedCb, (XtPointer) w);
793 XtAddCallback(w, DtNtextDeselectCallback, TextUnselectedCb, (XtPointer) w);
794 XtAddCallback(w, XmNhelpCallback, HelpCb, NULL);
799 static Widget CreateButton(Widget parent, String label, char mnemonic, XtCallbackProc callback, XtPointer callData)
802 XmString labelString;
806 labelString = XmStringCreateLocalized(label);
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);
815 XmStringFree(labelString);
820 static Widget CreateToggle(Widget parent, String label, char mnemonic, XtCallbackProc callback, XtPointer callData, Boolean value)
823 XmString labelString;
827 labelString = XmStringCreateLocalized(label);
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);
838 XmStringFree(labelString);
843 static Widget CreateCascade(Widget parent, String label, char mnemonic, Widget subMenu)
846 XmString labelString;
850 labelString = XmStringCreateLocalized(label);
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);
859 XmStringFree(labelString);