From: srcd@faraday.physics.utoronto.ca (Solomon Douglas)
Subject: My first Motif program
Summary: comments, please
Organization: Dept. of Physics, Univ. of Toronto
Date: Wed, 22 Jul 1992 15:23:26 GMT

I just finished writing a function in Motif that pops up a little dialog
box, waits for its button to be pressed, then returns.  It seems like a
silly exercise but it's actually going to be used as part of an
introduction to X for new users.  Would anyone be interested in going over
it for me and pointing out any bugs and stylistic errors?  I would greatly
appreciate it.  Responses by e-mail would be preferred.

Thanks in advance.  The program listing follows.

/* window.c - window() displays a popup window at the bottom of the screen
 *            and waits for a button-press, then kills the window and returns.
 *
 * Written by Solomon Douglas, Summer 1992
 */

#include <Xm/RowColumn.h>
#include <Xm/MessageB.h>
#include <Xm/PushB.h>
#include <Xm/Label.h>

/* Define the fonts to use, by means of a fallbacks list */
String fallbacks[] = {
    "xintro*fontList: \
        -*-courier-*-r-*--12-*=courier-12, \
        -*-courier-bold-o-*--14-*=courier-bold-14",
    NULL
};

char *argv[] = { "xintro" };
int argc = 1;
void button_callback(), map_callback();

void
window()
{
    XtAppContext app;
    Widget toplevel = XtVaAppInitialize(&app, "xintro",
        NULL, 0, &argc, argv, fallbacks, NULL);
    Widget dialog;
    int done = 0;

    /*
     * Create the three XmString objects - the title, text, and button of
     * the window
     */

    XmString title = XmStringCreateSimple(
                                "Please follow the directions below.");
    XmString text = XmStringConcat(
                            XmStringCreateLtoR(
"Use the pointing device (mouse or trackball) to point to the\nbutton below \
and press the left button on the pointing device.\n", "courier-bold-14"),
                            XmStringCreateLtoR(
"Notice the change in colours as you move the cursor into and out of this \
window.", "courier-12"));
    XmString ok = XmStringCreateSimple(
                    "Point here and press the left button to continue...");

    /*
     * Create the dialog box itself, and kill two of the buttons
     */

    dialog = XmCreateInformationDialog(toplevel, "", NULL, 0);
    XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
    XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
    
    /*
     * Set various resources of the dialog, including the text to be used
     */

    XtVaSetValues(dialog,
        XmNdefaultPosition, False,
        XmNdialogTitle, title,
        XmNmessageString, text,
        XmNokLabelString, ok,
        XmNdialogStyle, XmDIALOG_SYSTEM_MODAL,
        NULL);

    /*
     * Deallocate the three strings that were used
     */

    XmStringFree(title);
    XmStringFree(text);
    XmStringFree(ok);

    /*
     * button_callback() is the function to be called when the button is
     * pressed.
     */

    XtAddCallback(dialog, XmNokCallback, button_callback, (XtPointer)&done);

    /*
     * map_callback() will get called when the window is mapped, at which
     * point we can decide where to place it on the screen.
     */

    XtAddCallback(dialog, XmNmapCallback, map_callback, (XtPointer)&done);

    /*
     * pop up the window
     */

    XtManageChild(dialog);
    XtPopup(XtParent(dialog), XtGrabNone); /* is this line necessary? */

    /*
     * The main loop: 
     */

    while (!done)
        XtAppProcessEvent(app, XtIMAll);

    /*
     * pop down the window
     */

    XtUnmanageChild(dialog);

    /* TODO:
     * I have no idea what these next two lines are for, but the window
     * doesn't go away without them.  They're in example 5-11 but not in
     * example 5-10 of O'Reilly Volume 6.
     */
    XSync(XtDisplay(dialog), 0);
    XmUpdateDisplay(dialog);
}

void
map_callback(w, cd, cbs)
Widget w;
XtPointer cd;               /* unused */
XmAnyCallbackStruct *cbs;   /* unused */
{
    Dimension width, height;
    XtVaGetValues(w, XmNwidth, &width, XmNheight, &height, NULL);
    XtVaSetValues(w,
        XmNx, (WidthOfScreen(XtScreen(w)) - width) / 2,
        XmNy, HeightOfScreen(XtScreen(w)) - height - 80,
        NULL);
}

void
button_callback(w, cd, cbs)
Widget w;                   /* unused */
XtPointer cd;
XmAnyCallbackStruct *cbs;   /* unused */
{
    /*
     * cd points to a local variable inside "window", which is initialized
     * to 0.  When we set it to 1, window() will know the button's been
     * pressed.
     */

    *cd = 1;
}
-- 
 Solomon <|>   srcd@faraday.physics.utoronto.ca
 Douglas /|\