home *** CD-ROM | disk | FTP | other *** search
- /*
- * prompt box -- display a prompt box on the screen. Ask a question or
- * display information, etc... accepts yes/no/cancel and/or Ok as replies.
- * When the application calls the prompt box, the program "freezes" the
- * screen till the user selects one of the options available and then returns
- * to the application at the point in which the function was called.
- *
- * Because the user must reply to the question or provide some response, it
- * is important not to obscure the dialog box at all -- if it is obscured,
- * then it must raise itself back to the top of the window tree. To do this,
- * we must get visibility notify events. however, there is currently no
- * provision for this in the toolkit intrinsics without breaking the rule
- * of opaque data structures in object oriented programming. Thus, we must
- * include the private header files. Yet, even when visibility notify is
- * set to true, and we try to get the visibility notify event, we don't get
- * it! This is probably a bug with the current intrinsics, but the code
- * remains for when/if it gets fixed. A workaround exists by checking the
- * event types of all events (which is implemented here).
- *
- * The public routine here is PromptBox(BUTTONS, varargs)
- * The idea is to call it as:
- * PromptBox(OK_BUTTON|CANCEL_BUTTON, "rm: remove %s?", file);
- * The return value in this case will be OK_BUTTON *or* CANCEL_BUTTON
- * depending on which the user selected. You also have the choice of
- * YES_BUTTON and NO_BUTTON --to use more than one button, OR values together.
- *
- * To run this file as a standalone program, compile with -DPROGRAM.
- * Otherwise, this file is a module in which you can link with your
- * application to have a quick dialog box (cc -c prompt.c). If used as
- * a library module, the only external global it requires is top_level --
- * which is a pointer to the top_level widget returned by XtInitialize().
- *
- * This file is heavily dependent on the widgetwrap code accompanying this
- * source file. Note, if you are not on a sun workstation and not on a sys-v
- * unix box, and you *do* have vsprintf(), define -DVPRINTF when compiling.
- */
-
- #include <stdio.h>
- #include <X11/Intrinsic.h>
- #include <X11/StringDefs.h>
- #include <X11/Label.h>
- #include <X11/Command.h>
- #include <X11/Box.h>
- #include <X11/Form.h>
- #include <X11/Shell.h>
- #include "WidgetWrap.h"
- #include <varargs.h>
- #include <sys/stat.h>
-
- /* The following defines should exist in some header file somewhere */
- #define YES_BUTTON 1
- #define NO_BUTTON 2
- #define OK_BUTTON 4
- #define CANCEL_BUTTON 8
-
- #define SPACING(w,n) (((w)-((n)*(WIDTH+1)))/(n+1))
- #define WIDTH 60
-
- #ifndef max
- #define max(a,b) (((a) > (b))? (a) : (b))
- #endif /* max */
-
- extern Widget top_level;
- static Widget prompt_shell;
-
- static int ret_value, which_buttons;
- static int _do_prompt();
- static Widget _build_prompt(); /* returns the transient shell created */
-
- PromptBox(va_alist)
- va_dcl
- {
- char string[BUFSIZ], *fmt;
- va_list arg_ptr;
-
- va_start (arg_ptr);
-
- which_buttons = va_arg(arg_ptr, int);
-
- fmt = va_arg (arg_ptr, char *); /* get first arg */
-
- #if defined(sun) || defined(SYSV) || defined(VPRINTF)
- vsprintf(string, fmt, arg_ptr);
- #else /* VPRINTF */
- {
- /* we're on a BSD machine that has no vsprintf() */
- FILE foo;
- foo._cnt = BUFSIZ;
- foo._base = foo._ptr = string; /* may have to cast(unsigned char *) */
- foo._flag = _IOWRT+_IOSTRG;
- (void) _doprnt(fmt, arg_ptr, &foo);
- *foo._ptr = '\0'; /* plant terminating null character */
- }
- #endif /* VPRINTF */
- va_end (arg_ptr);
- return _do_prompt(string);
- }
-
- static int
- _do_prompt(string)
- String string;
- {
- int width;
- Widget shell;
- XEvent event;
-
- if (!top_level || !XtIsRealized(top_level)) {
- fputs(string, stderr);
- return -1; /* we haven't realized the toplevel yet! */
- }
-
- width = max(strlen(string) * 18, 30);
- shell = _build_prompt(string, width);
-
- #ifdef X11R2
- XtMoveWidget(shell,
- (WidthOfScreen(XtScreen(shell)) - width)/2,
- (HeightOfScreen(XtScreen(shell)) - width)/2);
- #else /* X11R2 */
- WidgetSet(shell,
- XtNx, (WidthOfScreen(XtScreen(shell)) - width)/2,
- XtNy, (HeightOfScreen(XtScreen(shell)) - width)/2,
- NULL);
- #endif /* X11R2 */
-
- /* grab exclusive to disallow other windows in this application
- * from being tampered with.
- */
- XtPopup(shell, XtGrabExclusive);
-
- /*
- * Loop here grabbing all events until the dialog box goes away.
- * Because we've set GrabExclusive, no other windows will get
- * events other than expose events, etc.., so we're safe. After
- * the popdown occurs, continue grabbing events till XtPending()
- * says there are no more events to get because the widgets will
- * generate Unmap events and so on.
- */
- for (ret_value = -1; ret_value == -1 || XtPending(); ) {
- XtNextEvent(&event);
- XtDispatchEvent(&event);
- if (ret_value == -1 &&
- event.xany.type == VisibilityNotify &&
- event.xvisibility.state != VisibilityUnobscured &&
- event.xvisibility.window == XtWindow(shell))
- XMapRaised(XtDisplay(shell), XtWindow(shell));
- }
- return ret_value;
- }
-
- static void
- raise_prompt(w, event)
- Widget w;
- XVisibilityEvent *event;
- {
- if (event->state != VisibilityUnobscured && ret_value == -1) {
- XMapRaised(XtDisplay(w), XtWindow(w));
- XFlush(XtDisplay(w));
- }
- }
-
- static void
- PopDown(w, value)
- Widget w;
- int value;
- {
- ret_value = value;
- XtPopdown(prompt_shell);
- XtDestroyWidget(prompt_shell);
- }
-
- static Widget
- _build_prompt(string, width)
- char *string;
- int width;
- {
- Widget top, box, yes, no, cancel, ok;
- int nbuttons = 0;
-
- prompt_shell = WidgetCreate(NULL, transientShellWidgetClass, top_level,
- XtNpopupShell, True,
- NULL);
-
- /* this currently doesn't work, but it should */
- {
- XtActionsRec foo;
-
- foo.string = "raise-prompt";
- foo.proc = raise_prompt;
- XtAddActions(&foo, 1);
-
- /* prompt_shell->core.visible_interest = TRUE; */
- XtOverrideTranslations(prompt_shell,
- XtParseTranslationTable("<Visible>: raise-prompt()"));
- }
-
- top = WidgetCreate(NULL, boxWidgetClass, prompt_shell,
- XtNhSpace, 0,
- XtNvSpace, 0,
- NULL);
-
- WidgetCreate(NULL, labelWidgetClass, top,
- XtNlabel, string,
- XtNwidth, width,
- NULL);
-
- if (which_buttons & YES_BUTTON)
- nbuttons++;
- if (which_buttons & NO_BUTTON)
- nbuttons++;
- if (which_buttons & OK_BUTTON)
- nbuttons++;
- if (which_buttons & CANCEL_BUTTON)
- nbuttons++;
-
- box = WidgetCreate(NULL, boxWidgetClass, top,
- XtNfromVert, box,
- XtNwidth, width,
- XtNhSpace, SPACING(width-3, nbuttons),
- /* I'd like to use a gray pixmap here, but the athena box widget
- * will free the pixmap once this is destroyed and other widgets
- * that have a handle to it will die with an invalid pixmap error
- * if they try to use their pixmap again.
- */
- /* XtNbackgroundPixmap, XtGrayPixmap(XtScreen(top_level)), */
- NULL);
-
- if (which_buttons & YES_BUTTON) {
- yes = WidgetCreate(NULL, commandWidgetClass, box,
- XtNwidth, WIDTH,
- XtNlabel, "Yes",
- NULL);
- XtAddCallback(yes, XtNcallback, PopDown, YES_BUTTON);
- }
-
- if (which_buttons & NO_BUTTON) {
- no = WidgetCreate(NULL, commandWidgetClass, box,
- XtNwidth, WIDTH,
- XtNlabel, "No",
- NULL);
- XtAddCallback(no, XtNcallback, PopDown, NO_BUTTON);
- }
-
- if (which_buttons & OK_BUTTON) {
- ok = WidgetCreate(NULL, commandWidgetClass, box,
- XtNwidth, WIDTH,
- XtNlabel, "Ok",
- NULL);
- XtAddCallback(ok, XtNcallback, PopDown, OK_BUTTON);
- }
-
- if (which_buttons & CANCEL_BUTTON) {
- cancel = WidgetCreate(NULL, commandWidgetClass, box,
- XtNwidth, WIDTH,
- XtNlabel, "Cancel",
- NULL);
- XtAddCallback(cancel, XtNcallback, PopDown, CANCEL_BUTTON);
- }
-
- return prompt_shell;
- }
-
- #ifdef PROGRAM
-
- Widget top_level;
- char *filename;
-
- /*ARGSUSED*/
- static void
- callback_func(w, _flags)
- Widget w;
- caddr_t _flags;
- {
- char *label;
- FILE *fp;
- struct stat buf;
- int flags = (int)_flags;
-
- WidgetGet(w, XtNlabel, &label, NULL);
-
- if (!strcmp(label, "Create")) {
- if (stat(filename, &buf) == 0)
- PromptBox(OK_BUTTON, "%s already exists!", filename);
- else if (PromptBox(flags, "Create file %s?", filename)
- == YES_BUTTON)
- if ((fp = fopen(filename, "w")) == (FILE *)NULL)
- PromptBox(OK_BUTTON, "I can't create %s.", filename);
- else
- fclose(fp);
- } else if (!strcmp(label, "Delete")) {
- if (stat(filename, &buf) == -1)
- PromptBox(OK_BUTTON, "%s doesn't exist!", filename);
- else if (PromptBox(flags, "Delete file %s?", filename)
- == YES_BUTTON)
- if (unlink(filename) == -1)
- PromptBox(OK_BUTTON, "I can't remove %s.", filename);
- } else if (PromptBox(flags, "Really Exit?") == OK_BUTTON)
- exit(0);
- }
-
- main(argc, argv)
- unsigned int argc;
- char **argv;
- {
- char trans[128], *name;
- Widget box, w1, w2, w3;
-
- /* initialize the toolkit and register the actions */
- top_level = XtInitialize(*argv, *argv, NULL, 0, &argc, argv);
-
- if (argc > 1)
- filename = argv[1];
- else
- fprintf(stderr, "usage: %s filename\n", argv[0]), exit(1);
-
- /* create the top button and its form parent */
- box = WidgetCreate(NULL, boxWidgetClass, top_level, NULL);
-
- w1 = WidgetCreate("button1", commandWidgetClass, box,
- XtNlabel, "Create",
- XtNwidth, 200,
- XtNheight, 30,
- NULL);
- XtAddCallback(w1, XtNcallback, callback_func,
- (caddr_t)(YES_BUTTON|NO_BUTTON));
-
- w2 = WidgetCreate("button2", commandWidgetClass, box,
- XtNlabel, "Delete",
- XtNwidth, 200,
- XtNheight, 30,
- NULL);
- XtAddCallback(w2, XtNcallback, callback_func,
- (caddr_t)(YES_BUTTON|NO_BUTTON));
-
- w3 = WidgetCreate("button3", commandWidgetClass, box,
- XtNlabel, "Exit",
- XtNwidth, 200,
- XtNheight, 30,
- NULL);
- XtAddCallback(w3, XtNcallback, callback_func,
- (caddr_t)(OK_BUTTON|CANCEL_BUTTON));
-
- XtRealizeWidget(top_level);
- XtMainLoop();
- }
-
- #endif /* PROGRAM */
-