/* w6a.c extracted from OSF's xmeditor.c, then ANSI C, then clean up */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include enum which {MENU_EXIT, MENU_OPEN, MENU_NEW, MENU_CLOSE, MENU_SAVE_AS, MENU_PRINT, DIALOG_FSELECT, DIALOG_CWARNING, DIALOG_XWARNING, DIALOG_NEW, DIALOG_SAVE, DIALOG_PRINT}; Widget text; /* multi-line text widget */ Widget open_dialog; /* file selection dialog */ Widget new_dialog; /* file name prompt dialog */ Widget close_warning; /* special internal selection dialog */ Widget exit_warning; /* special internal selection dialog */ Widget general_warning; /* warning dialog */ Widget save_dialog; /* save as prompt dialog */ Widget print_warning; /* warning dialog */ Boolean file_saved = True; /* indicates that the present file is saved */ char *filename = NULL; /* string containing file name */ int start_pos, end_pos; /* start and end position of last action */ XmStringCharSet charset = (XmStringCharSet) XmSTRING_DEFAULT_CHARSET; /* shorter name, charset, used to set up XmStrings */ /* OpenFile, Open the present file. Returns true if file exists and open is sucessful. */ static Boolean OpenFile(void) { int file_length; /* Length of file. */ char * file_string; /* Contents of file. */ FILE *fp = NULL; /* Pointer to open file */ if ((fp = fopen(filename, "r+")) == NULL) if ((fp = fopen(filename, "r")) != NULL) { fprintf(stderr, "Warning: file opened read only.\n"); } else { return(False); } /* if (stat(filename, &statbuf) == 0) file_length = statbuf.st_size; else find POSIX way to get length of a file */ file_length = 1000000; /* arbitrary file length for now */ /* read the file string */ file_string = (char *) XtMalloc((unsigned)file_length); fread(file_string, sizeof(char), file_length, fp); file_length = strlen(file_string); /* new have actual length */ /* close up the file */ if (fclose(fp) != 0) fprintf(stderr, "Warning: unable to close file.\n"); /* added the file string to the text widget */ XmTextSetString(text, file_string); file_saved = True; /* intialize to True */ /* make appropriate item sensitive */ XtSetSensitive(text, True); return(True); } /* Save call back goes here, utility routine SaveFile() below does most of work */ /* SaveFile, Save the present file. */ static Boolean SaveFile(void) { char * file_string = NULL; /* Contents of file. */ FILE *tfp; /* Pointer to open temporary file. */ char namebuf[BUFSIZ]; /* for "system" call below */ int status; char *tempname = (char *)XtMalloc(13); /* Temporary file name. */ strcpy(tempname, "xmedit_temp"); if ((tfp = fopen(tempname, "w")) == NULL) { fprintf(stderr, "Warning: unable to open temp file, text not saved.\n"); return(False); } /* get the text string */ file_string = (char *)XmTextGetString(text); /* write to a temp file */ fwrite(file_string, sizeof(char), strlen(file_string) + 1, tfp); /* flush and close the temp file */ if (fflush(tfp) != 0) fprintf(stderr,"Warning: unable to flush file.\n"); if (fclose(tfp) != 0) fprintf(stderr,"Warning: unable to close file.\n"); if (file_string != NULL) { XtFree(file_string); /* free the text string */ } /* move the tempname to the saved file, but do it independent of filesystem boundaries */ if (status == 0 || status == 1) { file_saved = True; } else { fprintf(stderr, "Warning: unable to save file.\n"); XtFree(tempname); return(False); } XtFree(tempname); return(True); } /* CloseFile, Close the present file. */ static void CloseFile(void) { /* blank out the text string in the text widget. caution: is causes a value changed callack. */ XmTextSetString(text, ""); file_saved = True; /* reinitialize file_saved flag */ /* free the file name */ if (filename != NULL) { XtFree(filename); filename = NULL; } /* set text to insensitive */ XtSetSensitive(text, False); } /* PrintFile, Write the file to disk, use system command to print it. */ static void PrintFile(void) { char *command; /* command used in printing */ /* malloc space for the command name. Note: command = size of the filename + "lp " + null terminator */ command = XtMalloc(strlen(filename) + 5); sprintf(command, "lpr %s\0", filename); if (system(command) != 0) fprintf(stderr, "print failed"); XtFree(command); } /* FileChangedCB, Process callback from Text. */ void FileChangedCB (Widget w, XtPointer client_data, XtPointer call_data) { /* set the file_saved flag to indicate that the file has been modified and the user should be notified before exiting. */ file_saved = False; } /* MenuCB, Process callback from PushButtons in PulldownMenus. */ void MenuCB (Widget w, enum which client_data, XtPointer call_data) { register int ac; /* arg count */ Arg al[10]; /* arg list */ switch (client_data) { case MENU_OPEN: /* display the file selection dialog */ XtManageChild (open_dialog); break; case MENU_NEW: /* display the prompt dialog */ XtManageChild (new_dialog); break; case MENU_CLOSE: /* the present file has not been saved since the last modification */ if (!file_saved) /* display the 'save' message dialog */ XtManageChild (close_warning); else CloseFile(); break; case MENU_SAVE_AS: /* Display the 'save as' dialog with the present filename displayed in it. */ ac = 0; XtSetArg(al[ac], XmNtextString, XmStringCreateLtoR (filename, charset)); ac++; XtSetValues(save_dialog, al, ac); XtManageChild (save_dialog); break; case MENU_PRINT: if (!file_saved) XtManageChild(print_warning); else if (filename != NULL) PrintFile(); break; case MENU_EXIT: /* exit if there is no files open */ if (!file_saved) /* display the 'save' message dialog */ XtManageChild (exit_warning); else { /* close up file pointers and descriptors */ CloseFile(); /* exit this program */ exit(EXIT_SUCCESS); } break; default: /* unknown client_data was recieved and there is no setup to handle this */ fprintf(stderr, "Warning: in menu callback\n"); break; } } /* DialogApplyCB, Process callback from Dialog apply actions. */ void DialogApplyCB (Widget w, enum which client_data, XtPointer call_data) { switch (client_data) { case DIALOG_PRINT: if (filename != NULL) PrintFile(); break; case DIALOG_CWARNING: CloseFile(); file_saved = True; /* reset the default */ break; case DIALOG_XWARNING: CloseFile(); exit(EXIT_SUCCESS); break; default: /* unknown client_data was recieved and there is no setup to handle this */ fprintf (stderr, "Warning: in apply callback\n"); break; } } /* DialogCancelCB, Process callback from Dialog cancel actions. */ void DialogCancelCB (Widget w, enum which client_data, XtPointer call_data) { switch (client_data) { case DIALOG_FSELECT: /* popdown the file selection box */ XtUnmanageChild (open_dialog); break; case DIALOG_CWARNING: case DIALOG_XWARNING: case DIALOG_NEW: case DIALOG_PRINT: /* no action is necessary at this time */ break; default: /* a unknown client_data was recieved and there is no setup to handle this */ fprintf (stderr, "Warning: in cancel callback\n"); break; } } /* DialogAcceptCB, Process callback from Dialog actions. */ void DialogAcceptCB (Widget w, enum which client_data, XtPointer call_data) { switch (client_data) { case DIALOG_FSELECT: /* open the file and read it into the text widget */ if (filename != NULL) { XtFree(filename); filename = NULL; } { XmFileSelectionBoxCallbackStruct *fcb = (XmFileSelectionBoxCallbackStruct *) call_data; /* get the filename from the file selection box */ XmStringGetLtoR(fcb->value, charset, &filename); /* Open file, print error if it does not exist. */ if (!OpenFile()) fprintf(stderr, "Warning: unable to open file\n"); /* popdown the file selection box */ XtUnmanageChild (open_dialog); } break; case DIALOG_NEW: /* open the file and read it into the text widget */ if (filename != NULL) { XtFree(filename); filename = NULL; } { XmSelectionBoxCallbackStruct *scb = (XmSelectionBoxCallbackStruct *) call_data; /* get the filename string from the file name prompt box */ XmStringGetLtoR(scb->value, charset, &filename); /* open file if it exists, if not set items sensitive */ if (!OpenFile()) { /* make appropriate item sensitive */ XtSetSensitive(text, True); } /* popdown the file selection box */ XtUnmanageChild (new_dialog); } break; case DIALOG_CWARNING: /* save the file */ if (SaveFile()) { CloseFile(); /* close the file */ } else fprintf(stderr, "Warning: unable to save file, file not closed"); break; case DIALOG_XWARNING: /* save the file */ if (SaveFile()) { CloseFile(); /* close the file */ exit(EXIT_SUCCESS); } else fprintf(stderr, "Warning: unable to save file, exit aborted"); break; case DIALOG_SAVE: { XmSelectionBoxCallbackStruct *scb = (XmSelectionBoxCallbackStruct *) call_data; /* get the filename string from the file selection box */ XmStringGetLtoR(scb->value, charset, &filename); SaveFile(); XtUnmanageChild (save_dialog); } break; case DIALOG_PRINT: /* save the file */ if (SaveFile()) { if (filename != NULL) PrintFile(); } else fprintf(stderr, "Warning: unable to save file, file not printed"); break; default: /* unknown callback type */ fprintf (stderr, "Warning: in accept callback\n"); break; } } /* CreateSpecialWarningDialog, Create special 4 button message box out of a Selection box. */ static Widget CreateSpecialWarningDialog (Widget parent, String name, String image_string, String message, ArgList arglist, int argcount) { Widget warning_dialog; /* special warning selection box */ Widget work_area; /* rowcolumn for pixmap and text */ Widget pixmap_label; /* pixmap label */ Widget text_label; /* text label */ Widget apply_button; /* apply button "Discard" */ Widget ok_button; /* ok button "Save" */ Widget kid[5]; /* buttons */ Pixel foreground; /* dialog foreground */ Pixel background; /* dialog background */ Pixmap pixmap; /* dialog pixmap */ register int i; /* kid index */ Arg al[10]; /* arg list */ register int ac; /* arg count */ warning_dialog = XmCreatePromptDialog(parent, name, arglist, argcount); ac = 0; XtSetArg(al[ac], XmNorientation, XmHORIZONTAL); ac++; work_area = XmCreateRowColumn(warning_dialog, "workarea", al, ac); XtManageChild(work_area); ac = 0; XtSetArg(al[ac], XmNforeground, &foreground); ac++; XtSetArg(al[ac], XmNbackground, &background); ac++; XtGetValues(warning_dialog, al, ac); ac = 0; XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++; pixmap = XmGetPixmap(XtScreen(warning_dialog), image_string, foreground, background); XtSetArg(al[ac], XmNlabelPixmap, pixmap); ac++; pixmap_label = XmCreateLabel(work_area, "pixmap_label", al, ac); XtManageChild(pixmap_label); ac = 0; XtSetArg(al[ac], XmNlabelString, XmStringCreateLtoR(message, charset)); ac++; text_label = XmCreateLabel(work_area, "text_label", al, ac); XtManageChild(text_label); apply_button = XmSelectionBoxGetChild (warning_dialog, XmDIALOG_APPLY_BUTTON); ac = 0; XtSetArg(al[ac], XmNlabelString, XmStringCreateLtoR("Discard", charset)); ac++; XtSetValues(apply_button, al, ac); XtManageChild(apply_button); ok_button = XmSelectionBoxGetChild (warning_dialog, XmDIALOG_OK_BUTTON); ac = 0; XtSetArg(al[ac], XmNlabelString, XmStringCreateLtoR("Save", charset)); ac++; XtSetValues(ok_button, al, ac); /* Unmanage unneeded children. */ i = 0; kid[i++] = XmSelectionBoxGetChild (warning_dialog, XmDIALOG_TEXT); kid[i++] = XmSelectionBoxGetChild (warning_dialog, XmDIALOG_SELECTION_LABEL); XtUnmanageChildren (kid, i); return(warning_dialog); } /* CreateMenuBar, Create MenuBar in MainWindow */ static Widget CreateMenuBar (Widget parent) { Widget menu_bar; /* RowColumn */ Widget cascade; /* CascadeButton */ Widget menu_pane; /* RowColumn */ Widget button; /* PushButton */ Arg al[10]; /* arg list */ int ac; /* arg count */ /* Create MenuArea. */ ac = 0; menu_bar = XmCreateMenuBar (parent, "menu_bar", al, ac); /* Create "Options" PulldownMenu. */ ac = 0; menu_pane = XmCreatePulldownMenu (menu_bar, "menu_pane", al, ac); ac = 0; XtSetArg(al[ac], XmNlabelString, XmStringCreateLtoR("Open", charset)); ac++; XtSetArg(al[ac], XmNmnemonic, 'O'); ac++; button = XmCreatePushButton (menu_pane, "Open", al, ac); XtAddCallback (button, XmNactivateCallback, (XtCallbackProc)MenuCB, (XtPointer)MENU_OPEN); XtManageChild (button); open_dialog = XmCreateFileSelectionDialog(menu_pane, "file selection dialog", NULL, 0); XtAddCallback (open_dialog, XmNokCallback, (XtCallbackProc)DialogAcceptCB, (XtPointer)DIALOG_FSELECT); XtAddCallback (open_dialog, XmNcancelCallback, (XtCallbackProc)DialogCancelCB, (XtPointer)DIALOG_FSELECT); ac = 0; XtSetArg(al[ac], XmNlabelString, XmStringCreateLtoR("New", charset)); ac++; XtSetArg(al[ac], XmNmnemonic, 'N'); ac++; button = XmCreatePushButton (menu_pane, "New", al, ac); XtAddCallback (button, XmNactivateCallback, (XtCallbackProc)MenuCB, (XtPointer)MENU_NEW); XtManageChild (button); ac = 0; XtSetArg(al[ac], XmNselectionLabelString, XmStringCreateLtoR ("Enter name of new file.", charset)); ac++; new_dialog = XmCreatePromptDialog(menu_pane, "new file dialog", al, ac); XtAddCallback (new_dialog, XmNokCallback, (XtCallbackProc)DialogAcceptCB, (XtPointer)DIALOG_NEW); XtAddCallback (new_dialog, XmNcancelCallback, (XtCallbackProc)DialogCancelCB, (XtPointer)DIALOG_NEW); ac = 0; XtSetArg(al[ac], XmNlabelString, XmStringCreateLtoR("Close", charset)); ac++; XtSetArg(al[ac], XmNmnemonic, 'C'); ac++; button = XmCreatePushButton (menu_pane, "Close", al, ac); XtAddCallback (button, XmNactivateCallback, (XtCallbackProc)MenuCB, (XtPointer)MENU_CLOSE); XtManageChild (button); close_warning = CreateSpecialWarningDialog(menu_pane, "save_warning", "exclam.xbm", "Save Changes?", al, ac); XtAddCallback (close_warning, XmNapplyCallback, (XtCallbackProc)DialogApplyCB, (XtPointer)DIALOG_CWARNING); XtAddCallback (close_warning, XmNokCallback, (XtCallbackProc)DialogAcceptCB, (XtPointer)DIALOG_CWARNING); /* Save homework stuff goes here */ ac = 0; XtSetArg(al[ac], XmNlabelString, XmStringCreateLtoR("Save As...", charset)); ac++; XtSetArg(al[ac], XmNmnemonic, 'A'); ac++; button = XmCreatePushButton (menu_pane, "Save As...", al, ac); XtAddCallback (button, XmNactivateCallback, (XtCallbackProc)MenuCB, (XtPointer)MENU_SAVE_AS); XtManageChild (button); ac = 0; XtSetArg(al[ac], XmNselectionLabelString, XmStringCreateLtoR ("Save As...", charset)); ac++; save_dialog = XmCreatePromptDialog(menu_pane, "save dialog", al, ac); XtAddCallback (save_dialog, XmNokCallback, (XtCallbackProc)DialogAcceptCB, (XtPointer)DIALOG_SAVE); ac = 0; XtSetArg(al[ac], XmNlabelString, XmStringCreateLtoR("Print", charset)); ac++; XtSetArg(al[ac], XmNmnemonic, 'P'); ac++; button = XmCreatePushButton (menu_pane, "Print", al, ac); XtAddCallback (button, XmNactivateCallback, (XtCallbackProc)MenuCB, (XtPointer)MENU_PRINT); XtManageChild (button); ac = 0; XtSetArg(al[ac], XmNselectionLabelString, XmStringCreateLtoR ("Save file before printing?", charset)); ac++; print_warning = CreateSpecialWarningDialog(menu_pane, "print_warning", "exclam.xbm", "Save file before printing?", al, ac); XtAddCallback (print_warning, XmNokCallback, (XtCallbackProc)DialogAcceptCB, (XtPointer)DIALOG_PRINT); ac = 0; XtSetArg(al[ac], XmNlabelString, XmStringCreateLtoR("Exit", charset)); ac++; XtSetArg(al[ac], XmNmnemonic, 'E'); ac++; XtSetArg(al[ac], XmNacceleratorText, XmStringCreateLtoR("F3", charset)); ac++; XtSetArg(al[ac], XmNaccelerator, "F3:"); ac++; button = XmCreatePushButton (menu_pane, "Exit", al, ac); XtAddCallback (button, XmNactivateCallback, (XtCallbackProc)MenuCB, (XtPointer)MENU_EXIT); XtManageChild (button); ac = 0; exit_warning = CreateSpecialWarningDialog(menu_pane, "exit warning", "exclam.xbm", "Save Changes?", al, ac); XtAddCallback (exit_warning, XmNapplyCallback, (XtCallbackProc)DialogApplyCB, (XtPointer)DIALOG_XWARNING); XtAddCallback (exit_warning, XmNokCallback, (XtCallbackProc)DialogAcceptCB, (XtPointer)DIALOG_XWARNING); ac = 0; XtSetArg (al[ac], XmNsubMenuId, menu_pane); ac++; XtSetArg(al[ac], XmNlabelString, XmStringCreateLtoR("File", charset)); ac++; XtSetArg(al[ac], XmNmnemonic, 'F'); ac++; cascade = XmCreateCascadeButton (menu_bar, "File", al, ac); XtManageChild (cascade); return (menu_bar); } /* main ** Initialize toolkit. ** Create MainWindow and subwidgets. ** Realize toplevel widgets. ** Process events. */ int main (int argc, char *argv[]) { Widget app_shell; /* ApplicationShell */ Widget main; /* MainWindow */ Widget menu_bar; /* RowColumn */ Widget form; /* Form */ XtAppContext app_context; /* Application Context */ Arg al[10]; /* arg list */ register int ac; /* arg count */ register int i; /* counter */ char *progname; /* program name without the full pathname */ void FileChangedCB(); if (progname=strrchr(argv[0], '/')) progname++; else if (progname=strrchr(argv[0], ']')) progname++; else progname = argv[0]; /* Initialize toolkit, open display and create application shell. */ app_shell = XtVaAppInitialize(&app_context, progname, NULL, 0, &argc, argv, NULL, NULL); /* Create MainWindow. */ main = XtVaCreateManagedWidget("main", xmMainWindowWidgetClass, app_shell, XmNshadowThickness, 0, NULL); /* Create MenuBar in MainWindow. */ menu_bar = CreateMenuBar (main); XtManageChild (menu_bar); /* Create Text. */ ac = 0; XtSetArg (al[ac], XmNrows, 24); ac++; XtSetArg (al[ac], XmNcolumns, 80); ac++; XtSetArg (al[ac], XmNresizeWidth, False); ac++; XtSetArg (al[ac], XmNresizeHeight, False); ac++; XtSetArg (al[ac], XmNscrollVertical, True); ac++; XtSetArg (al[ac], XmNscrollHorizontal, True); ac++; XtSetArg (al[ac], XmNeditMode, XmMULTI_LINE_EDIT); ac++; text = XmCreateScrolledText (main, "text", al, ac); /* add value changed callback */ XtAddCallback (text, XmNmodifyVerifyCallback, (XtCallbackProc)FileChangedCB, NULL); XtManageChild (text); XmAddTabGroup(text); XtSetSensitive(text, False); /* Realize toplevel widgets. */ XtRealizeWidget (app_shell); /* Process events. */ XtAppMainLoop (app_context); return 0; /* never executed */ } /* end w6a.c file */