OpenDis.c revision 1ccffcbd
1/*
2
3Copyright 1985, 1986, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25*/
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30#include "Xlibint.h"
31#include "Xxcbint.h"
32#include <X11/Xatom.h>
33#include <X11/Xresource.h>
34#include <stdio.h>
35#include "Xintconn.h"
36
37#ifdef XKB
38#include "XKBlib.h"
39#endif /* XKB */
40
41#ifdef XTHREADS
42#include "locking.h"
43int  (*_XInitDisplayLock_fn)(Display *dpy) = NULL;
44void (*_XFreeDisplayLock_fn)(Display *dpy) = NULL;
45
46#define InitDisplayLock(d)	(_XInitDisplayLock_fn ? (*_XInitDisplayLock_fn)(d) : Success)
47#define FreeDisplayLock(d)	if (_XFreeDisplayLock_fn) (*_XFreeDisplayLock_fn)(d)
48#else
49#define InitDisplayLock(dis) Success
50#define FreeDisplayLock(dis)
51#endif /* XTHREADS */
52
53static xReq _dummy_request = {
54	0, 0, 0
55};
56
57static void OutOfMemory(Display *dpy);
58
59/*
60 * Connects to a server, creates a Display object and returns a pointer to
61 * the newly created Display back to the caller.
62 */
63Display *
64XOpenDisplay (
65	register _Xconst char *display)
66{
67	register Display *dpy;		/* New Display object being created. */
68	register int i;
69	int j, k;			/* random iterator indexes */
70	char *display_name;		/* pointer to display name */
71	char *setup = NULL;		/* memory allocated at startup */
72	int iscreen;			/* screen number */
73	xConnSetupPrefix prefix;	/* prefix information */
74	int vendorlen;			/* length of vendor string */
75	union {
76		xConnSetup *setup;
77		char *failure;
78		char *vendor;
79		xPixmapFormat *sf;
80		xWindowRoot *rp;
81		xDepth *dp;
82		xVisualType *vp;
83	} u;				/* proto data returned from server */
84	long setuplength;	/* number of bytes in setup message */
85	long usedbytes = 0;     /* number of bytes we have processed */
86	unsigned long mask;
87	long int conn_buf_size;
88	char *xlib_buffer_size;
89
90	/*
91	 * If the display specifier string supplied as an argument to this
92	 * routine is NULL or a pointer to NULL, read the DISPLAY variable.
93	 */
94	if (display == NULL || *display == '\0') {
95		if ((display_name = getenv("DISPLAY")) == NULL) {
96			/* Oops! No DISPLAY environment variable - error. */
97			return(NULL);
98		}
99	}
100	else {
101		/* Display is non-NULL, copy the pointer */
102		display_name = (char *)display;
103	}
104
105/*
106 * Set the default error handlers.  This allows the global variables to
107 * default to NULL for use with shared libraries.
108 */
109	if (_XErrorFunction == NULL) (void) XSetErrorHandler (NULL);
110	if (_XIOErrorFunction == NULL) (void) XSetIOErrorHandler (NULL);
111
112/*
113 * Attempt to allocate a display structure. Return NULL if allocation fails.
114 */
115	if ((dpy = Xcalloc(1, sizeof(Display))) == NULL) {
116		return(NULL);
117	}
118
119	if ((dpy->display_name = strdup(display_name)) == NULL) {
120		OutOfMemory(dpy);
121		return(NULL);
122	}
123
124/*
125 * Call the Connect routine to get the transport connection object.
126 * If NULL is returned, the connection failed.
127 */
128
129	if(!_XConnectXCB(dpy, display, &iscreen)) {
130		OutOfMemory(dpy);
131		return NULL;
132	}
133
134	/* Initialize as much of the display structure as we can.
135	 * Initialize pointers to NULL so that XFreeDisplayStructure will
136	 * work if we run out of memory before we finish initializing.
137	 */
138	dpy->keysyms		= (KeySym *) NULL;
139	dpy->modifiermap	= NULL;
140	dpy->lock_meaning	= NoSymbol;
141	dpy->keysyms_per_keycode = 0;
142	dpy->xdefaults		= (char *)NULL;
143	dpy->scratch_length	= 0L;
144	dpy->scratch_buffer	= NULL;
145	dpy->key_bindings	= NULL;
146	dpy->ext_procs		= (_XExtension *)NULL;
147	dpy->ext_data		= (XExtData *)NULL;
148	dpy->ext_number 	= 0;
149	dpy->event_vec[X_Error] = _XUnknownWireEvent;
150	dpy->event_vec[X_Reply] = _XUnknownWireEvent;
151	dpy->wire_vec[X_Error]  = _XUnknownNativeEvent;
152	dpy->wire_vec[X_Reply]  = _XUnknownNativeEvent;
153	for (i = KeyPress; i < LASTEvent; i++) {
154	    dpy->event_vec[i] 	= _XWireToEvent;
155	    dpy->wire_vec[i] 	= NULL;
156	}
157	for (i = LASTEvent; i < 128; i++) {
158	    dpy->event_vec[i] 	= _XUnknownWireEvent;
159	    dpy->wire_vec[i] 	= _XUnknownNativeEvent;
160	}
161	dpy->resource_id	= 0;
162	dpy->db 		= (struct _XrmHashBucketRec *)NULL;
163	dpy->cursor_font	= None;
164	dpy->flags		= 0;
165	dpy->async_handlers	= NULL;
166	dpy->screens		= NULL;
167	dpy->vendor		= NULL;
168	dpy->buffer		= NULL;
169	dpy->atoms		= NULL;
170	dpy->error_vec		= NULL;
171	dpy->context_db		= NULL;
172	dpy->free_funcs		= NULL;
173	dpy->pixmap_format	= NULL;
174	dpy->cms.clientCmaps	= NULL;
175	dpy->cms.defaultCCCs	= NULL;
176	dpy->cms.perVisualIntensityMaps = NULL;
177	dpy->im_filters		= NULL;
178 	dpy->bigreq_size	= 0;
179	dpy->lock		= NULL;
180	dpy->lock_fns		= NULL;
181	dpy->qfree		= NULL;
182	dpy->next_event_serial_num = 1;
183	dpy->im_fd_info		= NULL;
184	dpy->im_fd_length	= 0;
185	dpy->conn_watchers	= NULL;
186	dpy->watcher_count	= 0;
187	dpy->filedes		= NULL;
188	dpy->flushes		= NULL;
189	dpy->xcmisc_opcode	= 0;
190	dpy->xkb_info		= NULL;
191	dpy->exit_handler_data	= NULL;
192        dpy->in_ifevent         = False;
193
194/*
195 * Setup other information in this display structure.
196 */
197	dpy->vnumber = X_PROTOCOL;
198	dpy->resource_alloc = _XAllocID;
199	dpy->idlist_alloc = _XAllocIDs;
200	dpy->synchandler = NULL;
201	dpy->savedsynchandler = NULL;
202	X_DPY_SET_REQUEST(dpy, 0);
203	X_DPY_SET_LAST_REQUEST_READ(dpy, 0);
204	dpy->default_screen = iscreen;  /* Value returned by ConnectDisplay */
205	dpy->last_req = (char *)&_dummy_request;
206	dpy->error_threads = NULL;
207	dpy->exit_handler = _XDefaultIOErrorExit;
208
209	/* Initialize the display lock */
210	if (InitDisplayLock(dpy) != 0) {
211	        OutOfMemory (dpy);
212		return(NULL);
213	}
214
215	if (!_XPollfdCacheInit(dpy)) {
216	        OutOfMemory (dpy);
217		return(NULL);
218	}
219
220	/* Set up the output buffers. */
221#ifndef XLIBDEFAULTBUFSIZE
222#define XLIBDEFAULTBUFSIZE 16384 /* 16k */
223#endif
224#ifndef XLIBMINBUFSIZE
225#define XLIBMINBUFSIZE BUFSIZE /* old default buffer size */
226#endif
227	xlib_buffer_size = getenv("XLIBBUFFERSIZE");
228
229#ifdef __sun /* Backwards compatibility for old Solaris libX11 name */
230	if (xlib_buffer_size == NULL)
231	    xlib_buffer_size = getenv("XSUNBUFFERSIZE");
232#endif
233
234	if (xlib_buffer_size == NULL)
235	    conn_buf_size = XLIBDEFAULTBUFSIZE;
236	else
237	    conn_buf_size = 1024 * strtol(xlib_buffer_size, NULL, 10);
238	if (conn_buf_size < XLIBMINBUFSIZE)
239	    conn_buf_size = XLIBMINBUFSIZE;
240
241	if ((dpy->bufptr = dpy->buffer = Xcalloc(1, conn_buf_size)) == NULL) {
242	    OutOfMemory (dpy);
243	    return(NULL);
244	}
245	dpy->xcb->real_bufmax = dpy->buffer + conn_buf_size;
246	dpy->bufmax = dpy->buffer;
247
248	/* Set up the input event queue and input event queue parameters. */
249	dpy->head = dpy->tail = NULL;
250	dpy->qlen = 0;
251
252	/* Set up free-function record */
253	if ((dpy->free_funcs = Xcalloc(1, sizeof(_XFreeFuncRec))) == NULL) {
254	    OutOfMemory (dpy);
255	    return(NULL);
256	}
257
258	{
259		const struct xcb_setup_t *xcbsetup = xcb_get_setup(dpy->xcb->connection);
260		memcpy(&prefix, xcbsetup, sizeof(prefix));
261		setuplength = prefix.length << 2;
262		setup = (char *) xcbsetup;
263		setup += SIZEOF(xConnSetupPrefix);
264		u.setup = (xConnSetup *) setup;
265	}
266
267/*
268 * Check if the reply was long enough to get any information out of it.
269 */
270	usedbytes = sz_xConnSetup;
271	if (setuplength < usedbytes ) {
272	    fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
273	    OutOfMemory(dpy);
274	    return (NULL);
275	}
276
277/*
278 * We succeeded at authorization, so let us move the data into
279 * the display structure.
280 */
281	dpy->proto_major_version= prefix.majorVersion;
282	dpy->proto_minor_version= prefix.minorVersion;
283	dpy->release 		= u.setup->release;
284	dpy->resource_base	= u.setup->ridBase;
285	dpy->resource_mask	= u.setup->ridMask;
286	dpy->min_keycode	= u.setup->minKeyCode;
287	dpy->max_keycode	= u.setup->maxKeyCode;
288	dpy->motion_buffer	= u.setup->motionBufferSize;
289	dpy->nformats		= u.setup->numFormats;
290	dpy->nscreens		= u.setup->numRoots;
291	dpy->byte_order		= u.setup->imageByteOrder;
292	dpy->bitmap_unit	= u.setup->bitmapScanlineUnit;
293	dpy->bitmap_pad		= u.setup->bitmapScanlinePad;
294	dpy->bitmap_bit_order   = u.setup->bitmapBitOrder;
295	dpy->max_request_size	= u.setup->maxRequestSize;
296	mask = dpy->resource_mask;
297	dpy->resource_shift	= 0;
298	if (!mask)
299	{
300	    fprintf (stderr, "Xlib: connection to \"%s\" invalid setup\n",
301		     dpy->display_name);
302	    OutOfMemory(dpy);
303	    return (NULL);
304	}
305
306	while (!(mask & 1)) {
307	    dpy->resource_shift++;
308	    mask = mask >> 1;
309	}
310	dpy->resource_max = (dpy->resource_mask >> dpy->resource_shift) - 5;
311/*
312 * now extract the vendor string...  String must be null terminated,
313 * padded to multiple of 4 bytes.
314 */
315	/* Check for a sane vendor string length */
316	if (u.setup->nbytesVendor > 256) {
317	    OutOfMemory(dpy);
318	    return (NULL);
319	}
320
321	dpy->vendor = Xmalloc(u.setup->nbytesVendor + 1);
322	if (dpy->vendor == NULL) {
323	    OutOfMemory(dpy);
324	    return (NULL);
325	}
326	vendorlen = u.setup->nbytesVendor;
327
328/*
329 * validate setup length
330 */
331	usedbytes += (vendorlen + 3) & ~3;
332	if (setuplength < usedbytes) {
333	    fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
334	    OutOfMemory(dpy);
335	    return (NULL);
336	}
337
338 	u.setup = (xConnSetup *) (((char *) u.setup) + sz_xConnSetup);
339  	(void) strncpy(dpy->vendor, u.vendor, (size_t) vendorlen);
340	dpy->vendor[vendorlen] = '\0';
341 	vendorlen = (vendorlen + 3) & ~3;	/* round up */
342	u.vendor += vendorlen;
343
344/*
345 * Now iterate down setup information.....
346 */
347	dpy->pixmap_format = Xcalloc(dpy->nformats, sizeof(ScreenFormat));
348	if (dpy->pixmap_format == NULL) {
349	        OutOfMemory (dpy);
350		return(NULL);
351	}
352/*
353 * First decode the Z axis Screen format information.
354 */
355	usedbytes += dpy->nformats * sz_xPixmapFormat;
356
357	if (setuplength < usedbytes) {
358	    fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
359	    OutOfMemory (dpy);
360	    return(NULL);
361	}
362
363	for (i = 0; i < dpy->nformats; i++) {
364	    register ScreenFormat *fmt = &dpy->pixmap_format[i];
365	    fmt->depth = u.sf->depth;
366	    fmt->bits_per_pixel = u.sf->bitsPerPixel;
367	    fmt->scanline_pad = u.sf->scanLinePad;
368	    fmt->ext_data = NULL;
369	    u.sf = (xPixmapFormat *) (((char *) u.sf) + sz_xPixmapFormat);
370	}
371
372/*
373 * next the Screen structures.
374 */
375	dpy->screens = Xcalloc(dpy->nscreens, sizeof(Screen));
376	if (dpy->screens == NULL) {
377	        OutOfMemory (dpy);
378		return(NULL);
379	}
380
381/*
382 * Now go deal with each screen structure.
383 */
384	for (i = 0; i < dpy->nscreens; i++) {
385	    register Screen *sp = &dpy->screens[i];
386	    VisualID root_visualID;
387
388	    usedbytes += sz_xWindowRoot;
389	    if (setuplength < usedbytes) {
390		fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
391		OutOfMemory (dpy);
392		return(NULL);
393	    }
394
395	    root_visualID = u.rp->rootVisualID;
396	    sp->display	    = dpy;
397	    sp->root 	    = u.rp->windowId;
398	    sp->cmap 	    = u.rp->defaultColormap;
399	    sp->white_pixel = u.rp->whitePixel;
400	    sp->black_pixel = u.rp->blackPixel;
401	    sp->root_input_mask = u.rp->currentInputMask;
402	    sp->width	    = u.rp->pixWidth;
403	    sp->height	    = u.rp->pixHeight;
404	    sp->mwidth	    = u.rp->mmWidth;
405	    sp->mheight	    = u.rp->mmHeight;
406	    sp->min_maps    = u.rp->minInstalledMaps;
407	    sp->max_maps    = u.rp->maxInstalledMaps;
408	    sp->backing_store= u.rp->backingStore;
409	    sp->save_unders = u.rp->saveUnders;
410	    sp->root_depth  = u.rp->rootDepth;
411	    sp->ndepths	    = u.rp->nDepths;
412	    sp->ext_data   = NULL;
413	    u.rp = (xWindowRoot *) (((char *) u.rp) + sz_xWindowRoot);
414/*
415 * lets set up the depth structures.
416 */
417	    sp->depths = Xcalloc(sp->ndepths, sizeof(Depth));
418	    if (sp->depths == NULL) {
419		OutOfMemory (dpy);
420		return(NULL);
421	    }
422	    /*
423	     * for all depths on this screen.
424	     */
425	    for (j = 0; j < sp->ndepths; j++) {
426		Depth *dp = &sp->depths[j];
427
428		usedbytes += sz_xDepth;
429		if (setuplength < usedbytes) {
430		    fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
431		    OutOfMemory (dpy);
432		    return(NULL);
433		}
434
435		dp->depth = u.dp->depth;
436		dp->nvisuals = u.dp->nVisuals;
437		u.dp = (xDepth *) (((char *) u.dp) + sz_xDepth);
438		if (dp->nvisuals > 0) {
439		    dp->visuals = Xcalloc(dp->nvisuals, sizeof(Visual));
440		    if (dp->visuals == NULL) {
441			OutOfMemory (dpy);
442			return(NULL);
443		    }
444		    for (k = 0; k < dp->nvisuals; k++) {
445			register Visual *vp = &dp->visuals[k];
446
447			usedbytes += sz_xVisualType;
448			if (setuplength < usedbytes) {
449			    fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
450			    OutOfMemory (dpy);
451			    return(NULL);
452			}
453
454			vp->visualid	= u.vp->visualID;
455			vp->class	= u.vp->class;
456			vp->bits_per_rgb= u.vp->bitsPerRGB;
457			vp->map_entries	= u.vp->colormapEntries;
458			vp->red_mask	= u.vp->redMask;
459			vp->green_mask	= u.vp->greenMask;
460			vp->blue_mask	= u.vp->blueMask;
461			vp->ext_data	= NULL;
462			u.vp = (xVisualType *) (((char *) u.vp) +
463						sz_xVisualType);
464		    }
465		    if (dp->depth == 32 && getenv ("XLIB_SKIP_ARGB_VISUALS"))
466		    {
467			Xfree (dp->visuals);
468			dp->visuals = NULL;
469			dp->nvisuals = 0;
470		    }
471		} else {
472		    dp->visuals = (Visual *) NULL;
473		}
474	    }
475	    sp->root_visual = _XVIDtoVisual(dpy, root_visualID);
476	}
477
478	if(usedbytes != setuplength){
479	    /* Sanity check, shouldn't happen. */
480	    fprintf(stderr, "Xlib: Did not parse entire setup message: "
481	                    "parsed: %ld, message: %ld\n",
482		    usedbytes, setuplength);
483	    OutOfMemory(dpy);
484	    return(NULL);
485	}
486
487/*
488 * Now start talking to the server to setup all other information...
489 */
490
491/*
492 * Make sure default screen is legal.
493 */
494	if (iscreen >= dpy->nscreens) {
495	    OutOfMemory(dpy);
496	    return(NULL);
497	}
498
499/*
500 * get availability of large requests
501 */
502	dpy->bigreq_size = xcb_get_maximum_request_length(dpy->xcb->connection);
503	if(dpy->bigreq_size <= dpy->max_request_size)
504		dpy->bigreq_size = 0;
505
506/*
507 * Set up other stuff clients are always going to use.
508 */
509	for (i = 0; i < dpy->nscreens; i++) {
510	    register Screen *sp = &dpy->screens[i];
511	    XGCValues values;
512	    values.foreground = sp->black_pixel;
513	    values.background = sp->white_pixel;
514	    if ((sp->default_gc = XCreateGC (dpy, sp->root,
515					     GCForeground|GCBackground,
516					     &values)) == NULL) {
517		OutOfMemory(dpy);
518		return (NULL);
519	    }
520	}
521/*
522 * call into synchronization routine so that all programs can be
523 * forced synchronous
524 */
525	(void) XSynchronize(dpy, _Xdebug);
526
527/*
528 * get the resource manager database off the root window.
529 */
530	LockDisplay(dpy);
531	{
532	    xGetPropertyReply reply;
533	    xGetPropertyReq *req;
534
535	    GetReq (GetProperty, req);
536	    req->window = RootWindow(dpy, 0);
537	    req->property = XA_RESOURCE_MANAGER;
538	    req->type = XA_STRING;
539	    req->delete = False;
540	    req->longOffset = 0;
541	    req->longLength = 100000000L;
542
543	    if (_XReply (dpy, (xReply *) &reply, 0, xFalse)) {
544		if (reply.format == 8 && reply.propertyType == XA_STRING &&
545		    (reply.nItems + 1 > 0) &&
546		    (reply.nItems <= req->longLength * 4) &&
547		    (dpy->xdefaults = Xmalloc (reply.nItems + 1))) {
548		    _XReadPad (dpy, dpy->xdefaults, reply.nItems);
549		    dpy->xdefaults[reply.nItems] = '\0';
550		}
551		else if (reply.propertyType != None)
552		    _XEatDataWords(dpy, reply.length);
553	    }
554	}
555	UnlockDisplay(dpy);
556
557#ifdef MOTIFBC
558	{
559	    extern Display *_XHeadOfDisplayList;
560	    _XHeadOfDisplayList = dpy;
561	}
562#endif
563#ifdef XKB
564	XkbUseExtension(dpy,NULL,NULL);
565#endif
566/*
567 * and return successfully
568 */
569 	return(dpy);
570}
571
572/* XFreeDisplayStructure frees all the storage associated with a
573 * Display.  It is used by XOpenDisplay if it runs out of memory,
574 * and also by XCloseDisplay.   It needs to check whether all pointers
575 * are non-NULL before dereferencing them, since it may be called
576 * by XOpenDisplay before the Display structure is fully formed.
577 * XOpenDisplay must be sure to initialize all the pointers to NULL
578 * before the first possible call on this.
579 */
580
581void _XFreeDisplayStructure(Display *dpy)
582{
583	/* move all cookies in the EQ to the jar, then free them. */
584	if (dpy->qfree) {
585	    _XQEvent *qelt = dpy->qfree;
586	    while (qelt) {
587		if (_XIsEventCookie(dpy, &qelt->event))
588		    _XStoreEventCookie(dpy, &qelt->event);
589		qelt = qelt->next;
590	    }
591        }
592	if (dpy->cookiejar)
593	    _XFreeEventCookies(dpy);
594	while (dpy->ext_procs) {
595	    _XExtension *ext = dpy->ext_procs;
596	    dpy->ext_procs = ext->next;
597	    Xfree (ext->name);
598	    Xfree (ext);
599	}
600	if (dpy->im_filters)
601	   (*dpy->free_funcs->im_filters)(dpy);
602	if (dpy->cms.clientCmaps)
603	   (*dpy->free_funcs->clientCmaps)(dpy);
604	if (dpy->cms.defaultCCCs)
605	   (*dpy->free_funcs->defaultCCCs)(dpy);
606	if (dpy->cms.perVisualIntensityMaps)
607	   (*dpy->free_funcs->intensityMaps)(dpy);
608	if (dpy->atoms)
609	    (*dpy->free_funcs->atoms)(dpy);
610	if (dpy->modifiermap)
611	   (*dpy->free_funcs->modifiermap)(dpy->modifiermap);
612	if (dpy->key_bindings)
613	   (*dpy->free_funcs->key_bindings)(dpy);
614	if (dpy->context_db)
615	   (*dpy->free_funcs->context_db)(dpy);
616	if (dpy->xkb_info)
617	   (*dpy->free_funcs->xkb)(dpy);
618
619	/* if RM database was allocated by XGetDefault() free it */
620	if (dpy->db && (dpy->flags & XlibDisplayDfltRMDB))
621	    XrmDestroyDatabase(dpy->db);
622
623	if (dpy->screens) {
624	    register int i;
625
626            for (i = 0; i < dpy->nscreens; i++) {
627		Screen *sp = &dpy->screens[i];
628
629		if (sp->depths) {
630		   register int j;
631
632		   for (j = 0; j < sp->ndepths; j++) {
633			Depth *dp = &sp->depths[j];
634
635			if (dp->visuals) {
636			   register int k;
637
638			   for (k = 0; k < dp->nvisuals; k++)
639			     _XFreeExtData (dp->visuals[k].ext_data);
640			   Xfree (dp->visuals);
641			   }
642			}
643
644		   Xfree (sp->depths);
645		   }
646
647		_XFreeExtData (sp->ext_data);
648		}
649
650	    Xfree (dpy->screens);
651	    }
652
653	if (dpy->pixmap_format) {
654	    register int i;
655
656	    for (i = 0; i < dpy->nformats; i++)
657	      _XFreeExtData (dpy->pixmap_format[i].ext_data);
658            Xfree (dpy->pixmap_format);
659	    }
660
661	free(dpy->display_name);
662
663	Xfree (dpy->vendor);
664	Xfree (dpy->buffer);
665	Xfree (dpy->keysyms);
666	Xfree (dpy->xdefaults);
667	Xfree (dpy->error_vec);
668
669	_XFreeExtData (dpy->ext_data);
670
671	Xfree (dpy->free_funcs);
672	Xfree (dpy->scratch_buffer);
673	FreeDisplayLock(dpy);
674
675	if (dpy->qfree) {
676	    register _XQEvent *qelt = dpy->qfree;
677
678	    while (qelt) {
679		register _XQEvent *qnxt = qelt->next;
680		Xfree (qelt);
681		qelt = qnxt;
682	    }
683	}
684	while (dpy->im_fd_info) {
685	    struct _XConnectionInfo *conni = dpy->im_fd_info;
686	    dpy->im_fd_info = conni->next;
687	    Xfree (conni->watch_data);
688	    Xfree (conni);
689	}
690	if (dpy->conn_watchers) {
691	    struct _XConnWatchInfo *watcher = dpy->conn_watchers;
692	    dpy->conn_watchers = watcher->next;
693	    Xfree (watcher);
694	}
695
696	Xfree (dpy->filedes);
697
698	_XFreeX11XCBStructure(dpy);
699
700	Xfree (dpy);
701}
702
703/* OutOfMemory is called if malloc fails.  XOpenDisplay returns NULL
704   after this returns. */
705
706static void OutOfMemory(Display *dpy)
707{
708    if(dpy->xcb->connection)
709	xcb_disconnect(dpy->xcb->connection);
710    _XFreeDisplayStructure (dpy);
711}
712