OpenDis.c revision e9fcaa8a
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 = (Display *)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		/* Try falling back on other transports if no transport specified */
131		const char *slash = strrchr(display_name, '/');
132		if(slash == NULL) {
133			const char *protocols[] = {"local", "unix", "tcp", "inet6", "inet", NULL};
134			const char **s;
135			size_t buf_size = strlen(display_name) + 7; // max strlen + 2 (null + /)
136			char *buf = Xmalloc(buf_size * sizeof(char));
137
138			if(buf) {
139				for(s = protocols; buf && *s; s++) {
140					snprintf(buf, buf_size, "%s/%s", *s, display_name);
141					if(_XConnectXCB(dpy, buf, &iscreen))
142						goto fallback_success;
143				}
144				Xfree(buf);
145			}
146		}
147
148		OutOfMemory(dpy);
149		return NULL;
150	}
151fallback_success:
152
153	/* Initialize as much of the display structure as we can.
154	 * Initialize pointers to NULL so that XFreeDisplayStructure will
155	 * work if we run out of memory before we finish initializing.
156	 */
157	dpy->keysyms		= (KeySym *) NULL;
158	dpy->modifiermap	= NULL;
159	dpy->lock_meaning	= NoSymbol;
160	dpy->keysyms_per_keycode = 0;
161	dpy->xdefaults		= (char *)NULL;
162	dpy->scratch_length	= 0L;
163	dpy->scratch_buffer	= NULL;
164	dpy->key_bindings	= NULL;
165	dpy->ext_procs		= (_XExtension *)NULL;
166	dpy->ext_data		= (XExtData *)NULL;
167	dpy->ext_number 	= 0;
168	dpy->event_vec[X_Error] = _XUnknownWireEvent;
169	dpy->event_vec[X_Reply] = _XUnknownWireEvent;
170	dpy->wire_vec[X_Error]  = _XUnknownNativeEvent;
171	dpy->wire_vec[X_Reply]  = _XUnknownNativeEvent;
172	for (i = KeyPress; i < LASTEvent; i++) {
173	    dpy->event_vec[i] 	= _XWireToEvent;
174	    dpy->wire_vec[i] 	= NULL;
175	}
176	for (i = LASTEvent; i < 128; i++) {
177	    dpy->event_vec[i] 	= _XUnknownWireEvent;
178	    dpy->wire_vec[i] 	= _XUnknownNativeEvent;
179	}
180	dpy->resource_id	= 0;
181	dpy->db 		= (struct _XrmHashBucketRec *)NULL;
182	dpy->cursor_font	= None;
183	dpy->flags		= 0;
184	dpy->async_handlers	= NULL;
185	dpy->screens		= NULL;
186	dpy->vendor		= NULL;
187	dpy->buffer		= NULL;
188	dpy->atoms		= NULL;
189	dpy->error_vec		= NULL;
190	dpy->context_db		= NULL;
191	dpy->free_funcs		= NULL;
192	dpy->pixmap_format	= NULL;
193	dpy->cms.clientCmaps	= NULL;
194	dpy->cms.defaultCCCs	= NULL;
195	dpy->cms.perVisualIntensityMaps = NULL;
196	dpy->im_filters		= NULL;
197 	dpy->bigreq_size	= 0;
198	dpy->lock		= NULL;
199	dpy->lock_fns		= NULL;
200	dpy->qfree		= NULL;
201	dpy->next_event_serial_num = 1;
202	dpy->im_fd_info		= NULL;
203	dpy->im_fd_length	= 0;
204	dpy->conn_watchers	= NULL;
205	dpy->watcher_count	= 0;
206	dpy->filedes		= NULL;
207	dpy->flushes		= NULL;
208	dpy->xcmisc_opcode	= 0;
209	dpy->xkb_info		= NULL;
210
211/*
212 * Setup other information in this display structure.
213 */
214	dpy->vnumber = X_PROTOCOL;
215	dpy->resource_alloc = _XAllocID;
216	dpy->idlist_alloc = _XAllocIDs;
217	dpy->synchandler = NULL;
218	dpy->savedsynchandler = NULL;
219	dpy->request = 0;
220	dpy->last_request_read = 0;
221	dpy->default_screen = iscreen;  /* Value returned by ConnectDisplay */
222	dpy->last_req = (char *)&_dummy_request;
223
224	/* Initialize the display lock */
225	if (InitDisplayLock(dpy) != 0) {
226	        OutOfMemory (dpy);
227		return(NULL);
228	}
229
230	if (!_XPollfdCacheInit(dpy)) {
231	        OutOfMemory (dpy);
232		return(NULL);
233	}
234
235	/* Set up the output buffers. */
236#ifndef XLIBDEFAULTBUFSIZE
237#define XLIBDEFAULTBUFSIZE 16384 /* 16k */
238#endif
239#ifndef XLIBMINBUFSIZE
240#define XLIBMINBUFSIZE BUFSIZE /* old default buffer size */
241#endif
242	xlib_buffer_size = getenv("XLIBBUFFERSIZE");
243
244#ifdef __sun /* Backwards compatibility for old Solaris libX11 name */
245	if (xlib_buffer_size == NULL)
246	    xlib_buffer_size = getenv("XSUNBUFFERSIZE");
247#endif
248
249	if (xlib_buffer_size == NULL)
250	    conn_buf_size = XLIBDEFAULTBUFSIZE;
251	else
252	    conn_buf_size = 1024 * strtol(xlib_buffer_size, NULL, 10);
253	if (conn_buf_size < XLIBMINBUFSIZE)
254	    conn_buf_size = XLIBMINBUFSIZE;
255
256	if ((dpy->bufptr = dpy->buffer = Xcalloc(1, conn_buf_size)) == NULL) {
257	    OutOfMemory (dpy);
258	    return(NULL);
259	}
260	dpy->xcb->real_bufmax = dpy->buffer + conn_buf_size;
261	dpy->bufmax = dpy->buffer;
262
263	/* Set up the input event queue and input event queue parameters. */
264	dpy->head = dpy->tail = NULL;
265	dpy->qlen = 0;
266
267	/* Set up free-function record */
268	if ((dpy->free_funcs = (_XFreeFuncRec *)Xcalloc(1,
269							sizeof(_XFreeFuncRec)))
270	    == NULL) {
271	    OutOfMemory (dpy);
272	    return(NULL);
273	}
274
275	{
276		const struct xcb_setup_t *xcbsetup = xcb_get_setup(dpy->xcb->connection);
277		memcpy(&prefix, xcbsetup, sizeof(prefix));
278		setuplength = prefix.length << 2;
279		setup = (char *) xcbsetup;
280		setup += SIZEOF(xConnSetupPrefix);
281		u.setup = (xConnSetup *) setup;
282	}
283
284/*
285 * Check if the reply was long enough to get any information out of it.
286 */
287	usedbytes = sz_xConnSetup;
288	if (setuplength < usedbytes ) {
289	    fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
290	    OutOfMemory(dpy);
291	    return (NULL);
292	}
293
294/*
295 * We succeeded at authorization, so let us move the data into
296 * the display structure.
297 */
298	dpy->proto_major_version= prefix.majorVersion;
299	dpy->proto_minor_version= prefix.minorVersion;
300	dpy->release 		= u.setup->release;
301	dpy->resource_base	= u.setup->ridBase;
302	dpy->resource_mask	= u.setup->ridMask;
303	dpy->min_keycode	= u.setup->minKeyCode;
304	dpy->max_keycode	= u.setup->maxKeyCode;
305	dpy->motion_buffer	= u.setup->motionBufferSize;
306	dpy->nformats		= u.setup->numFormats;
307	dpy->nscreens		= u.setup->numRoots;
308	dpy->byte_order		= u.setup->imageByteOrder;
309	dpy->bitmap_unit	= u.setup->bitmapScanlineUnit;
310	dpy->bitmap_pad		= u.setup->bitmapScanlinePad;
311	dpy->bitmap_bit_order   = u.setup->bitmapBitOrder;
312	dpy->max_request_size	= u.setup->maxRequestSize;
313	mask = dpy->resource_mask;
314	dpy->resource_shift	= 0;
315	if (!mask)
316	{
317	    fprintf (stderr, "Xlib: connection to \"%s\" invalid setup\n",
318		     dpy->display_name);
319	    OutOfMemory(dpy);
320	    return (NULL);
321	}
322
323	while (!(mask & 1)) {
324	    dpy->resource_shift++;
325	    mask = mask >> 1;
326	}
327	dpy->resource_max = (dpy->resource_mask >> dpy->resource_shift) - 5;
328/*
329 * now extract the vendor string...  String must be null terminated,
330 * padded to multiple of 4 bytes.
331 */
332	/* Check for a sane vendor string length */
333	if (u.setup->nbytesVendor > 256) {
334	    OutOfMemory(dpy);
335	    return (NULL);
336	}
337
338	dpy->vendor = (char *) Xmalloc((unsigned) (u.setup->nbytesVendor + 1));
339	if (dpy->vendor == NULL) {
340	    OutOfMemory(dpy);
341	    return (NULL);
342	}
343	vendorlen = u.setup->nbytesVendor;
344
345/*
346 * validate setup length
347 */
348	usedbytes += (vendorlen + 3) & ~3;
349	if (setuplength < usedbytes) {
350	    fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
351	    OutOfMemory(dpy);
352	    return (NULL);
353	}
354
355 	u.setup = (xConnSetup *) (((char *) u.setup) + sz_xConnSetup);
356  	(void) strncpy(dpy->vendor, u.vendor, vendorlen);
357	dpy->vendor[vendorlen] = '\0';
358 	vendorlen = (vendorlen + 3) & ~3;	/* round up */
359	u.vendor += vendorlen;
360
361/*
362 * Now iterate down setup information.....
363 */
364	dpy->pixmap_format =
365	    (ScreenFormat *)Xmalloc(
366		(unsigned) (dpy->nformats *sizeof(ScreenFormat)));
367	if (dpy->pixmap_format == NULL) {
368	        OutOfMemory (dpy);
369		return(NULL);
370	}
371/*
372 * First decode the Z axis Screen format information.
373 */
374	usedbytes += dpy->nformats * sz_xPixmapFormat;
375
376	if (setuplength < usedbytes) {
377	    fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
378	    OutOfMemory (dpy);
379	    return(NULL);
380	}
381
382	for (i = 0; i < dpy->nformats; i++) {
383	    register ScreenFormat *fmt = &dpy->pixmap_format[i];
384	    fmt->depth = u.sf->depth;
385	    fmt->bits_per_pixel = u.sf->bitsPerPixel;
386	    fmt->scanline_pad = u.sf->scanLinePad;
387	    fmt->ext_data = NULL;
388	    u.sf = (xPixmapFormat *) (((char *) u.sf) + sz_xPixmapFormat);
389	}
390
391/*
392 * next the Screen structures.
393 */
394	dpy->screens =
395	    (Screen *)Xmalloc((unsigned) dpy->nscreens*sizeof(Screen));
396	if (dpy->screens == NULL) {
397	        OutOfMemory (dpy);
398		return(NULL);
399	}
400
401/*
402 * Now go deal with each screen structure.
403 */
404	for (i = 0; i < dpy->nscreens; i++) {
405	    register Screen *sp = &dpy->screens[i];
406	    VisualID root_visualID;
407
408	    usedbytes += sz_xWindowRoot;
409	    if (setuplength < usedbytes) {
410		fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
411		OutOfMemory (dpy);
412		return(NULL);
413	    }
414
415	    root_visualID = u.rp->rootVisualID;
416	    sp->display	    = dpy;
417	    sp->root 	    = u.rp->windowId;
418	    sp->cmap 	    = u.rp->defaultColormap;
419	    sp->white_pixel = u.rp->whitePixel;
420	    sp->black_pixel = u.rp->blackPixel;
421	    sp->root_input_mask = u.rp->currentInputMask;
422	    sp->width	    = u.rp->pixWidth;
423	    sp->height	    = u.rp->pixHeight;
424	    sp->mwidth	    = u.rp->mmWidth;
425	    sp->mheight	    = u.rp->mmHeight;
426	    sp->min_maps    = u.rp->minInstalledMaps;
427	    sp->max_maps    = u.rp->maxInstalledMaps;
428	    sp->backing_store= u.rp->backingStore;
429	    sp->save_unders = u.rp->saveUnders;
430	    sp->root_depth  = u.rp->rootDepth;
431	    sp->ndepths	    = u.rp->nDepths;
432	    sp->ext_data   = NULL;
433	    u.rp = (xWindowRoot *) (((char *) u.rp) + sz_xWindowRoot);
434/*
435 * lets set up the depth structures.
436 */
437	    sp->depths = (Depth *)Xmalloc(
438			(unsigned)sp->ndepths*sizeof(Depth));
439	    if (sp->depths == NULL) {
440		OutOfMemory (dpy);
441		return(NULL);
442	    }
443	    /*
444	     * for all depths on this screen.
445	     */
446	    for (j = 0; j < sp->ndepths; j++) {
447		Depth *dp = &sp->depths[j];
448
449		usedbytes += sz_xDepth;
450		if (setuplength < usedbytes) {
451		    fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
452		    OutOfMemory (dpy);
453		    return(NULL);
454		}
455
456		dp->depth = u.dp->depth;
457		dp->nvisuals = u.dp->nVisuals;
458		u.dp = (xDepth *) (((char *) u.dp) + sz_xDepth);
459		if (dp->nvisuals > 0) {
460		    dp->visuals =
461		      (Visual *)Xmalloc((unsigned)dp->nvisuals*sizeof(Visual));
462		    if (dp->visuals == NULL) {
463			OutOfMemory (dpy);
464			return(NULL);
465		    }
466		    for (k = 0; k < dp->nvisuals; k++) {
467			register Visual *vp = &dp->visuals[k];
468
469			usedbytes += sz_xVisualType;
470			if (setuplength < usedbytes) {
471			    fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
472			    OutOfMemory (dpy);
473			    return(NULL);
474			}
475
476			vp->visualid	= u.vp->visualID;
477			vp->class	= u.vp->class;
478			vp->bits_per_rgb= u.vp->bitsPerRGB;
479			vp->map_entries	= u.vp->colormapEntries;
480			vp->red_mask	= u.vp->redMask;
481			vp->green_mask	= u.vp->greenMask;
482			vp->blue_mask	= u.vp->blueMask;
483			vp->ext_data	= NULL;
484			u.vp = (xVisualType *) (((char *) u.vp) +
485						sz_xVisualType);
486		    }
487		    if (dp->depth == 32 && getenv ("XLIB_SKIP_ARGB_VISUALS"))
488		    {
489			Xfree (dp->visuals);
490			dp->visuals = NULL;
491			dp->nvisuals = 0;
492		    }
493		} else {
494		    dp->visuals = (Visual *) NULL;
495		}
496	    }
497	    sp->root_visual = _XVIDtoVisual(dpy, root_visualID);
498	}
499
500	if(usedbytes != setuplength){
501	    /* Sanity check, shouldn't happen. */
502	    fprintf(stderr, "Xlib: Did not parse entire setup message: "
503	                    "parsed: %ld, message: %ld\n",
504		    usedbytes, setuplength);
505	    OutOfMemory(dpy);
506	    return(NULL);
507	}
508
509/*
510 * Now start talking to the server to setup all other information...
511 */
512
513/*
514 * Make sure default screen is legal.
515 */
516	if (iscreen >= dpy->nscreens) {
517	    OutOfMemory(dpy);
518	    return(NULL);
519	}
520
521	dpy->bigreq_size = xcb_get_maximum_request_length(dpy->xcb->connection);
522	if(dpy->bigreq_size <= dpy->max_request_size)
523		dpy->bigreq_size = 0;
524
525/*
526 * Set up other stuff clients are always going to use.
527 */
528	for (i = 0; i < dpy->nscreens; i++) {
529	    register Screen *sp = &dpy->screens[i];
530	    XGCValues values;
531	    values.foreground = sp->black_pixel;
532	    values.background = sp->white_pixel;
533	    if ((sp->default_gc = XCreateGC (dpy, sp->root,
534					     GCForeground|GCBackground,
535					     &values)) == NULL) {
536		OutOfMemory(dpy);
537		return (NULL);
538	    }
539	}
540/*
541 * call into synchronization routine so that all programs can be
542 * forced synchronous
543 */
544	(void) XSynchronize(dpy, _Xdebug);
545
546/*
547 * get availability of large requests, and
548 * get the resource manager database off the root window.
549 */
550	LockDisplay(dpy);
551	{
552	    xGetPropertyReply reply;
553	    xGetPropertyReq *req;
554
555	    GetReq (GetProperty, req);
556	    req->window = RootWindow(dpy, 0);
557	    req->property = XA_RESOURCE_MANAGER;
558	    req->type = XA_STRING;
559	    req->delete = False;
560	    req->longOffset = 0;
561	    req->longLength = 100000000L;
562
563	    if (_XReply (dpy, (xReply *) &reply, 0, xFalse)) {
564		if (reply.format == 8 && reply.propertyType == XA_STRING &&
565		    (reply.nItems + 1 > 0) &&
566		    (reply.nItems <= req->longLength * 4) &&
567		    (dpy->xdefaults = Xmalloc (reply.nItems + 1))) {
568		    _XReadPad (dpy, dpy->xdefaults, reply.nItems);
569		    dpy->xdefaults[reply.nItems] = '\0';
570		}
571		else if (reply.propertyType != None)
572		    _XEatData(dpy, reply.nItems * (reply.format >> 3));
573	    }
574	}
575	UnlockDisplay(dpy);
576
577#ifdef MOTIFBC
578	{
579	    extern Display *_XHeadOfDisplayList;
580	    _XHeadOfDisplayList = dpy;
581	}
582#endif
583#ifdef XKB
584	XkbUseExtension(dpy,NULL,NULL);
585#endif
586/*
587 * and return successfully
588 */
589 	return(dpy);
590}
591
592/* XFreeDisplayStructure frees all the storage associated with a
593 * Display.  It is used by XOpenDisplay if it runs out of memory,
594 * and also by XCloseDisplay.   It needs to check whether all pointers
595 * are non-NULL before dereferencing them, since it may be called
596 * by XOpenDisplay before the Display structure is fully formed.
597 * XOpenDisplay must be sure to initialize all the pointers to NULL
598 * before the first possible call on this.
599 */
600
601void _XFreeDisplayStructure(Display *dpy)
602{
603	/* move all cookies in the EQ to the jar, then free them. */
604	if (dpy->qfree) {
605	    _XQEvent *qelt = dpy->qfree;
606	    while (qelt) {
607		if (_XIsEventCookie(dpy, &qelt->event))
608		    _XStoreEventCookie(dpy, &qelt->event);
609		qelt = qelt->next;
610	    }
611        }
612	if (dpy->cookiejar)
613	    _XFreeEventCookies(dpy);
614	while (dpy->ext_procs) {
615	    _XExtension *ext = dpy->ext_procs;
616	    dpy->ext_procs = ext->next;
617	    if (ext->name)
618		Xfree (ext->name);
619	    Xfree ((char *)ext);
620	}
621	if (dpy->im_filters)
622	   (*dpy->free_funcs->im_filters)(dpy);
623	if (dpy->cms.clientCmaps)
624	   (*dpy->free_funcs->clientCmaps)(dpy);
625	if (dpy->cms.defaultCCCs)
626	   (*dpy->free_funcs->defaultCCCs)(dpy);
627	if (dpy->cms.perVisualIntensityMaps)
628	   (*dpy->free_funcs->intensityMaps)(dpy);
629	if (dpy->atoms)
630	    (*dpy->free_funcs->atoms)(dpy);
631	if (dpy->modifiermap)
632	   (*dpy->free_funcs->modifiermap)(dpy->modifiermap);
633	if (dpy->key_bindings)
634	   (*dpy->free_funcs->key_bindings)(dpy);
635	if (dpy->context_db)
636	   (*dpy->free_funcs->context_db)(dpy);
637	if (dpy->xkb_info)
638	   (*dpy->free_funcs->xkb)(dpy);
639
640	/* if RM database was allocated by XGetDefault() free it */
641	if (dpy->db && (dpy->flags & XlibDisplayDfltRMDB))
642	    XrmDestroyDatabase(dpy->db);
643
644	if (dpy->screens) {
645	    register int i;
646
647            for (i = 0; i < dpy->nscreens; i++) {
648		Screen *sp = &dpy->screens[i];
649
650		if (sp->depths) {
651		   register int j;
652
653		   for (j = 0; j < sp->ndepths; j++) {
654			Depth *dp = &sp->depths[j];
655
656			if (dp->visuals) {
657			   register int k;
658
659			   for (k = 0; k < dp->nvisuals; k++)
660			     _XFreeExtData (dp->visuals[k].ext_data);
661			   Xfree ((char *) dp->visuals);
662			   }
663			}
664
665		   Xfree ((char *) sp->depths);
666		   }
667
668		_XFreeExtData (sp->ext_data);
669		}
670
671	    Xfree ((char *)dpy->screens);
672	    }
673
674	if (dpy->pixmap_format) {
675	    register int i;
676
677	    for (i = 0; i < dpy->nformats; i++)
678	      _XFreeExtData (dpy->pixmap_format[i].ext_data);
679            Xfree ((char *)dpy->pixmap_format);
680	    }
681
682	free(dpy->display_name);
683	if (dpy->vendor)
684	   Xfree (dpy->vendor);
685
686        if (dpy->buffer)
687	   Xfree (dpy->buffer);
688	if (dpy->keysyms)
689	   Xfree ((char *) dpy->keysyms);
690	if (dpy->xdefaults)
691	   Xfree (dpy->xdefaults);
692	if (dpy->error_vec)
693	    Xfree ((char *)dpy->error_vec);
694
695	_XFreeExtData (dpy->ext_data);
696	if (dpy->free_funcs)
697	    Xfree ((char *)dpy->free_funcs);
698 	if (dpy->scratch_buffer)
699 	    Xfree (dpy->scratch_buffer);
700	FreeDisplayLock(dpy);
701
702	if (dpy->qfree) {
703	    register _XQEvent *qelt = dpy->qfree;
704
705	    while (qelt) {
706		register _XQEvent *qnxt = qelt->next;
707		Xfree ((char *) qelt);
708		qelt = qnxt;
709	    }
710	}
711	while (dpy->im_fd_info) {
712	    struct _XConnectionInfo *conni = dpy->im_fd_info;
713	    dpy->im_fd_info = conni->next;
714	    if (conni->watch_data)
715		Xfree (conni->watch_data);
716	    Xfree (conni);
717	}
718	if (dpy->conn_watchers) {
719	    struct _XConnWatchInfo *watcher = dpy->conn_watchers;
720	    dpy->conn_watchers = watcher->next;
721	    Xfree (watcher);
722	}
723	if (dpy->filedes)
724	    Xfree (dpy->filedes);
725
726	_XFreeX11XCBStructure(dpy);
727
728	Xfree ((char *)dpy);
729}
730
731/* OutOfMemory is called if malloc fails.  XOpenDisplay returns NULL
732   after this returns. */
733
734static void OutOfMemory(Display *dpy)
735{
736    if(dpy->xcb->connection)
737	xcb_disconnect(dpy->xcb->connection);
738    _XFreeDisplayStructure (dpy);
739}
740