home *** CD-ROM | disk | FTP | other *** search
/ PC Shareware 1999 March / PCShareware-3-99.iso / IMPLE / DJGPP.RAR / DJGPP2 / XLIB-SR0.ZIP / SRC / EXTENSIO / XMULTIBU.C < prev    next >
C/C++ Source or Header  |  1994-09-03  |  22KB  |  698 lines

  1. /*
  2.  * $XConsortium: XMultibuf.c,v 1.26 91/05/04 19:32:35 rws Exp $
  3.  *
  4.  * Copyright 1989 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising or
  11.  * publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  *
  23.  * Authors:  Jim Fulton, MIT X Consortium
  24.  */
  25.  
  26. #define NEED_EVENTS
  27. #define NEED_REPLIES
  28. #include <X11/Xlibint.h>
  29. #include "Xext.h"            /* in ../include */
  30. #include "extutil.h"            /* in ../include */
  31. #include "multibst.h"            /* in ../include */
  32.  
  33. static XExtensionInfo _multibuf_info_data;
  34. static XExtensionInfo *multibuf_info = &_multibuf_info_data;
  35. static /* const */ char *multibuf_extension_name = MULTIBUFFER_PROTOCOL_NAME;
  36.  
  37. #define MbufCheckExtension(dpy,i,val) \
  38.   XextCheckExtension (dpy, i, multibuf_extension_name, val)
  39. #define MbufSimpleCheckExtension(dpy,i) \
  40.   XextSimpleCheckExtension (dpy, i, multibuf_extension_name)
  41.  
  42.  
  43. /*****************************************************************************
  44.  *                                                                           *
  45.  *               private utility routines                          *
  46.  *                                                                           *
  47.  *****************************************************************************/
  48.  
  49. /*
  50.  * find_display - locate the display info block
  51.  */
  52. static int close_display();
  53. static char *error_string();
  54. static Bool wire_to_event();
  55. static Status event_to_wire();
  56. static /* const */ XExtensionHooks multibuf_extension_hooks = {
  57.     NULL,                /* create_gc */
  58.     NULL,                /* copy_gc */
  59.     NULL,                /* flush_gc */
  60.     NULL,                /* free_gc */
  61.     NULL,                /* create_font */
  62.     NULL,                /* free_font */
  63.     close_display,            /* close_display */
  64.     wire_to_event,            /* wire_to_event */
  65.     event_to_wire,            /* event_to_wire */
  66.     NULL,                /* error */
  67.     error_string,            /* error_string */
  68. };
  69.  
  70. static /* const */ char *multibuf_error_list[] = {
  71.     "BadBuffer",            /* MultibufferBadBuffer */
  72. };
  73.  
  74. static XEXT_GENERATE_FIND_DISPLAY (find_display, multibuf_info,
  75.                    multibuf_extension_name, 
  76.                    &multibuf_extension_hooks, 
  77.                    MultibufferNumberEvents, NULL)
  78.  
  79. static XEXT_GENERATE_CLOSE_DISPLAY (close_display, multibuf_info)
  80.  
  81. static XEXT_GENERATE_ERROR_STRING (error_string, multibuf_extension_name,
  82.                    MultibufferNumberErrors, 
  83.                    multibuf_error_list)
  84.  
  85. /*
  86.  * wire_to_event - convert a wire event in network format to a C 
  87.  * event structure
  88.  */
  89. static Bool wire_to_event (dpy, libevent, netevent)
  90.     Display *dpy;
  91.     XEvent *libevent;
  92.     xEvent *netevent;
  93. {
  94.     XExtDisplayInfo *info = find_display (dpy);
  95.  
  96.     MbufCheckExtension (dpy, info, False);
  97.  
  98.     switch ((netevent->u.u.type & 0x7f) - info->codes->first_event) {
  99.       case MultibufferClobberNotify:
  100.     {
  101.         XmbufClobberNotifyEvent *ev;
  102.         xMbufClobberNotifyEvent *event;
  103.     
  104.             ev = (XmbufClobberNotifyEvent *) libevent;
  105.         event = (xMbufClobberNotifyEvent *) netevent;
  106.             ev->type = event->type & 0x7f;
  107.             ev->serial = _XSetLastRequestRead(dpy,(xGenericReply *) netevent);
  108.             ev->send_event = ((event->type & 0x80) != 0);
  109.             ev->display = dpy;
  110.             ev->buffer = event->buffer;
  111.             return True;
  112.     }
  113.       case MultibufferUpdateNotify:
  114.     {
  115.         XmbufUpdateNotifyEvent *ev;
  116.         xMbufUpdateNotifyEvent *event;
  117.  
  118.         ev = (XmbufUpdateNotifyEvent *) libevent;
  119.         event = (xMbufUpdateNotifyEvent *) netevent;
  120.         ev->type = event->type & 0x7f;
  121.         ev->serial = _XSetLastRequestRead(dpy,(xGenericReply *) netevent);
  122.         ev->send_event = ((event->type & 0x80) != 0);
  123.         ev->display = dpy;
  124.         ev->buffer = event->buffer;
  125.         return True;
  126.     }
  127.     }
  128.     return False;
  129. }
  130.  
  131.  
  132. /*
  133.  * event_to_wire - convert a C event structure to a wire event in
  134.  * network format
  135.  */
  136. static Status event_to_wire (dpy, libevent, netevent)
  137.     Display *dpy;
  138.     XEvent  *libevent;
  139.     xEvent  *netevent;
  140. {
  141.     XExtDisplayInfo *info = find_display (dpy);
  142.  
  143.     MbufCheckExtension (dpy, info, 0);
  144.  
  145.     switch ((libevent->type & 0x7f) - info->codes->first_event) {
  146.       case MultibufferClobberNotify:
  147.     {
  148.         XmbufClobberNotifyEvent *ev;
  149.         xMbufClobberNotifyEvent *event;
  150.     
  151.             ev = (XmbufClobberNotifyEvent *) libevent;
  152.         event = (xMbufClobberNotifyEvent *) netevent;
  153.             event->type = ev->type;
  154.             event->sequenceNumber = (ev->serial & 0xffff);
  155.             event->buffer = ev->buffer;
  156.             return 1;
  157.     }
  158.       case MultibufferUpdateNotify:
  159.     {
  160.         XmbufUpdateNotifyEvent *ev;
  161.         xMbufUpdateNotifyEvent *event;
  162.  
  163.         ev = (XmbufUpdateNotifyEvent *) libevent;
  164.         event = (xMbufUpdateNotifyEvent *) netevent;
  165.         event->type = ev->type;
  166.         event->sequenceNumber = (ev->serial & 0xffff);
  167.         event->buffer = ev->buffer;
  168.         return 1;
  169.     }
  170.     }
  171.     return 0;
  172. }
  173.  
  174.  
  175. /*
  176.  * read_buffer_info - read Buffer Info descriptors from the net; if unable
  177.  * to allocate memory, read junk to make sure that stream is clear.
  178.  */
  179. #define TALLOC(type,count) ((type *) Xmalloc ((unsigned) count * sizeof(type)))
  180.  
  181. static XmbufBufferInfo *read_buffer_info (dpy, nbufs)
  182.     Display *dpy;
  183.     int nbufs;
  184. {
  185.     xMbufBufferInfo *netbuf = TALLOC (xMbufBufferInfo, nbufs);
  186.     XmbufBufferInfo *bufinfo = NULL;
  187.     long netbytes = nbufs * SIZEOF(xMbufBufferInfo);
  188.  
  189.     if (netbuf) {
  190.     _XRead (dpy, (char *) netbuf, netbytes);
  191.  
  192.     bufinfo = TALLOC (XmbufBufferInfo, nbufs);
  193.     if (bufinfo) {
  194.         register XmbufBufferInfo *c;
  195.         register xMbufBufferInfo *net;
  196.         register int i;
  197.  
  198.         for (i = 0, c = bufinfo, net = netbuf; i < nbufs;
  199.          i++, c++, net++) {
  200.         c->visualid = net->visualID;
  201.         c->max_buffers = net->maxBuffers;
  202.         c->depth = net->depth;
  203.         }
  204.     }
  205.     Xfree ((char *) netbuf);
  206.     } else {                /* eat the data */
  207.     while (netbytes > 0) {
  208.         char dummy[256];        /* stack size vs loops tradeoff */
  209.         long nbytes = sizeof dummy;
  210.  
  211.         if (nbytes > netbytes) nbytes = netbytes;
  212.         _XRead (dpy, dummy, nbytes);
  213.         netbytes -= nbytes;
  214.     }
  215.     }
  216.  
  217.     return bufinfo;
  218. }
  219.  
  220. #undef TALLOC
  221.  
  222.  
  223. /*****************************************************************************
  224.  *                                                                           *
  225.  *            Multibuffering/stereo public interfaces                  *
  226.  *                                                                           *
  227.  *****************************************************************************/
  228.  
  229.  
  230. /* 
  231.  * XmbufQueryExtension - 
  232.  *     Returns True if the multibuffering/stereo extension is available
  233.  *     on the given display.  If the extension exists, the value of the
  234.  *     first event code (which should be added to the event type constants
  235.  *     MultibufferClobberNotify and MultibufferUpdateNotify to get the
  236.  *     actual values) is stored into event_base and the value of the first
  237.  *     error code (which should be added to the error type constant
  238.  *     MultibufferBadBuffer to get the actual value) is stored into 
  239.  *     error_base.
  240.  */
  241. Bool XmbufQueryExtension (dpy, event_base_return, error_base_return)
  242.     Display *dpy;
  243.     int *event_base_return, *error_base_return;
  244. {
  245.     XExtDisplayInfo *info = find_display (dpy);
  246.     
  247.     if (XextHasExtension (info)) {
  248.     *event_base_return = info->codes->first_event;
  249.     *error_base_return = info->codes->first_error;
  250.     return True;
  251.     } else {
  252.     return False;
  253.     }
  254. }
  255.  
  256.  
  257. /* 
  258.  * XmbufGetVersion -
  259.  *     Gets the major and minor version numbers of the extension.  The return
  260.  *     value is zero if an error occurs or non-zero if no error happens.
  261.  */
  262. Status XmbufGetVersion (dpy, major_version_return, minor_version_return)
  263.     Display *dpy;
  264.     int *major_version_return, *minor_version_return;
  265. {
  266.     XExtDisplayInfo *info = find_display (dpy);
  267.     xMbufGetBufferVersionReply rep;
  268.     register xMbufGetBufferVersionReq *req;
  269.  
  270.     MbufCheckExtension (dpy, info, 0);
  271.  
  272.     LockDisplay (dpy);
  273.     MbufGetReq (MbufGetBufferVersion, req, info);
  274.     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
  275.     UnlockDisplay (dpy);
  276.     SyncHandle ();
  277.     return 0;
  278.     }
  279.     *major_version_return = rep.majorVersion;
  280.     *minor_version_return = rep.minorVersion;
  281.     UnlockDisplay (dpy);
  282.  
  283.     SyncHandle ();
  284.     return 1;
  285. }
  286.  
  287.  
  288. /*
  289.  * XmbufCreateBuffers - 
  290.  *     Requests that "count" buffers be created with the given update_action
  291.  *     and update_hint and be associated with the indicated window.  The
  292.  *     number of buffers created is returned (zero if an error occurred)
  293.  *     and buffers_return is filled in with that many Multibuffer identifiers.
  294.  */
  295. int XmbufCreateBuffers (dpy, w, count, update_action, update_hint, buffers)
  296.     Display *dpy;
  297.     Window w;
  298.     int count;
  299.     int update_action, update_hint;
  300.     Multibuffer *buffers;
  301. {
  302.     XExtDisplayInfo *info = find_display (dpy);
  303.     xMbufCreateImageBuffersReply rep;
  304.     register xMbufCreateImageBuffersReq *req;
  305.     int i, result;
  306.  
  307.     MbufCheckExtension (dpy, info, 0);
  308.  
  309.     /*
  310.      * allocate the id; hopefully, it would be nice to be able to 
  311.      * get rid of the ones we don't need, but this would require access
  312.      * various Xlib internals.  we could do caching on this side, but the
  313.      * chances of wasting enough resources to really matter is very small
  314.      */
  315.     for (i = 0; i < count; i++) buffers[i] = XAllocID (dpy);
  316.  
  317.     LockDisplay (dpy);
  318.     MbufGetReq (MbufCreateImageBuffers, req, info);
  319.     req->window = w;
  320.     req->updateAction = update_action;
  321.     req->updateHint = update_hint;
  322.     req->length += count;
  323.     PackData32 (dpy, buffers, count * sizeof (Multibuffer));
  324.     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
  325.     UnlockDisplay (dpy);
  326.     SyncHandle ();
  327.     return 0;
  328.     }
  329.     result = rep.numberBuffer;
  330.     UnlockDisplay (dpy);
  331.  
  332.     SyncHandle ();
  333.     return result;
  334. }
  335.  
  336.  
  337. /*
  338.  * XmbufDestroyBuffers - 
  339.  *     Destroys the buffers associated with the given window.
  340.  */
  341. void XmbufDestroyBuffers (dpy, window)
  342.     Display *dpy;
  343.     Window  window;
  344. {
  345.     XExtDisplayInfo *info = find_display (dpy);
  346.     register xMbufDestroyImageBuffersReq *req;
  347.  
  348.     MbufSimpleCheckExtension (dpy, info);
  349.  
  350.     LockDisplay (dpy);
  351.     MbufGetReq (MbufDestroyImageBuffers, req, info);
  352.     req->window = window;
  353.     UnlockDisplay (dpy);
  354.     SyncHandle ();
  355. }
  356.  
  357.  
  358. /*
  359.  * XmbufDisplayBuffers - 
  360.  *     Displays the indicated buffers their appropriate windows within
  361.  *     max_delay milliseconds after min_delay milliseconds have passed.
  362.  *     No two buffers may be associated with the same window or else a Matc
  363.  *     error is generated.
  364.  */
  365. void XmbufDisplayBuffers (dpy, count, buffers, min_delay, max_delay)
  366.     Display *dpy;
  367.     int count;
  368.     Multibuffer *buffers;
  369.     int min_delay, max_delay;
  370. {
  371.     XExtDisplayInfo *info = find_display (dpy);
  372.     register xMbufDisplayImageBuffersReq *req;
  373.  
  374.     MbufSimpleCheckExtension (dpy, info);
  375.  
  376.     LockDisplay (dpy);
  377.     MbufGetReq (MbufDisplayImageBuffers, req, info);
  378.     req->minDelay = min_delay;
  379.     req->maxDelay = max_delay;
  380.     req->length += count;
  381.     PackData32 (dpy, buffers, count * sizeof (Multibuffer));
  382.     UnlockDisplay (dpy);
  383.     SyncHandle();
  384. }
  385.  
  386.  
  387. /*
  388.  * XmbufGetWindowAttributes - 
  389.  *     Gets the multibuffering attributes that apply to all buffers associated
  390.  *     with the given window.  Returns non-zero on success and zero if an
  391.  *     error occurs.
  392.  */
  393. Status XmbufGetWindowAttributes (dpy, w, attr)
  394.     Display *dpy;
  395.     Window w;
  396.     XmbufWindowAttributes *attr;
  397. {
  398.     XExtDisplayInfo *info = find_display (dpy);
  399.     register xMbufGetMBufferAttributesReq *req;
  400.     xMbufGetMBufferAttributesReply rep;
  401.  
  402.     MbufCheckExtension (dpy, info, 0);
  403.  
  404.     LockDisplay (dpy);
  405.     MbufGetReq (MbufGetMBufferAttributes, req, info);
  406.     req->window = w;
  407.     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
  408.     UnlockDisplay (dpy);
  409.     SyncHandle ();
  410.     return 0;
  411.     }
  412.     attr->buffers = (Multibuffer *) NULL; 
  413.     if (attr->nbuffers = rep.length) {
  414.     int nbytes = rep.length * sizeof(Multibuffer);
  415.     attr->buffers = (Multibuffer *) Xmalloc((unsigned) nbytes);
  416.     nbytes = rep.length << 2;
  417.     if (! attr->buffers) {
  418.         _XEatData(dpy, (unsigned long) nbytes);
  419.         UnlockDisplay(dpy);
  420.         SyncHandle();
  421.         return (0);
  422.     }
  423.     _XRead32 (dpy, (char *) attr->buffers, nbytes);
  424.     }
  425.     attr->displayed_index = rep.displayedBuffer;
  426.     attr->update_action = rep.updateAction;
  427.     attr->update_hint = rep.updateHint;
  428.     attr->window_mode = rep.windowMode;
  429.  
  430.     UnlockDisplay (dpy);
  431.     SyncHandle();
  432.     return 1;
  433. }
  434.  
  435.  
  436. /*
  437.  * XmbufChangeWindowAttributes - 
  438.  *     Sets the multibuffering attributes that apply to all buffers associated
  439.  *     with the given window.  This is currently limited to the update_hint.
  440.  */
  441. void XmbufChangeWindowAttributes (dpy, w, valuemask, attr)
  442.     Display *dpy;
  443.     Window w;
  444.     unsigned long valuemask;
  445.     XmbufSetWindowAttributes *attr;
  446. {
  447.     XExtDisplayInfo *info = find_display (dpy);
  448.     register xMbufSetMBufferAttributesReq *req;
  449.  
  450.     MbufSimpleCheckExtension (dpy, info);
  451.  
  452.     LockDisplay (dpy);
  453.     MbufGetReq (MbufSetMBufferAttributes, req, info);
  454.     req->window = w;
  455.     if (req->valueMask = valuemask) {    /* stolen from lib/X/XWindow.c */
  456.     unsigned long values[1];    /* one per element in if stmts below */
  457.     unsigned long *v = values;
  458.     unsigned int nvalues;
  459.  
  460.     if (valuemask & MultibufferWindowUpdateHint) 
  461.       *v++ = attr->update_hint;
  462.     req->length += (nvalues = v - values);
  463.     nvalues <<= 2;            /* watch out for macros... */
  464.     Data32 (dpy, (long *) values, (long)nvalues);
  465.     }
  466.     UnlockDisplay (dpy);
  467.     SyncHandle();
  468. }
  469.  
  470.  
  471. /*
  472.  * XmbufGetBufferAttributes - 
  473.  *     Gets the attributes for the indicated buffer.  Returns non-zero on
  474.  *     success and zero if an error occurs.
  475.  */
  476. Status XmbufGetBufferAttributes (dpy, b, attr)
  477.     Display *dpy;
  478.     Multibuffer b;
  479.     XmbufBufferAttributes *attr;
  480. {
  481.     XExtDisplayInfo *info = find_display (dpy);
  482.     register xMbufGetBufferAttributesReq *req;
  483.     xMbufGetBufferAttributesReply rep;
  484.  
  485.     MbufCheckExtension (dpy, info, 0);
  486.  
  487.     LockDisplay (dpy);
  488.     MbufGetReq (MbufGetBufferAttributes, req, info);
  489.     req->buffer = b;
  490.     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
  491.     UnlockDisplay (dpy);
  492.     SyncHandle ();
  493.     return 0;
  494.     }
  495.     attr->window = rep.window;
  496.     attr->event_mask = rep.eventMask;
  497.     attr->buffer_index = rep.bufferIndex;
  498.     attr->side = rep.side;
  499.  
  500.     UnlockDisplay (dpy);
  501.     SyncHandle();
  502.     return 1;
  503. }
  504.  
  505.  
  506. /*
  507.  * XmbufChangeBufferAttributes - 
  508.  *     Sets the attributes for the indicated buffer.  This is currently
  509.  *     limited to the event_mask.
  510.  */
  511. void XmbufChangeBufferAttributes (dpy, b, valuemask, attr)
  512.     Display *dpy;
  513.     Multibuffer b;
  514.     unsigned long valuemask;
  515.     XmbufSetBufferAttributes *attr;
  516. {
  517.     XExtDisplayInfo *info = find_display (dpy);
  518.     register xMbufSetBufferAttributesReq *req;
  519.  
  520.     MbufSimpleCheckExtension (dpy, info);
  521.  
  522.     LockDisplay (dpy);
  523.     MbufGetReq (MbufSetBufferAttributes, req, info);
  524.     req->buffer = b;
  525.     if (req->valueMask = valuemask) {    /* stolen from lib/X/XWindow.c */
  526.     unsigned long values[1];    /* one per element in if stmts below */
  527.     unsigned long *v = values;
  528.     unsigned int nvalues;
  529.  
  530.     if (valuemask & MultibufferBufferEventMask)
  531.       *v++ = attr->event_mask;
  532.     req->length += (nvalues = v - values);
  533.     nvalues <<= 2;            /* watch out for macros... */
  534.     Data32 (dpy, (long *) values, (long)nvalues);
  535.     }
  536.     UnlockDisplay (dpy);
  537.     SyncHandle();
  538. }
  539.  
  540.  
  541.  
  542. /*
  543.  * XmbufGetScreenInfo - 
  544.  *     Gets the parameters controlling how mono and stereo windows may be
  545.  *     created on the indicated screen.  The numbers of sets of visual and 
  546.  *     depths are returned in nmono_return and nstereo_return.  If 
  547.  *     nmono_return is greater than zero, then mono_info_return is set to
  548.  *     the address of an array of XmbufBufferInfo structures describing the
  549.  *     various visuals and depths that may be used.  Otherwise,
  550.  *     mono_info_return is set to NULL.  Similarly, stereo_info_return is
  551.  *     set according to nstereo_return.  The storage returned in 
  552.  *     mono_info_return and stereo_info_return may be released by XFree.
  553.  *     If no errors are encounted, non-zero will be returned.
  554.  */
  555. Status XmbufGetScreenInfo (dpy, d, nmono_return, mono_info_return,
  556.                nstereo_return, stereo_info_return)
  557.     Display *dpy;
  558.     Drawable d;
  559.     int *nmono_return;
  560.     XmbufBufferInfo **mono_info_return;
  561.     int *nstereo_return;
  562.     XmbufBufferInfo **stereo_info_return;
  563. {
  564.     XExtDisplayInfo *info = find_display (dpy);
  565.     register xMbufGetBufferInfoReq *req;
  566.     xMbufGetBufferInfoReply rep;
  567.     int nmono, nstereo;
  568.     XmbufBufferInfo *minfo, *sinfo;
  569.  
  570.     MbufCheckExtension (dpy, info, 0);
  571.  
  572.     LockDisplay (dpy);
  573.     MbufGetReq (MbufGetBufferInfo, req, info);
  574.     req->drawable = d;
  575.     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
  576.     UnlockDisplay (dpy);
  577.     SyncHandle ();
  578.     return 0;
  579.     }
  580.     nmono = rep.normalInfo;
  581.     nstereo = rep.stereoInfo;
  582.     minfo = ((nmono > 0) ? read_buffer_info (dpy, nmono) : NULL);
  583.     sinfo = ((nstereo > 0) ? read_buffer_info (dpy, nstereo) : NULL);
  584.  
  585.     /* check for bad reads indicating we need to return an error */
  586.     if ((nmono > 0 && !minfo) || (nstereo > 0 && !sinfo)) {
  587.     if (minfo) Xfree ((char *) minfo);
  588.     if (sinfo) Xfree ((char *) sinfo);
  589.     UnlockDisplay (dpy);
  590.     SyncHandle();
  591.     return 0;
  592.     }
  593.  
  594.     *nmono_return = nmono;
  595.     *mono_info_return = minfo;
  596.     *nstereo_return = nstereo;
  597.     *stereo_info_return = sinfo;
  598.  
  599.     UnlockDisplay (dpy);
  600.     SyncHandle();
  601.     return 1;
  602. }
  603.  
  604.  
  605. /*
  606.  * XmbufCreateStereoWindow - 
  607.  *     Creates a stereo window in the same way that XCreateWindow creates
  608.  *     a mono window (in fact, use the same code, except for the request)
  609.  *      and returns the left and right buffers that may be 
  610.  */
  611. Window XmbufCreateStereoWindow (dpy, parent, x, y, width, height, border_width,
  612.                 depth, class, visual, valuemask, attr,
  613.                 leftp, rightp)
  614.     Display *dpy;
  615.     Window parent;
  616.     int x, y;
  617.     unsigned int width, height, border_width;
  618.     int depth;
  619.     unsigned int class;
  620.     Visual *visual;
  621.     unsigned long valuemask;
  622.     XSetWindowAttributes *attr;
  623.     Multibuffer *leftp, *rightp;
  624. {
  625.     XExtDisplayInfo *info = find_display (dpy);
  626.     Window wid;
  627.     register xMbufCreateStereoWindowReq *req;
  628.  
  629.     MbufCheckExtension (dpy, info, None);
  630.  
  631.     LockDisplay(dpy);
  632.     MbufGetReq(MbufCreateStereoWindow, req, info);
  633.     wid = req->wid = XAllocID(dpy);
  634.     req->parent = parent;
  635.     req->left = *leftp = XAllocID (dpy);
  636.     req->right = *rightp = XAllocID (dpy);
  637.     req->x = x;
  638.     req->y = y;
  639.     req->width = width;
  640.     req->height = height;
  641.     req->borderWidth = border_width;
  642.     req->depth = depth;
  643.     req->class = class;
  644.     if (visual == CopyFromParent)
  645.     req->visual = CopyFromParent;
  646.     else
  647.     req->visual = visual->visualid;
  648.     valuemask &= (CWBackPixmap|CWBackPixel|CWBorderPixmap|
  649.              CWBorderPixel|CWBitGravity|CWWinGravity|
  650.              CWBackingStore|CWBackingPlanes|CWBackingPixel|
  651.              CWOverrideRedirect|CWSaveUnder|CWEventMask|
  652.              CWDontPropagate|CWColormap|CWCursor);
  653.     if (req->mask = valuemask) {
  654.     unsigned long values[32];
  655.     register unsigned long *value = values;
  656.     unsigned int nvalues;
  657.  
  658.     if (valuemask & CWBackPixmap)
  659.       *value++ = attr->background_pixmap;
  660.     if (valuemask & CWBackPixel)
  661.       *value++ = attr->background_pixel;
  662.     if (valuemask & CWBorderPixmap)
  663.       *value++ = attr->border_pixmap;
  664.     if (valuemask & CWBorderPixel)
  665.       *value++ = attr->border_pixel;
  666.     if (valuemask & CWBitGravity)
  667.       *value++ = attr->bit_gravity;
  668.     if (valuemask & CWWinGravity)
  669.       *value++ = attr->win_gravity;
  670.     if (valuemask & CWBackingStore)
  671.       *value++ = attr->backing_store;
  672.     if (valuemask & CWBackingPlanes)
  673.       *value++ = attr->backing_planes;
  674.     if (valuemask & CWBackingPixel)
  675.       *value++ = attr->backing_pixel;
  676.     if (valuemask & CWOverrideRedirect)
  677.       *value++ = attr->override_redirect;
  678.     if (valuemask & CWSaveUnder)
  679.       *value++ = attr->save_under;
  680.     if (valuemask & CWEventMask)
  681.       *value++ = attr->event_mask;
  682.     if (valuemask & CWDontPropagate)
  683.       *value++ = attr->do_not_propagate_mask;
  684.     if (valuemask & CWColormap)
  685.       *value++ = attr->colormap;
  686.     if (valuemask & CWCursor)
  687.       *value++ = attr->cursor;
  688.     req->length += (nvalues = value - values);
  689.  
  690.     nvalues <<= 2;                /* watch out for macros... */
  691.     Data32 (dpy, (long *) values, (long)nvalues);
  692.     }
  693.     UnlockDisplay(dpy);
  694.     SyncHandle();
  695.     return wid;
  696. }
  697.  
  698.