home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Uip / rcvalert / xalert.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  15.8 KB  |  732 lines

  1. /* xalert.c: X based alert program */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/xalert.c,v 6.0 1991/12/18 20:39:41 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/xalert.c,v 6.0 1991/12/18 20:39:41 jpo Rel $
  9.  *
  10.  * $Log: xalert.c,v $
  11.  * Revision 6.0  1991/12/18  20:39:41  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. #include <stdio.h>
  19. #include <X11/Intrinsic.h>
  20. #include <X11/StringDefs.h>
  21. #include <X11/Shell.h>
  22. #include <X11/Xaw/Command.h>    
  23. #include <X11/Xaw/Box.h>
  24. #include <X11/Xaw/Label.h>
  25. #include <X11/Xaw/Cardinals.h>    
  26. #include <X11/Xaw/Form.h>
  27. #include <X11/Xaw/Text.h>
  28. #include <X11/Xaw/AsciiText.h>
  29. #include <X11/Xaw/MenuButton.h>
  30. #include <X11/Xaw/SimpleMenu.h>
  31. #include <X11/Xaw/Sme.h>
  32. #include <X11/Xaw/SmeBSB.h>
  33. #include <X11/Xaw/SmeLine.h>
  34. #include <X11/Xaw/Dialog.h>
  35. #include <X11/Xaw/Paned.h>
  36. #include <pwd.h>
  37.  
  38. #include <isode/manifest.h>
  39. #include <isode/psap.h>
  40. #include <sys/types.h>
  41. #include "sys.file.h"
  42. #include <sys/stat.h>
  43. #include <utmp.h>
  44. #include <sys/time.h>
  45. #include <ctype.h>
  46. #include <signal.h>
  47.  
  48. #include "data.h"
  49. #include "image.h"
  50.  
  51. #define check_width 9
  52. #define check_height 8
  53. static char check_bits[] = {
  54.    0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00,
  55.    0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00
  56. };
  57.  
  58. #define    BASIC_WIDTH 400
  59.  
  60. static struct _app_resources {
  61.     char    *filename;
  62.     char    *user;
  63.     int    port;
  64.     Boolean    bell;
  65.     Boolean autoraise;
  66.     Boolean photos;
  67. } app_resource;
  68.  
  69. static int    defaultPort = 0;
  70. char    homedir[BUFSIZ];
  71. char filename[] = ".alert";
  72.  
  73. char a_filename[]="-filename";
  74. char a_user[]    = "-user";
  75. char a_port[]    = "-port";
  76. char a_d[]    = "-d";
  77. char a_f[]    = "-f";
  78. char a_u[]    = "-u";
  79. char a_p[]    = "-p";
  80. char a_s[]    = "-s";
  81. char a_t[]    = "-t";
  82. char a_w[]    = "-w";
  83. char a_x[]    = "-x";
  84.  
  85. #define offset(x)    XtOffset (struct _app_resources *, x)
  86. static XtResource resources[] = {
  87. {"fileName",    "FileName",    XtRString,    sizeof (String),
  88.      offset(filename),    XtRString,     (caddr_t) filename },
  89. {"userName",    "UserName",    XtRString,    sizeof (String),
  90.      offset(user),        XtRString,    (caddr_t) NULL },
  91. {"port",    "Port",        XtRInt,        sizeof (int),
  92.      offset(port),        XtRInt,        (caddr_t) &defaultPort },
  93. {"bell",    "Bell",        XtRBoolean,    sizeof(Boolean),
  94.      offset(bell),        XtRImmediate,    (caddr_t)1},
  95. {"autoRaise",    "AutoRaise",    XtRBoolean,    sizeof(Boolean),
  96.      offset(autoraise),    XtRImmediate,    (caddr_t)0},
  97. #ifndef NOPHOTOS
  98. {"photos",    "Photos",    XtRBoolean,    sizeof(Boolean),
  99.      offset(photos),    XtRImmediate,    (caddr_t)1},
  100. #endif
  101. };
  102.  
  103. static XrmOptionDescRec table[] = {
  104. {a_filename,    "fileName",    XrmoptionSepArg,    (caddr_t) NULL},
  105. {a_user,    "userName",    XrmoptionSepArg,    (caddr_t) NULL},
  106. {a_port,    "port",        XrmoptionSepArg,    (caddr_t) NULL},
  107. {"-nobell",    "Bell",        XrmoptionNoArg,        (caddr_t)"False"},
  108. {"-bell",    "Bell",        XrmoptionNoArg,        (caddr_t)"True"},
  109. {"-autoraise",    "AutoRaise",    XrmoptionNoArg,        (caddr_t)"True"},
  110. {"-noautoraise","AutoRaise",    XrmoptionNoArg,        (caddr_t)"False"},
  111. #ifndef NOPHOTOS
  112. {"-nophotos",    "Photos",    XrmoptionNoArg,        (caddr_t)"False"},
  113. {"-photos",    "Photos",    XrmoptionNoArg,        (caddr_t)"True"},
  114. #endif
  115. };
  116.  
  117. XtAppContext context;
  118. Display *dpy;
  119. Screen     *scrn;
  120. Widget     toplevel, pane, box, qb, topform, txt, photow, photolbl, db, optionw, pbox;
  121. static Pixmap check;
  122.  
  123. char    username[128];
  124. int    replysock;
  125. char    twfilename[BUFSIZ];
  126. char    hostname[128];
  127. char    *extra = "NEW: ";
  128. char    *format = "%extra(%size) %20from %subject << %50body";
  129. static char    *myname;
  130. int    width = 80;
  131. int    debug = 0;
  132. int    stdoutonly = 0;
  133. int    no_x = 0;
  134. int    termwidth=80;
  135.  
  136. static void    Quit ();
  137. static void    QuitCancel ();
  138. static void    Delete ();
  139. static void    TextIn ();
  140. static void    catch_exit ();
  141. static int    EQuit ();
  142. static int    EQuit2 ();
  143. static void    Cancel ();
  144. static void    Ok ();
  145. static void create_menu ();
  146. #ifndef NOPHOTOS
  147. static void     lookup_photo ();
  148. static void    PhotoClr ();
  149. static void photo_clr ();
  150.  
  151. #endif
  152.  
  153. XtActionsRec actionTable[] = {
  154. {"Ok",    Ok},
  155. {"Cancel",    Cancel}
  156. };
  157.  
  158. XrmDatabase fred;
  159.  
  160. main (argc, argv)
  161. int    argc;
  162. char    *argv[];
  163. {
  164.     int sd;
  165.     struct passwd *pwd;
  166.     char    *cp, *getenv ();
  167.     long    ptr;
  168.     XrmValue value;
  169.  
  170.     value.size=sizeof(ptr);
  171.     value.addr= (caddr_t) (&ptr);
  172.  
  173.     myname = argv[0];
  174.     if ((pwd = getpwuid (getuid ())) == NULL) {
  175.         fprintf (stderr, "Unknown user");
  176.     }
  177.     else {
  178.         (void) strcpy (username, pwd -> pw_name);
  179.         if ((cp = getenv ("HOME")) && *cp)
  180.             (void) strcpy (homedir, cp);
  181.         else
  182.             (void) strcpy (homedir, pwd -> pw_dir);
  183.     }
  184.  
  185.     pre_scan(argc, argv);
  186.  
  187.     if (! no_x) {
  188.         XtToolkitInitialize();
  189.         context = XtCreateApplicationContext();
  190.         dpy = XtOpenDisplay(context, (String)NULL, "xalert", "XAlert",
  191.                     table, XtNumber(table), &argc, argv);
  192.         if (dpy == (Display *)0) {
  193.             fprintf (stderr, "Unable to open display, so using tty\n");
  194.             no_x++;
  195.         }
  196.     }
  197.  
  198.     if (no_x) {
  199.         if (!app_resource.filename) app_resource.filename = filename;
  200.         if (!app_resource.user) app_resource.user = username;
  201.         signal(SIGHUP, catch_exit);
  202.         signal(SIGTERM, catch_exit);
  203.         signal(SIGINT, catch_exit);
  204.         sd = udp_start (app_resource.port, app_resource.filename, homedir);
  205.         for (;;) {
  206.             fd_set rfds;
  207.             char    buffer[BUFSIZ];
  208.             char    from[BUFSIZ];
  209.             int    n;
  210.     
  211.             FD_ZERO (&rfds);
  212.             FD_SET (sd, &rfds);
  213.             if(select (sd + 1, &rfds, NULLFD, NULLFD,
  214.                    (struct timeval *)0) <= 0)
  215.                 continue;
  216.     
  217.             n = sizeof (buffer) - 1;
  218.             if (FD_ISSET (sd, &rfds) &&
  219.                 getdata (sd, buffer, &n, app_resource.user,
  220.                      from)) {
  221.                 buffer[n] = 0;
  222.                 if (termwidth < n) buffer[termwidth] = 0;
  223.                 if (stdoutonly || (notify_normal (buffer, app_resource.user) == NOTOK &&
  224.                            isatty (1)))
  225.                     printf ("\n\r%s%c\n\r",
  226.                         buffer, '\007');
  227.             }
  228.         }
  229.     }
  230.  
  231.     scrn = DefaultScreenOfDisplay(dpy);
  232.  
  233.     XtAppAddActions(context, actionTable, XtNumber(actionTable));
  234.  
  235.     toplevel = XtAppCreateShell("xalert", "XAlert", 
  236.                     applicationShellWidgetClass, dpy, NULL,0);
  237.  
  238.     XtGetApplicationResources (toplevel, (caddr_t)&app_resource, resources,
  239.                    XtNumber(resources), NULL, 0);
  240.  
  241.     if (app_resource.user == NULL)
  242.         app_resource.user = username;
  243.  
  244.     sd = udp_start (app_resource.port, app_resource.filename, homedir);
  245.  
  246.     pane = XtVaCreateManagedWidget ("toppane",
  247.                     panedWidgetClass,
  248.                     toplevel,
  249.                     NULL);
  250.  
  251.     topform = XtVaCreateManagedWidget("topform",
  252.                       formWidgetClass,
  253.                       pane,
  254.                       NULL);
  255.     box = XtVaCreateManagedWidget ("box",
  256.                        formWidgetClass,
  257.                        topform,
  258.                        NULL);
  259.  
  260.         qb = XtVaCreateManagedWidget ("Quit",
  261.                       commandWidgetClass,
  262.                       box,
  263.                       NULL);
  264.     XtAddCallback(qb, XtNcallback, QuitCancel, NULL);
  265.  
  266.     db = XtVaCreateManagedWidget ("Clear",
  267.                       commandWidgetClass,
  268.                       box,
  269.                       NULL);
  270.     XtAddCallback (db, XtNcallback, Delete, NULL);
  271.  
  272.     optionw = XtVaCreateManagedWidget ("Options",
  273.                        menuButtonWidgetClass,
  274.                        box,
  275.                        XtNmenuName, "Options",
  276.                        NULL);
  277.  
  278.     create_menu (toplevel, "Options", optionw);
  279.  
  280.     txt = XtVaCreateManagedWidget("text",
  281.                       asciiTextWidgetClass,
  282.                       topform,
  283.                       NULL);
  284. #ifndef NOPHOTOS
  285.     pbox = XtVaCreateWidget ("pbox",
  286.                  formWidgetClass,
  287.                  pane,
  288.                  NULL);
  289.  
  290.     photolbl = XtVaCreateManagedWidget ("photolabel",
  291.                         labelWidgetClass,
  292.                         pbox,
  293.                         NULL);
  294.  
  295.     photow = XtVaCreateManagedWidget ("photo",
  296.                       commandWidgetClass,
  297.                       pbox,
  298.                       XtNlabel,    "",
  299.                       0);
  300.     XtAddCallback (photow, XtNcallback, PhotoClr, NULL);
  301.  
  302.     if(app_resource.photos) {
  303.         XtManageChild(pbox);
  304.     }
  305.  
  306. #endif
  307.  
  308.     XSetErrorHandler (EQuit);
  309.     XSetIOErrorHandler (EQuit2);
  310.  
  311.     (void) XtAppAddInput (context, sd, XtInputReadMask, TextIn, NULL);
  312.     
  313.     XtInstallAllAccelerators(txt, toplevel);
  314.  
  315.     XtRealizeWidget(toplevel);
  316.  
  317.     XtSetKeyboardFocus(toplevel, txt);
  318.  
  319.     XtAppMainLoop (context);
  320. }
  321.  
  322. static void    Reset ();
  323. static void    ToggleBell ();
  324. static void     AutoRaise ();
  325. #ifndef NOPHOTOS
  326. static void    TogglePhotos ();
  327. #endif
  328.  
  329. struct MenuEntries {
  330.     char *name;
  331.     void (*fnx)();
  332.     Boolean    *state;
  333. };
  334.  
  335. struct MenuEntries menus[] = {
  336.     "Reset",     Reset,        NULL,
  337.     "Bell",        ToggleBell,    &app_resource.bell,
  338.     "AutoRaise",     AutoRaise,    &app_resource.autoraise,
  339. #ifndef NOPHOTOS
  340.     "Photos",    TogglePhotos,    &app_resource.photos,
  341. #endif
  342.     NULLCP,        NULL,        NULL,
  343.     };
  344.  
  345. static void create_menu (top, name, button)
  346. Widget top;
  347. char    *name;
  348. Widget button;
  349. {
  350.     Widget mw, bsb;
  351.     struct MenuEntries *mp;
  352.  
  353.     check = XCreateBitmapFromData (dpy,
  354.                        RootWindowOfScreen(XtScreen(top)),
  355.                        check_bits,
  356.                        check_width,
  357.                        check_height);
  358.     mw = XtVaCreatePopupShell (name,
  359.                    simpleMenuWidgetClass,
  360.                    button,
  361.                    NULL);
  362.  
  363.     for (mp = menus; mp -> name; mp ++) {
  364.         bsb = XtVaCreateManagedWidget (mp -> name,
  365.                            smeBSBObjectClass,
  366.                            mw,
  367.                            XtNleftMargin, check_width + 5,
  368.                            NULL);
  369.         XtAddCallback (bsb, XtNcallback, mp -> fnx, button);
  370.         if (mp -> state && *mp ->state)
  371.             XtVaSetValues (bsb,
  372.                        XtNleftBitmap, check,
  373.                        NULL);
  374.     }
  375. }
  376.  
  377. /* ARGSUSED */
  378. static void    TextIn (cdata, fdp, iid)
  379. caddr_t    cdata;
  380. int    *fdp;
  381. XtInputId *iid;
  382. {
  383.     char    buffer[BUFSIZ];
  384.     char    from[BUFSIZ];
  385.     int    n;
  386.  
  387.     if (*fdp == 0) {
  388.         if ((n = read (*fdp, buffer, sizeof buffer)) <= 0)
  389.             Quit (toplevel, (caddr_t)0, (caddr_t)0);
  390.         buffer[n] = 0;
  391.         AddText (buffer, n);
  392.     }
  393.     else {
  394.         if (getdata (*fdp, buffer, &n, app_resource.user, from)) {
  395.             AddText (buffer, n);
  396. #ifndef NOPHOTOS
  397.             lookup_photo(from);
  398. #endif
  399.         }
  400.         
  401.     }
  402. }
  403.  
  404. /* ARGSUSED */
  405. static int    EQuit (disp, error)
  406. Display *disp;
  407. XErrorEvent *error;
  408. {
  409.     Quit (toplevel, (caddr_t)0, (caddr_t)0);
  410. }
  411.  
  412. /* ARGSUSED */
  413. static int    EQuit2 (disp)
  414. Display *disp;
  415. {
  416.     Quit (toplevel, (caddr_t)0, (caddr_t)0);
  417. }
  418.  
  419. /* ARGSUSED */
  420. static void Quit(widget, closure, callData)
  421. Widget widget;
  422. caddr_t closure;
  423. caddr_t callData;
  424. {
  425.     XtDestroyWidget(toplevel);
  426.     catch_exit();
  427. }
  428.  
  429. static void catch_exit()
  430. {
  431.     if (twfilename[0])
  432.         (void) unlink (twfilename);
  433.     udp_cleanup ();
  434.  
  435.     exit(0);
  436. }
  437.  
  438. AddText (s, n)
  439. char    *s;
  440. int    n;
  441. {
  442.     XawTextPosition      last;
  443.     XawTextBlock text;
  444.  
  445.     XawTextSetInsertionPoint (txt, (XawTextPosition)9999999);
  446.     last = XawTextGetInsertionPoint (txt);
  447.  
  448.     text.ptr = s;
  449.     text.firstPos = 0;
  450.     text.length = n;
  451.     text.format = FMT8BIT;
  452.  
  453.     if (XawTextReplace (txt, last, last, &text) != XawEditDone)
  454.         XBell (XtDisplay (txt), 0);
  455.     else {
  456.         XawTextPosition newend;
  457.  
  458.         XawTextSetInsertionPoint(txt, last + text.length);
  459.         newend = XawTextGetInsertionPoint(txt);
  460.         if (text.ptr[text.length-1] != '\n') {
  461.             text.ptr = "\n";
  462.             text.length = 1;
  463.             XawTextReplace(txt, newend, newend, &text);
  464.             XawTextSetInsertionPoint(txt, newend += 1);
  465.         }
  466.     }
  467.     if (app_resource.bell)
  468.         XBell (XtDisplay (toplevel), 50);
  469.     if (app_resource.autoraise)
  470.         XMapRaised (dpy, XtWindow(toplevel));
  471. }
  472.  
  473. /* ARGSUSED */
  474. static void Reset (widget, closure, callData)
  475. Widget widget;
  476. caddr_t closure;
  477. caddr_t callData;
  478. {
  479.     makeredirfile (app_resource.filename, homedir);
  480. }
  481.  
  482. /* ARGSUSED */
  483. static void ToggleBell (widget, closure, callData)
  484. Widget widget;
  485. caddr_t closure;
  486. caddr_t callData;
  487. {
  488.     app_resource.bell = !app_resource.bell;
  489.     if (app_resource.bell)
  490.         XtVaSetValues (widget, XtNleftBitmap, check, NULL);
  491.     else    XtVaSetValues (widget, XtNleftBitmap, None, NULL);
  492. }
  493.  
  494. /* ARGSUSED */
  495. static void AutoRaise (widget, closure, callData)
  496. Widget widget;
  497. caddr_t closure;
  498. caddr_t callData;
  499. {
  500.     app_resource.autoraise = !app_resource.autoraise;
  501.     if (app_resource.autoraise)
  502.         XtVaSetValues (widget, XtNleftBitmap, check, NULL);
  503.     else    XtVaSetValues (widget, XtNleftBitmap, None, NULL);
  504. }
  505.  
  506. /* ARGSUSED */
  507. static void Delete (widget, closure, callData) 
  508. Widget widget;
  509. caddr_t closure;
  510. caddr_t callData;
  511. {
  512.     XtVaSetValues (txt, XtNstring, "", NULL);
  513. #ifndef NOPHOTOS
  514.     photo_clr ();
  515. #endif
  516. }
  517.  
  518.  
  519. /* YUCK ! This should use XrmParseCommand etc ... */
  520. pre_scan (argc, argv)
  521. int    argc;
  522. char    *argv[];
  523. {
  524.     int i;
  525.  
  526.     for (i=1; i<argc; i++)
  527.     {    if (!strcmp(argv[i], a_filename) || !strcmp(argv[i], a_f))
  528.             app_resource.filename = argv[++i];
  529.         else if (!strcmp(argv[i], a_user) || !strcmp(argv[i], a_u))
  530.             app_resource.user = username;
  531.         else if (!strcmp(argv[i], a_port) || !strcmp(argv[i], a_p))
  532.             app_resource.port = atoi(argv[++i]);
  533.         else if (!strcmp(argv[i], a_s))
  534.             stdoutonly = 1;
  535.         else if (!strcmp(argv[i], a_t))
  536.             no_x = 1;
  537.         else if (!strcmp(argv[i], a_w))
  538.             termwidth = atoi(argv[++i]);
  539.         else if (!strcmp(argv[i], a_x))
  540.             no_x = 0;
  541.         else if (!strcmp(argv[i], a_d))
  542.             debug = 1;
  543.     }
  544. }
  545.  
  546. #ifndef NOPHOTOS
  547. /*ARGSUSED*/
  548. static void TogglePhotos (widget, closure, callData)
  549. Widget widget;
  550. caddr_t closure;
  551. caddr_t callData;
  552. {
  553.     app_resource.photos = !app_resource.photos;
  554.  
  555.     if (app_resource.photos) {
  556.         XtVaSetValues (widget, XtNleftBitmap, check, NULL);
  557.         XtManageChild(pbox);
  558.         photo_clr();
  559.     }
  560.     else {
  561.         XtVaSetValues (widget, XtNleftBitmap, None, NULL);
  562.         XtUnmanageChild(pbox);
  563.     }
  564. }
  565.  
  566.  
  567. static void photo_clr ()
  568. {
  569.     XtVaSetValues (photow, XtNbitmap, None, NULL);
  570.     XtVaSetValues (photow, XtNlabel, "", NULL);
  571.     XtVaSetValues (photolbl, XtNlabel, "", NULL);
  572. }
  573.  
  574. /* ARGSUSED */
  575. static void PhotoClr (widget, closure, callData) 
  576. Widget widget;
  577. caddr_t closure;
  578. caddr_t callData;
  579. {
  580.     photo_clr ();
  581. }
  582.  
  583. static void lookup_photo (from)
  584. char *from;
  585. {
  586.     static int first_time = 0;
  587.     char    *cp;
  588.     char    user[BUFSIZ];
  589.     Pixmap pix;
  590.     struct image *image;
  591.  
  592.     if (app_resource.photos == False)
  593.         return;
  594.  
  595.     if (first_time == 0) {
  596.         extern int ufn_indent;
  597.         first_time = 1;
  598.         ufn_indent = 0;
  599.         init_aka (myname, 0, NULLCP);
  600.     }
  601.     if (XtIsRealized(photow) == 0)
  602.         return;
  603.  
  604.     photo_clr (photow);
  605.  
  606.     if ((cp = index(from, '@')) == NULL)
  607.         return;
  608.  
  609.     (void) strncpy (user, from, cp - from);
  610.     user[cp - from] = 0;
  611.  
  612.     if ((image = fetch_image (user, cp + 1)) == NULL)
  613.         return;
  614.  
  615.     if (image -> data) {
  616.         pix = XCreateBitmapFromData (dpy, XtWindow (photow),
  617.                          image -> data -> qb_forw -> qb_data,
  618.                          image -> width, image -> height);
  619.         if (pix == None)
  620.             return;
  621.         XtVaSetValues (photow,
  622.                    XtNbitmap, pix,
  623.                    0);
  624.     }
  625.     else {
  626.         char lbuf[BUFSIZ*2];
  627.  
  628.         lbuf[0] = 0;
  629.         if (image -> phone) 
  630.             (void) strcat (lbuf, image -> phone);
  631.         if (image -> address)
  632.             (void) strcat (lbuf, image -> address);
  633.         if (image -> info)
  634.             (void) strcat (lbuf, image -> info);
  635.         if (image -> description)
  636.             (void) strcat (lbuf, image -> description);
  637.         XtVaSetValues (photow,
  638.                    XtNlabel, lbuf,
  639.                    NULL);
  640.     }
  641.     if (image -> ufnname)
  642.         XtVaSetValues (photolbl,
  643.                    XtNlabel, image -> ufnname,
  644.                    NULL);
  645. }
  646.  
  647. #endif
  648.  
  649.  
  650.  
  651. static void DestroyPopupPrompt(); /* the callback of the popup cancel button */
  652. static void Ok();        /* an action proc calling ColorTheButton */
  653.  
  654.  
  655. /*ARGSUSED*/
  656. static void 
  657. QuitCancel(button, client_data, call_data)
  658. Widget    button;        
  659. XtPointer client_data, call_data;
  660. {
  661.     Arg        args[5];
  662.     Widget    popup, dialog;
  663.     Position    x, y;
  664.     Dimension    width, height;
  665.     Cardinal    n;
  666.  
  667.     n = 0;
  668.     XtSetArg(args[0], XtNwidth, &width); n++;
  669.     XtSetArg(args[1], XtNheight, &height); n++;
  670.     XtGetValues(button, args, n);
  671.     XtTranslateCoords(button, (Position) (width / 2), (Position) (height / 2),
  672.               &x, &y);
  673.  
  674.     n = 0;
  675.     XtSetArg(args[n], XtNx, x);                n++;
  676.     XtSetArg(args[n], XtNy, y);                n++;
  677.  
  678.     popup = XtCreatePopupShell("prompt", transientShellWidgetClass, button,
  679.                    args, n);
  680.  
  681.     dialog = XtVaCreateManagedWidget("dialog",
  682.                      dialogWidgetClass,
  683.                      popup,
  684.                      NULL);
  685.  
  686.     /*
  687.      * The prompting message's size is dynamic; allow it to request resize. 
  688.      */
  689.  
  690.     XawDialogAddButton(dialog, "ok", Quit, (XtPointer) dialog);
  691.     XawDialogAddButton(dialog, "cancel", DestroyPopupPrompt,(XtPointer)dialog);
  692.  
  693.     XtInstallAllAccelerators(dialog, dialog);    
  694.  
  695.     XtPopup(popup, XtGrabExclusive);
  696.  
  697.     XtSetKeyboardFocus(toplevel, dialog);
  698. }
  699. /*ARGSUSED*/
  700. static void 
  701. DestroyPopupPrompt(widget, client_data, call_data)
  702. Widget    widget;        
  703. XtPointer client_data, call_data;    
  704. {
  705.     Widget popup = XtParent( (Widget) client_data);
  706.     XtDestroyWidget(popup);
  707. }
  708.  
  709. /*ARGSUSED*/
  710. static void 
  711. Ok(widget, event, params, num_params)
  712. Widget widget;        
  713. XEvent *event;        
  714. String *params;    
  715. Cardinal *num_params;
  716. {
  717.     catch_exit ();
  718. }
  719.  
  720. /*ARGSUSED*/
  721. static void 
  722. Cancel(widget, event, params, num_params)
  723. Widget widget;        
  724. XEvent *event;        
  725. String *params;    
  726. Cardinal *num_params;
  727. {
  728.     Widget dialog = XtParent(widget);
  729.  
  730.     DestroyPopupPrompt(widget, (XtPointer) dialog, (XtPointer) NULL);
  731. }
  732.