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