/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* gos720 src/gos/2d/XTOP/extras/xmtexted/xmtexted.c 1.4 */ /* */ /* Licensed Materials - Property of IBM */ /* */ /* COPYRIGHT International Business Machines Corp. 2002,2005 */ /* All Rights Reserved */ /* */ /* US Government Users Restricted Rights - Use, duplication or */ /* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /* */ /* IBM_PROLOG_END_TAG */ static char sccsid[] = "@(#)09 1.4 src/gos/2d/XTOP/extras/xmtexted/xmtexted.c, xsample, gos720 12/27/05 15:53:03"; #include #include #include #include #include #include #include #include #include #include #include typedef int (*funcptr)(char *); /* open_file, save_file */ /* globals */ XtAppContext app; Widget toplevel, textw; char *current_file; Boolean modified = False; /* * Set current filename, modified status, and titlebar string. */ void set_status(char *new_current_file, Boolean new_modified) { char *title; if (current_file != new_current_file) { if (current_file) XtFree(current_file); current_file = new_current_file ? strdup(new_current_file) : NULL; } modified = new_modified; title = strdup(current_file ? current_file : "Untitled"); if (modified) { /* Append [modified] to the title. */ title = (char *)XtRealloc( title, sizeof(char) * (strlen(title)+strlen(" [modified]")+1) ); strcat(title, " [modified]"); } XtVaSetValues(toplevel, XmNtitle, title, NULL); XtFree(title); } void text_modified_cb(Widget widget, XtPointer client_data, XtPointer call_data) { set_status(current_file, True); } void popdown_cb(Widget widget, XtPointer client_data, XtPointer call_data) { XtUnmanageChild(widget); } /* * A generic popup dialog with one "Ok" button. */ void error_popup(char *msg) { static Widget dialog; XmString ok, msgstr, title; if (!dialog) { dialog = XmCreateErrorDialog(toplevel, "error_dialog", NULL, 0); title = XmStringCreateLocalized("Error"); XtVaSetValues(dialog, XmNdialogTitle, title, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, NULL); XmStringFree(title); XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON)); XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON)); XtAddCallback(dialog, XmNokCallback, popdown_cb, NULL); } msgstr = XmStringCreateLocalized(msg); XtVaSetValues(dialog, XmNmessageString, msgstr, NULL); XmStringFree(msgstr); XtManageChild(dialog); XtPopup(XtParent(dialog), XtGrabNone); } int open_file(char *filename) { struct stat stat_buffer; FILE *fd; char msg[256]; char *contents; long int bytes_read; /* Check for existence, proper file type, and readability. */ if ( (stat(filename, &stat_buffer) == -1) || ((stat_buffer.st_mode & S_IFMT) != S_IFREG) || (!(fd = fopen(filename, "r"))) ) { snprintf(msg, 255, "Unable to open %s.", filename); msg[255] = 0; error_popup(msg); return(0); } if ( !(contents = XtMalloc(stat_buffer.st_size+1)) ) { snprintf(msg, 255, "Unable to allocate %ld bytes for %s.", stat_buffer.st_size+1, filename); msg[255] = 0; error_popup(msg); fclose(fd); return(0); } bytes_read = fread(contents, sizeof(char), stat_buffer.st_size, fd); /* Check for short read. */ if (bytes_read != stat_buffer.st_size) { snprintf(msg, 255, "Error reading %s: entire file not read.", filename); msg[255] = 0; error_popup(msg); } contents[bytes_read] = 0; /* null terminate */ XmTextSetString(textw, contents); XtFree(contents); fclose(fd); set_status(filename, False); return(1); } int save_file(char *filename) { FILE *fd; char msg[256]; char *contents; /* Check for write ability. */ if ( !(fd = fopen(filename, "w")) ) { snprintf(msg, 255, "Unable to save %s.", filename); msg[255] = 0; error_popup(msg); return(0); } contents = XmTextGetString(textw); /* Check for short write. */ if (fwrite(contents, sizeof(char), strlen(contents), fd) != strlen(contents)) { snprintf(msg, 255, "Error writing %s: entire file not saved.", filename); msg[255] = 0; error_popup(msg); } XtFree(contents); fclose(fd); set_status(filename, False); return(1); } /* * The window manager has sent WM_DELETE_WINDOW. */ void delete_window_cb(Widget widget, XtPointer client_data, XtPointer call_data) { if (check_saved_dialog()) exit(0); } /* * "Ok" has been clicked on the "Save As" dialog. */ void file_save_cb(Widget widget, XtPointer client_data, XtPointer call_data) { XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *)call_data; int *retval = (int *)client_data; char *filename; if (!XmStringGetLtoR(cbs->value, XmFONTLIST_DEFAULT_TAG, &filename)) return; if (*retval = save_file(filename)) XtUnmanageChild(widget); XtFree(filename); } /* * "Ok" has been clicked on the "Open File" dialog. */ void file_open_cb(Widget widget, XtPointer client_data, XtPointer call_data) { XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *)call_data; int *retval = (int *)client_data; char *filename; if (!XmStringGetLtoR(cbs->value, XmFONTLIST_DEFAULT_TAG, &filename)) return; if (*retval = open_file(filename)) XtUnmanageChild(widget); XtFree(filename); } /* * Callback for the "Are you sure?" dialog. */ void check_saved_cb(Widget widget, XtPointer client_data, XtPointer call_data) { XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *)call_data; int *retval = (int *)client_data; switch(cbs->reason) { case XmCR_OK: /* Yes */ *retval = 1; break; case XmCR_CANCEL: /* No */ *retval = 2; break; default: /* Cancel */ *retval = 0; break; } } /* * Generic file selection dialog. * Returns 1 if open or save was successfully performed, 0 otherwise. */ int file_select_dialog(funcptr open_or_save) { static Widget open_dialog, save_dialog; Widget dialog; XmString title, ok_str; int retval = -1; dialog = (open_or_save == open_file) ? open_dialog : save_dialog; if (!dialog) { dialog = XmCreateFileSelectionDialog(toplevel, "file_selection", NULL, 0); if (open_or_save == open_file) { title = XmStringCreateLocalized("Open File"); ok_str = XmStringCreateLocalized("Open"); XtAddCallback(dialog, XmNokCallback, file_open_cb, &retval); } else { title = XmStringCreateLocalized("Save As"); ok_str = XmStringCreateLocalized("Save"); XtAddCallback(dialog, XmNokCallback, file_save_cb, &retval); } XtVaSetValues(dialog, XmNdialogTitle, title, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, XmNokLabelString, ok_str, NULL); XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON)); XmStringFree(title); XmStringFree(ok_str); } XtAddCallback(dialog, XmNcancelCallback, popdown_cb, NULL); XtManageChild(dialog); XtPopup(XtParent(dialog), XtGrabNone); while (retval == -1) XtAppProcessEvent(app, XtIMAll); return(retval); } /* * Prompt user before wiping a modified document. * Returns 1 (saved), 2 (didn't save), or 0 (canceled). */ int check_saved_dialog(void) { static Widget dialog; XmString title, msg, yes, no, cancel; int retval = -1; if (!modified) return(1); if (!dialog) { title = XmStringCreateLocalized("Warning"); msg = XmStringCreateLocalized("The current document has been modified.\n" "Would you like to save it?"); yes = XmStringCreateLocalized("Yes"); no = XmStringCreateLocalized("No"); cancel = XmStringCreateLocalized("Cancel"); dialog = XmCreateWarningDialog(toplevel, "check_saved", NULL, 0); XtVaSetValues(dialog, XmNdialogTitle, title, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, XmNdefaultButtonType, XmDIALOG_HELP_BUTTON, XmNmessageString, msg, XmNokLabelString, yes, XmNcancelLabelString, no, XmNhelpLabelString, cancel, NULL); XmStringFree(title); XmStringFree(msg); XmStringFree(yes); XmStringFree(no); XmStringFree(cancel); } XtAddCallback(dialog, XmNokCallback, check_saved_cb, &retval); XtAddCallback(dialog, XmNcancelCallback, check_saved_cb, &retval); XtAddCallback(dialog, XmNhelpCallback, check_saved_cb, &retval); XtManageChild(dialog); XtPopup(XtParent(dialog), XtGrabNone); while (retval == -1) XtAppProcessEvent(app, XtIMAll); if (retval == 1) /* Yes */ { /* Now success depends on the save operation. */ retval = (current_file) ? save_file(current_file) : file_select_dialog(save_file); } XtPopdown(XtParent(dialog)); return(retval); } /* * A menu item from the "File" pulldown was selected. */ void file_menu_cb(Widget widget, XtPointer client_data, XtPointer call_data) { int item = (int)client_data; char *filename; switch(item) { case 0: /* New */ if (check_saved_dialog()) { XmTextSetString(textw, ""); set_status(NULL, False); } break; case 1: /* Open */ if (check_saved_dialog()) (void)file_select_dialog(open_file); break; case 2: /* Save */ if (current_file) { save_file(current_file); break; } /* else fall through */ case 3: /* Save As */ (void)file_select_dialog(save_file); break; case 4: /* Quit */ if (check_saved_dialog()) exit(0); break; default: break; } } int main(int argc, char* argv[]) { Widget mainw, menubar; XmString file; XmString new, open, save, saveas, quit; XmString new_acc, open_acc, save_acc, quit_acc; Atom wm_delete_window; Arg args[1]; setlocale(LC_ALL, ""); toplevel = XtVaOpenApplication(&app, "XmTextEd", NULL, 0, &argc, argv, NULL, sessionShellWidgetClass, NULL); set_status(NULL, False); /* no current file, unmodified */ /* Callback for when the window manager sends WM_DELETE_WINDOW. */ wm_delete_window = XmInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW", False); XmAddWMProtocols(toplevel, &wm_delete_window, 1); XmAddWMProtocolCallback(toplevel, wm_delete_window, delete_window_cb, NULL); mainw = XtVaCreateWidget("mainw", xmMainWindowWidgetClass, toplevel, NULL); file = XmStringCreateLocalized("File"); menubar = XmVaCreateSimpleMenuBar(mainw, "menubar", XmVaCASCADEBUTTON, file, 'F', NULL); XmStringFree(file); new = XmStringCreateLocalized("New"); new_acc = XmStringCreateLocalized("Ctrl+N"); open = XmStringCreateLocalized("Open"); open_acc = XmStringCreateLocalized("Ctrl+O"); save = XmStringCreateLocalized("Save"); save_acc = XmStringCreateLocalized("Ctrl+S"); saveas = XmStringCreateLocalized("Save As"); quit = XmStringCreateLocalized("Quit"); quit_acc = XmStringCreateLocalized("Ctrl+Q"); XmVaCreateSimplePulldownMenu(menubar, "file", 0, file_menu_cb, XmVaPUSHBUTTON, new, 'N', "Ctrln", new_acc, XmVaPUSHBUTTON, open, 'O', "Ctrlo", open_acc, XmVaSEPARATOR, XmVaPUSHBUTTON, save, 'S', "Ctrls", save_acc, XmVaPUSHBUTTON, saveas, 'A', NULL, NULL, XmVaSEPARATOR, XmVaPUSHBUTTON, quit, 'Q', "Ctrlq", quit_acc, NULL); XmStringFree(new); XmStringFree(new_acc); XmStringFree(open); XmStringFree(open_acc); XmStringFree(save); XmStringFree(save_acc); XmStringFree(saveas); XmStringFree(quit); XtSetArg(args[0], XmNeditMode, XmMULTI_LINE_EDIT); textw = XmCreateScrolledText(mainw, "textw", args, 1); XtAddCallback(textw, XmNvalueChangedCallback, text_modified_cb, NULL); XtManageChild(textw); XtManageChild(menubar); XtManageChild(mainw); XtRealizeWidget(toplevel); /* Check for initial file specified on command line. */ if ( (argc>1) && argv[1] && *argv[1] ) open_file(argv[1]); XtAppMainLoop(app); }