/* Written by Dan Heller and Paula Ferguson.  
 * Copyright 1994, O'Reilly & Associates, Inc.
 * Permission to use, copy, and modify this program without
 * restriction is hereby granted, as long as this copyright
 * notice appears in each copy of the program source code.
 * This program is freely distributable without licensing fees and
 * is provided without guarantee or warrantee expressed or implied.
 * This program is -not- in the public domain.
 */

/* warn_msg.c -- display a very urgent warning message.
 * Really catch the user's attention by flashing an urgent-
 * looking pixmap every 250 milliseconds.
 * The program demonstrates how to set the XmNsymbolPixmap
 * resource, how to destroy the pixmap and how to use timers.
 */
#include <Xm/MessageB.h>
#include <Xm/PushB.h>

#include "bang0.symbol"
#include "bang1.symbol"

#define TEXT "Alert!\n\
The computer room is ON FIRE!\n\
All of your e-mail will be lost."

/* define the data structure we need to implement flashing effect */
typedef struct {
    XtIntervalId   id;
    int            which;
    Pixmap         pix1, pix2;
    Widget         dialog;
    XtAppContext   app;
} TimeOutClientData;

main(argc, argv)
int argc;
char *argv[];
{
    XtAppContext app;
    Widget toplevel, button;
    XmString label;
    void warning();

    XtSetLanguageProc (NULL, NULL, NULL);

    toplevel = XtVaAppInitialize (&app, "Demos",
        NULL, 0, &argc, argv, NULL, NULL);

    label = XmStringCreateLocalized (
        "Don't Even Think About Pressing This Button");
    button = XtVaCreateManagedWidget ("button",
        xmPushButtonWidgetClass, toplevel,
        XmNlabelString,          label,
        NULL);
    XmStringFree (label);

    /* set up callback to popup warning */
    XtAddCallback (button, XmNactivateCallback, warning, NULL);

    XtRealizeWidget (toplevel);
    XtAppMainLoop (app);
}

/* warning() -- callback routine for the button.  Create a message
 * dialog and set the message string.  Allocate an instance of
 * the TimeOutClientData structure and set a timer to alternate
 * between the two pixmaps.  The data is passed to the timeout
 * routine and the callback for when the user presses "OK".
 */
void
warning(parent, client_data, call_data)
Widget parent;
XtPointer client_data;
XtPointer call_data;
{
    Widget        dialog;
    XtAppContext  app = XtWidgetToApplicationContext (parent);
    XmString      text;
    extern void   done(), destroy_it(), blink();
    Display      *dpy = XtDisplay (parent);
    Screen       *screen = XtScreen (parent);
    Pixel         fg, bg;
    Arg           args[5];
    int           n, depth;
    TimeOutClientData *data = XtNew (TimeOutClientData);

    /* Create the dialog */
    n = 0;
    XtSetArg (args[n], XmNdeleteResponse, XmDESTROY); n++;
    dialog = XmCreateMessageDialog (parent, "danger", args, n);

    XtUnmanageChild (XmMessageBoxGetChild (dialog, XmDIALOG_CANCEL_BUTTON));
    XtUnmanageChild (XmMessageBoxGetChild (dialog, XmDIALOG_HELP_BUTTON));

    XtAddCallback (dialog, XmNokCallback, done, NULL);
    XtAddCallback (dialog, XmNdestroyCallback, destroy_it, data);

    /* now that dialog has been created, it's colors are initialized */
    XtVaGetValues (dialog,
        XmNforeground, &fg,
        XmNbackground, &bg,
        XmNdepth, &depth,
        NULL);

    /* Create pixmaps that are going to be used as symbolPixmaps.
     * Use the foreground and background colors of the dialog.
     */
    data->pix1 = XCreatePixmapFromBitmapData (dpy, XtWindow (parent),
        bang0_bits, bang0_width, bang0_height, fg, bg, depth);
    data->pix2 = XCreatePixmapFromBitmapData (dpy, XtWindow (parent),
        bang1_bits, bang1_width, bang1_height, fg, bg, depth);
    /* complete the timeout client data */
    data->dialog = dialog;
    data->app = app;

    /* Add the timeout for blinking effect */
    data->id = XtAppAddTimeOut (app, 1000L, blink, data);

    /* display the help text and the appropriate pixmap */
    text = XmStringCreateLtoR (TEXT, XmFONTLIST_DEFAULT_TAG);
    XtVaSetValues (dialog,
        XmNmessageString,      text,
        XmNsymbolPixmap,       data->pix2,
        NULL);
    XmStringFree (text);

    XtManageChild (dialog);
    XtPopup (XtParent (dialog), XtGrabNone);
}

/* blink() -- visual blinking effect for dialog's symbol.  Displays
 * flashing ! symbol, restarts timer and saves timer id.
 */
void
blink(client_data, id)
XtPointer client_data;
XtIntervalId *id;
{
    TimeOutClientData *data = (TimeOutClientData *) client_data;

    data->id = XtAppAddTimeOut (data->app, 250L, blink, data);
    data->which = !data->which;
    XtVaSetValues (data->dialog,
        XmNsymbolPixmap,  data->which?
            data->pix1 : data->pix2, NULL);
    /*XtVaSetValues (data->dialog,
        XmNsymbolPixmap,  (data->which = !data->which) ?
            data->pix1 : data->pix2, NULL);*/
}

/* done() -- called when user presses "OK" in dialog or
 * if the user picked the Close button in system menu.
 * Remove the timeout id stored in data, free pixmaps and
 * make sure the widget is destroyed (which is only when
 * the user presses the "OK" button.
 */
void
done(dialog, client_data, call_data)
Widget dialog;
XtPointer client_data;
XtPointer call_data;
{
    XtDestroyWidget(dialog);
}

/* destroy_it() -- called when dialog is destroyed.  Removes
 * timer and frees allocated data.
 */
void
destroy_it(dialog, client_data, call_data)
Widget dialog;
XtPointer client_data;
XtPointer call_data;
{
    TimeOutClientData *data = (TimeOutClientData *) client_data;
    Pixmap symbol;

    XtRemoveTimeOut (data->id);
    XFreePixmap (XtDisplay (data->dialog), data->pix1);
    XFreePixmap (XtDisplay (data->dialog), data->pix2);
    XtFree (data);
}