home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume1 / torch / part01 / alert.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-28  |  18.7 KB  |  720 lines

  1. /*
  2. Copyright 1988 Torch Computers Ltd.
  3.  
  4. Permission to use, copy, modify, and otherwise generally do what you like
  5. with this software is hereby granted provided that the above copyright notice
  6. appears in all copies.
  7.  
  8. Torch disclaims all warranties implied or expressed with regard to this
  9. software.  In no event shall Torch be liable for any damages arising from
  10. this use of software.
  11. */
  12.  
  13. /********************************************************
  14. *                            *
  15. *  Title   Yorn, Gs and Alert                *
  16. *                            *
  17. *  File       : alert.c                    *
  18. *  Author  : Gary Henderson                *
  19. *            Mark Howells                               *
  20. *  Date       : 27th Sep 1988.                *
  21. *  Purpose : Create and display the widgets for the     *
  22. *            yorn and alert boxes.                      *
  23. *                            *
  24. *********************************************************/
  25.  
  26. /*------Include files-----------------------------------*/
  27.  
  28. #include <stdio.h>
  29. #include <X11/Xlib.h>
  30. #include <X11/Xos.h>
  31. #include <X11/Xutil.h>
  32. #include <X11/StringDefs.h>
  33. #include <X11/Intrinsic.h>
  34. #include <X11/Form.h>
  35. #include <X11/Core.h>
  36. #include <X11/Shell.h>
  37. #include <X11/Label.h>
  38. #include <X11/Command.h>
  39.  
  40. #include "alert.bitmaps"
  41.  
  42. /*------Forward delarations-----------------------------*/
  43.  
  44. static void Nack();
  45. static void OkAck();
  46. static void AlertExposures();
  47. static void AlertText();
  48. static Pixmap LoadSymbol ();
  49. extern long time ();
  50.  
  51. typedef struct {
  52.     unsigned int    width, height;
  53.     Pixmap          id;
  54.     Pixel           foreground, background;
  55. } symbol;
  56.  
  57. /*------Constants and macros----------------------------*/
  58.  
  59. #define ALBOX1X        150
  60. #define ALBOX2X        250
  61.  
  62. #define CROSS    1
  63. #define CHECK    0
  64. #define NOREPLY 100
  65.  
  66. #ifndef MIN
  67. #define MIN(a,b) ((a) > (b) ? (b) : (a))
  68. #endif MIN
  69.  
  70. #define ALTEXTWIDTH MIN ((sysfont->max_bounds.width * 40), \
  71.                           root_width / 5)
  72.  
  73. #define ALTEXTHEIGHT     ((sysfont->max_bounds.descent + \
  74.                           sysfont->max_bounds.ascent) * 6)
  75.  
  76. #define ALONX             ((root_width / 5 + rand () % 48))
  77.  
  78. #define ALONY             ((root_height / 5 + rand () % 48))
  79.  
  80. /*------Exported variables/functions--------------------*/
  81.  
  82. int ackreply = CROSS;
  83. Widget alertwidget;
  84.  
  85. /*------Imported variables/functions--------------------*/
  86.  
  87. extern Widget a_widget;
  88. extern XFontStruct *sysfont;
  89. extern unsigned int root_width, root_height;
  90. extern Display * display;
  91. extern Window root_window;
  92. extern int screen_number;
  93. extern Screen * screen;
  94. extern Boolean zoom;
  95. extern char *yornsym_name, *alertsym_name, *oksym_name, *ticksym_name,
  96.             *crosssym_name;
  97. extern Cursor arrow_cursor;
  98.  
  99. extern void ReadWidgetColours ();
  100.  
  101. /*------Static variables--------------------------------*/
  102.  
  103. static char *curtext;
  104. static Widget triangle, button1, button2, textwidget;
  105. static GC alert_gc, text_gc;
  106. static symbol warn, query, tick, cross, ok;
  107. static symbol *triangle_symbol, *button1_symbol, *button2_symbol;
  108.  
  109. /*
  110.                             *****************
  111.                             *        *
  112.                             *   INITALERT    *
  113.                             *        *
  114.                             *****************
  115. -------------------------------------------------------------------------
  116. | Initialise the widgets for the yorn and alert boxes.                    |
  117. -------------------------------------------------------------------------
  118. */
  119. void InitAlert (geometry)
  120. char * geometry;
  121. {
  122.     Widget formwidget;
  123.     Arg args[10];
  124.     
  125.     static XtCallbackRec ackbacks[] = {
  126.         {OkAck, NULL},
  127.         {NULL, NULL},
  128.     };
  129.     
  130.     static XtCallbackRec nackbacks[] = {
  131.     {Nack, NULL},
  132.     {NULL, NULL},
  133.     };
  134.     Pixel foreground, background;
  135.  
  136. #ifdef BSD    
  137.     (void) srand ((int) time ((long *) 0));
  138. #endif BSD
  139.  
  140. #if defined(UNISOFTV) || defined(SYSV)
  141.     (void) srand ((unsigned int) time ((long *) 0));
  142. #endif /* UNISOFTV || SYSV */
  143.  
  144.     alert_gc = XCreateGC (display, root_window, 0L, (XGCValues *) 0);
  145.     text_gc = XCreateGC (display, root_window, 0L, (XGCValues *) 0);
  146.     
  147.     XSetGraphicsExposures (display, alert_gc, False);
  148.     XSetFillStyle (display, alert_gc, FillStippled);
  149.  
  150.     XSetGraphicsExposures (display, text_gc, False);
  151.  
  152.     XtSetArg (args[0], XtNx, ALONX);
  153.     XtSetArg (args[1], XtNy, ALONY);
  154.     XtSetArg (args[2], XtNgeometry, geometry);
  155.     
  156.     /* An alert (or yorn) box is a popup widget, its exact type depends
  157.        on the zoom resource option */
  158.  
  159.     alertwidget = XtCreatePopupShell ("alert/yorn", 
  160.                                       zoom ? topLevelShellWidgetClass :
  161.                              overrideShellWidgetClass, 
  162.                       a_widget,
  163.                       args,
  164.                       geometry ? 3 : 2);
  165.                     
  166.     formwidget= XtCreateManagedWidget ("contents",
  167.                                       formWidgetClass,
  168.                       alertwidget,
  169.                       (ArgList) 0,
  170.                       0);
  171.  
  172.    /* Now a label widget for the /\   or    /\ 
  173.                                 /  \       /  \
  174.                    / ?  \     / !  \
  175.                    ------     ------ 
  176.       (a label widget has foreground colour that is used for the symbol's
  177.       other colour) */
  178.  
  179.     XtSetArg (args[0], XtNhorizDistance, 10);
  180.     XtSetArg (args[1], XtNvertDistance, 10);
  181.     XtSetArg (args[2], XtNresizable, False);
  182.     XtSetArg (args[3], XtNborderWidth, 0);
  183.     XtSetArg (args[4], XtNlabel, "\0");
  184.     
  185.     triangle = XtCreateManagedWidget ("symbol", labelWidgetClass, 
  186.                                         formwidget, args, 5);
  187.  
  188.     query.width = queryform_width;
  189.     query.height = queryform_height;
  190.     
  191.     query.id = LoadSymbol (triangle, 
  192.                            queryform_bits, 
  193.                yornsym_name, 
  194.                &query.width,
  195.                &query.height,
  196.                &query.foreground,
  197.                &query.background);
  198.  
  199.     warn.width = warnform_width;
  200.     warn.height = warnform_height;
  201.     
  202.     warn.id  = LoadSymbol (triangle,
  203.                            warnform_bits, 
  204.                alertsym_name,
  205.                &warn.width,
  206.                &warn.height,
  207.                &warn.foreground,
  208.                &warn.background);
  209.  
  210.     XtSetArg (args[0], XtNwidth, warn.width > query.width ? 
  211.                                 warn.width : query.width);
  212.     XtSetArg (args[1], XtNheight, warn.height > query.height ? 
  213.                                  warn.height : query.height);
  214.  
  215.     XtSetValues (triangle, args, 2);
  216.     
  217.     XtAddEventHandler (triangle, 
  218.                       StructureNotifyMask | ExposureMask,
  219.               True,
  220.               AlertExposures,
  221.               (caddr_t) 0);
  222.  
  223.     /* Now a widget for the text.  Use a label widget (because it has a
  224.        foreground colour) and format the text ourselves. */
  225.  
  226.     XtSetArg (args[0], XtNborderWidth, 0);
  227.     XtSetArg (args[1], XtNwidth, ALTEXTWIDTH);
  228.     XtSetArg (args[2], XtNheight, ALTEXTHEIGHT);
  229.     XtSetArg (args[3], XtNresizable, True);
  230.     XtSetArg (args[4], XtNhorizDistance, 5);
  231.     XtSetArg (args[5], XtNvertDistance, 1);
  232.     XtSetArg (args[6], XtNfromHoriz, triangle);
  233.     XtSetArg (args[7], XtNlabel, "\0");
  234.     
  235.     textwidget= XtCreateManagedWidget ("text", labelWidgetClass, 
  236.                                         formwidget, args, 8);
  237.  
  238.     ReadWidgetColours (textwidget, &foreground, &background);
  239.  
  240.     XSetForeground (display, text_gc, foreground);
  241.     XSetBackground (display, text_gc, background);
  242.     XSetFont (display, text_gc, sysfont->fid);
  243.     
  244.     XtAddEventHandler (textwidget, 
  245.                       StructureNotifyMask | ExposureMask,
  246.               True,
  247.               AlertText,
  248.               (caddr_t) &curtext);
  249.  
  250.     /* And finally (Esther) two command buttons */
  251.  
  252.     XtSetArg (args[0], XtNhorizDistance, ALBOX1X);
  253.     XtSetArg (args[1], XtNvertDistance, 1);
  254.     XtSetArg (args[2], XtNresizable, True);
  255.     XtSetArg (args[3], XtNfromVert, textwidget);
  256.     XtSetArg (args[4], XtNcallback, ackbacks);
  257.     XtSetArg (args[5], XtNlabel, "\0");
  258.    
  259.     button1 = XtCreateManagedWidget("ok/yes button",
  260.                                     commandWidgetClass,
  261.                     formwidget,
  262.                     args,
  263.                     6);
  264.                  
  265.     ok.width = okform_width;
  266.     ok.height = okform_height;
  267.     
  268.     ok.id = LoadSymbol (button1, 
  269.                         okform_bits, 
  270.                 oksym_name, 
  271.                 &ok.width, 
  272.                 &ok.height,
  273.                 &ok.foreground,
  274.                 &ok.background);
  275.              
  276.     tick.width = tickform_width;
  277.     tick.height = tickform_height;
  278.     
  279.     tick.id = LoadSymbol (button1, 
  280.                           tickform_bits, 
  281.               ticksym_name, 
  282.               &tick.width,
  283.               &tick.height,
  284.               &tick.foreground,
  285.               &tick.background);
  286.  
  287.     XtSetArg (args[0], XtNwidth, ok.width > tick.width ? 
  288.                                  ok.width : tick.width);
  289.     XtSetArg (args[1], XtNheight, ok.height > tick.height ? 
  290.                                   ok.height : tick.height);
  291.  
  292.     XtSetValues (button1, args, 2);
  293.     
  294.     XtAddEventHandler (button1, 
  295.                       StructureNotifyMask | LeaveWindowMask | ExposureMask,
  296.               True,
  297.               AlertExposures,
  298.               (caddr_t) 1);
  299.  
  300.     XtSetArg (args[0], XtNhorizDistance, ALBOX2X);
  301.     XtSetArg (args[1], XtNvertDistance, 1);
  302.     XtSetArg (args[2], XtNresizable, True);
  303.     XtSetArg (args[3], XtNfromVert, textwidget);
  304.     XtSetArg (args[4], XtNcallback, nackbacks);
  305.     XtSetArg (args[5], XtNlabel, "\0");
  306.    
  307.     button2 = XtCreateManagedWidget("no button",
  308.                                     commandWidgetClass,
  309.                     formwidget,
  310.                     args,
  311.                     6);
  312.     
  313.     cross.height = crossform_height;
  314.     cross.width = crossform_width;
  315.     
  316.     cross.id = LoadSymbol (button2,
  317.                            crossform_bits,
  318.                crosssym_name,
  319.                &cross.width,
  320.                &cross.height,
  321.                &cross.foreground,
  322.                &cross.background);
  323.     
  324.     XtSetArg (args[0], XtNwidth, cross.width);
  325.     XtSetArg (args[1], XtNheight, cross.height);
  326.  
  327.     XtSetValues (button2, args, 2);
  328.     
  329.     XtAddEventHandler (button2,
  330.                       StructureNotifyMask | LeaveWindowMask | ExposureMask,
  331.               True,
  332.               AlertExposures,
  333.               (caddr_t) 2);
  334.  
  335.     XtRealizeWidget (alertwidget);
  336. }
  337. /*
  338.                             *****************
  339.                             *        *
  340.                             *     OKACK    *
  341.                             *     NACK    *
  342.                             *****************
  343. -------------------------------------------------------------------------
  344. | One of the buttons has been pressed by the user.                      |
  345. -------------------------------------------------------------------------
  346. */
  347.  
  348. /*ARGSUSED*/
  349. static void OkAck (widget, client_data, call_data)
  350. Widget widget;
  351. caddr_t client_data,call_data;
  352. {
  353.     ackreply = CHECK;
  354.     XtPopdown (alertwidget);
  355. }
  356.  
  357. /*ARGSUSED*/
  358. static void Nack (widget, client_data, call_data)
  359. Widget widget;
  360. caddr_t client_data,call_data;
  361. {
  362.     ackreply = CROSS;
  363.     XtPopdown (alertwidget);
  364. }
  365.  
  366. /*
  367.                             *****************
  368.                             *        *
  369.                             *    ALERT    *
  370.                             *        *
  371.                             *****************
  372. -------------------------------------------------------------------------
  373. | Popup an alert box and wait for the user to click the acknowlegde     |
  374. | button.                                                               |
  375. -------------------------------------------------------------------------
  376. */
  377. void Alert (text)
  378. char *text;
  379. {
  380.     XEvent xevent;
  381.     
  382.     ackreply = NOREPLY;
  383.     DrawAlert (&warn, &ok, (symbol *) 0, text);
  384.     
  385.     while (ackreply == NOREPLY)
  386.     {
  387.         XtNextEvent (&xevent);
  388.     XtDispatchEvent (&xevent);
  389.     }
  390.  
  391.     exit (0);
  392. }
  393.  
  394. /*
  395.                             *****************
  396.                             *        *
  397.                             *     YORN    *
  398.                             *        *
  399.                             *****************
  400. -------------------------------------------------------------------------
  401. | Popup a yorn box and wait for the user to click in the tick or cross    |
  402. | button and return the answer to the calling program.                    |
  403. -------------------------------------------------------------------------
  404. */
  405.  
  406. void Yorn (text)
  407. char *text;
  408. {
  409.     XEvent xevent;
  410.  
  411.     ackreply = NOREPLY;
  412.     DrawAlert (&query, &tick, &cross, text);
  413.  
  414.     while (ackreply == NOREPLY)
  415.     {
  416.         XtNextEvent (&xevent);
  417.     XtDispatchEvent (&xevent);
  418.     }
  419.  
  420.     exit (ackreply);
  421. }
  422.  
  423. /*
  424.                             *****************
  425.                             *        *
  426.                             *   DRAWALERT    *
  427.                             *        *
  428.                             *****************
  429. -------------------------------------------------------------------------
  430. | Note what symbols to use and how many buttons to show, then actually    |
  431. | popup the widget.                                                     |
  432. -------------------------------------------------------------------------
  433. */
  434. DrawAlert (tri_symbol, first_button, second_button, text)
  435. symbol *tri_symbol, *first_button, *second_button;
  436. char *text;
  437. {
  438.     if (second_button)
  439.            XtMapWidget (button2);
  440.     else
  441.            XtUnmapWidget (button2);
  442.  
  443.     triangle_symbol = tri_symbol;
  444.     button1_symbol = first_button;
  445.     button2_symbol = second_button;
  446.     curtext = text;
  447.  
  448.     XtPopup (alertwidget, XtGrabNone);
  449.     
  450.     XDefineCursor (display, XtWindow (alertwidget), arrow_cursor);
  451.  
  452.     XFlush (display);
  453. }
  454.  
  455. /*
  456.                             *****************
  457.                             *        *
  458.                             * ALERTEXPOSURES*
  459.                             *        *
  460.                             *****************
  461. -------------------------------------------------------------------------
  462. | Exposure and reconfigure event processing for widgets containing      |
  463. | symbols.  Redraws the symbols when necessary.                            |
  464. -------------------------------------------------------------------------
  465. */
  466. static void AlertExposures (widget, which1, event)
  467. Widget widget;
  468. caddr_t which1;
  469. XEvent *event;
  470. {
  471.     XRectangle rect;
  472.     Arg args[2];
  473.     int width;
  474.     int height;
  475.     symbol *sym;
  476.     
  477.     if (!XtIsRealized (widget))
  478.     return;
  479.  
  480.     XtSetArg (args[0], XtNwidth, &width);
  481.     XtSetArg (args[1], XtNheight, &height);
  482.  
  483.     XtGetValues (widget, args, 2);
  484.  
  485.     switch (event->type)
  486.     {
  487.     case  Expose:    rect.x = event->xexpose.x;
  488.             rect.y = event->xexpose.y;
  489.             rect.width = event->xexpose.width;
  490.             rect.height = event->xexpose.height;
  491.             break;
  492.     
  493.     case  GraphicsExpose:    
  494.                     rect.x = event->xgraphicsexpose.x;
  495.             rect.y = event->xgraphicsexpose.y;
  496.             rect.width = event->xgraphicsexpose.width;
  497.             rect.height = event->xgraphicsexpose.height;
  498.             break;
  499.     
  500.     case  ConfigureNotify: 
  501.                     XClearWindow (display, XtWindow (widget));
  502.             
  503.             /* Deliberate fall through ... */
  504.     
  505.     case  LeaveNotify:   
  506.                     rect.x = 0;
  507.             rect.y = 0;
  508.             rect.width = width;
  509.             rect.height = height;
  510.             break;
  511.         default: 
  512.                     return;
  513.     }
  514.     
  515.     XSetClipRectangles (display, alert_gc, 0, 0, &rect, 1, Unsorted);
  516.  
  517.     switch ((int) which1)
  518.     {
  519.         case 0:            sym = triangle_symbol;
  520.                     break;
  521.  
  522.         case 1:            sym = button1_symbol;
  523.                     break;
  524.  
  525.         case 2:            sym = button2_symbol;
  526.                     break;
  527.  
  528.     default:        return;
  529.     }
  530.  
  531.     if (sym == (symbol *) 0)
  532.         return;
  533.     
  534.     XSetForeground (display, alert_gc, sym->foreground);
  535.     XSetBackground (display, alert_gc, sym->background);
  536.     XSetStipple (display, alert_gc, sym->id);
  537.     XSetTSOrigin (display, 
  538.                   alert_gc, 
  539.           (width - (int) sym->width) / 2,
  540.           (height - (int) sym->height) / 2);
  541.                     
  542.     XFillRectangle (display,
  543.                     XtWindow (widget),
  544.             alert_gc,
  545.             (width - (int) sym->width) / 2,
  546.             (height - (int) sym->height) / 2,
  547.             sym->width,
  548.             sym->height);
  549. }
  550.  
  551. /*
  552.                             *****************
  553.                             *        *
  554.                             *   ALERTTEXT    *
  555.                             *        *
  556.                             *****************
  557. -------------------------------------------------------------------------
  558. | Draw the alert or yorn text in the text widget.  Format (word wrap)    |
  559. | the text to best fit the curent widget size.                            | 
  560. -------------------------------------------------------------------------
  561. */
  562. static void AlertText (widget, str, event)
  563. Widget widget;
  564. caddr_t str;
  565. XEvent *event;
  566. {
  567.     register char *text = *(char **) str;
  568.     register pos, ppos, slen, textx, texty;
  569.     int text_width;
  570.     
  571.     XRectangle rect;
  572.     Arg args[2];
  573.     int width, height;
  574.  
  575.     XtSetArg (args[0], XtNwidth, &width);
  576.     XtSetArg (args[1], XtNheight, &height);
  577.     XtGetValues (widget, args, 2);
  578.  
  579.     pos   = 0;            /* position of next 'space' in string */
  580.     ppos  = 0;            /* previous of a 'space' in string */
  581.     slen  = strlen (text);    /* length of string   */
  582.     textx = 10;                /* Current x position, (indent 1st line) */
  583.     texty = 10;                /* Current y position */
  584.  
  585.     /* Work out clip rectangle */
  586.  
  587.     switch (event->type) 
  588.     {
  589.         case Expose:    rect.x = event->xexpose.x;
  590.                 rect.y = event->xexpose.y;
  591.                 rect.width = event->xexpose.width;
  592.                 rect.height = event->xexpose.height;
  593.                 break;
  594.  
  595.         case GraphicsExpose:
  596.                     rect.x = event->xgraphicsexpose.x;
  597.                 rect.y = event->xgraphicsexpose.y;
  598.                 rect.width = event->xgraphicsexpose.width;
  599.                 rect.height = event->xgraphicsexpose.height;
  600.                 break;
  601.  
  602.         case ConfigureNotify:
  603.                         XClearWindow (display, XtWindow(widget));
  604.                     rect.x = 0;
  605.                 rect.y = 0;
  606.                 rect.width = width;
  607.                 rect.height = height;
  608.                 break;
  609.  
  610.         default:        return;
  611.     }
  612.  
  613.     XSetClipRectangles (display, text_gc, 0, 0, &rect, 1, Unsorted);
  614.     
  615.     while (pos < slen)
  616.     {
  617.         /* Wrap lines at spaces if possible */
  618.  
  619.           while (pos < slen)
  620.             if (*(text + pos++) == ' ')
  621.                 break;
  622.  
  623.           text_width = XTextWidth (sysfont, text + ppos,pos - ppos);
  624.  
  625.         /* If this would run over end when printed, wrap!! */
  626.  
  627.           if (textx + text_width >= width)
  628.           {
  629.             texty += sysfont->ascent + sysfont->descent;
  630.             textx = 10;
  631.           }
  632.  
  633.         /* print sub-string */
  634.  
  635.         /* If this would still run over end when printed, draw a char at a time */
  636.  
  637.           if (textx + text_width >= width)
  638.           {
  639.             while ((textx + XTextWidth(sysfont,text + ppos,1) <= width) && 
  640.                 ppos <= pos)
  641.             {
  642.                 XDrawString (display,
  643.                              XtWindow (widget),
  644.                              text_gc,
  645.                              textx,
  646.                      texty + sysfont->ascent,
  647.                              text + ppos,
  648.                              1);
  649.                 
  650.         textx += XTextWidth (sysfont,text + ppos,1);
  651.                 ppos ++;
  652.             }
  653.           }
  654.           else
  655.         {
  656.             XDrawString (display,
  657.                  XtWindow (widget),
  658.                  text_gc,
  659.                  textx,
  660.                  texty + sysfont->ascent,
  661.                  text + ppos,
  662.                  pos - ppos);
  663.  
  664.             textx += text_width;
  665.  
  666.             /* Update ppos */
  667.  
  668.             ppos = pos;
  669.     }
  670.     }
  671. }
  672.  
  673. /*
  674.                             *****************
  675.                             *        *
  676.                             *   LOADSYMBOL    *
  677.                             *        *
  678.                             *****************
  679. -------------------------------------------------------------------------
  680. | Download a bitmap to the server to use as one of the symbols for the    |
  681. | yorn or alert boxes.                                                    |
  682. | Returns the pixmap XID, two colours (the pixel values) to use when    |
  683. | drawing the symbol and modifies the width and height values if a      |
  684. | different bitmap (from a file) has been used.                            |
  685. -------------------------------------------------------------------------
  686. */
  687. static Pixmap LoadSymbol (widget, bits, name, width, height, fore, back)
  688. Widget widget;
  689. char *bits, *name;
  690. unsigned int *width, *height;
  691. Pixel *fore, *back;
  692. {
  693.     Pixmap pixmap;
  694.     unsigned int wid, hei;
  695.     
  696.     ReadWidgetColours (widget, fore, back);
  697.     
  698.     /* If a name of an alternative bitmap file has been supplied, try to
  699.        read it.  If that fails for any reason, or no name is given, download
  700.        the default bitmap */
  701.        
  702.     if (name)
  703.         if (XReadBitmapFile (display, 
  704.                          root_window,
  705.                   name,
  706.                  &wid,
  707.                  &hei,
  708.                  &pixmap,
  709.                  (int *) 0, 
  710.                  (int *) 0) == BitmapSuccess)
  711.         {
  712.         *width = wid;
  713.         *height = hei;
  714.  
  715.         return pixmap;
  716.     }
  717.  
  718.     return XCreateBitmapFromData (display, root_window, bits, *width, *height);
  719. }
  720.