Display.c revision 444c061a
1/* $Xorg: Display.c,v 1.6 2001/02/09 02:03:54 xorgcvs Exp $ */
2
3/***********************************************************
4Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
5Copyright 1993 by Sun Microsystems, Inc. Mountain View, CA.
6
7                        All Rights Reserved
8
9Permission to use, copy, modify, and distribute this software and its
10documentation for any purpose and without fee is hereby granted,
11provided that the above copyright notice appear in all copies and that
12both that copyright notice and this permission notice appear in
13supporting documentation, and that the names of Digital or Sun not be
14used in advertising or publicity pertaining to distribution of the
15software without specific, written prior permission.
16
17DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
18ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
19DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
20ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
21WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
22ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23SOFTWARE.
24
25SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
26INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
27NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE  LI-
28ABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
29ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
30PROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
31OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
32THE USE OR PERFORMANCE OF THIS SOFTWARE.
33
34******************************************************************/
35/* $XFree86: xc/lib/Xt/Display.c,v 3.15 2002/09/18 01:25:01 dawes Exp $ */
36
37/*
38
39Copyright 1987, 1988, 1998  The Open Group
40
41Permission to use, copy, modify, distribute, and sell this software and its
42documentation for any purpose is hereby granted without fee, provided that
43the above copyright notice appear in all copies and that both that
44copyright notice and this permission notice appear in supporting
45documentation.
46
47The above copyright notice and this permission notice shall be included in
48all copies or substantial portions of the Software.
49
50THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
51IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
52FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
53OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
54AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
55CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
56
57Except as contained in this notice, the name of The Open Group shall not be
58used in advertising or otherwise to promote the sale, use or other dealings
59in this Software without prior written authorization from The Open Group.
60
61*/
62
63#ifdef HAVE_CONFIG_H
64#include <config.h>
65#endif
66#include "IntrinsicI.h"
67#ifndef X_NO_RESOURCE_CONFIGURATION_MANAGEMENT
68#include "ResConfigP.h"
69#endif
70
71#include <stdlib.h>
72
73#ifdef XTHREADS
74void (*_XtProcessLock)(void) = NULL;
75void (*_XtProcessUnlock)(void) = NULL;
76void (*_XtInitAppLock)(XtAppContext) = NULL;
77#endif
78
79static String XtNnoPerDisplay = "noPerDisplay";
80
81ProcessContext _XtGetProcessContext(void)
82{
83    static ProcessContextRec processContextRec = {
84	(XtAppContext)NULL,
85	(XtAppContext)NULL,
86	(ConverterTable)NULL,
87	{(XtLanguageProc)NULL, (XtPointer)NULL}
88    };
89
90    return &processContextRec;
91}
92
93
94XtAppContext _XtDefaultAppContext(void)
95{
96    ProcessContext process = _XtGetProcessContext();
97    XtAppContext app;
98
99    LOCK_PROCESS;
100    if (process->defaultAppContext == NULL) {
101	process->defaultAppContext = XtCreateApplicationContext();
102    }
103    app = process->defaultAppContext;
104    UNLOCK_PROCESS;
105    return app;
106}
107
108static void AddToAppContext(
109	Display *d,
110	XtAppContext app)
111{
112#define DISPLAYS_TO_ADD 4
113
114	if (app->count >= app->max) {
115	    app->max += DISPLAYS_TO_ADD;
116	    app->list = (Display **) XtRealloc((char *)app->list,
117		    (unsigned) app->max * sizeof(Display *));
118	}
119
120	app->list[app->count++] = d;
121	app->rebuild_fdlist = TRUE;
122#ifndef USE_POLL
123	if (ConnectionNumber(d) + 1 > app->fds.nfds) {
124	    app->fds.nfds = ConnectionNumber(d) + 1;
125	}
126#else
127	app->fds.nfds++;
128#endif
129#undef DISPLAYS_TO_ADD
130}
131
132static void XtDeleteFromAppContext(
133	Display *d,
134	register XtAppContext app)
135{
136	register int i;
137
138	for (i = 0; i < app->count; i++) if (app->list[i] == d) break;
139
140	if (i < app->count) {
141	    if (i <= app->last && app->last > 0) app->last--;
142	    for (i++; i < app->count; i++) app->list[i-1] = app->list[i];
143	    app->count--;
144	}
145	app->rebuild_fdlist = TRUE;
146#ifndef USE_POLL
147	if ((ConnectionNumber(d) + 1) == app->fds.nfds)
148	    app->fds.nfds--;
149	else			/* Unnecessary, just to be fool-proof */
150	    FD_CLR(ConnectionNumber(d), &app->fds.rmask);
151#else
152	app->fds.nfds--;
153#endif
154}
155
156static XtPerDisplay NewPerDisplay(
157	Display *dpy)
158{
159	PerDisplayTablePtr pd;
160
161	pd = XtNew(PerDisplayTable);
162	LOCK_PROCESS;
163	pd->dpy = dpy;
164	pd->next = _XtperDisplayList;
165	_XtperDisplayList = pd;
166	UNLOCK_PROCESS;
167	return &(pd->perDpy);
168}
169
170static XtPerDisplay InitPerDisplay(
171    Display *dpy,
172    XtAppContext app,
173    _Xconst char * name,
174    _Xconst char * classname)
175{
176    XtPerDisplay pd;
177
178    AddToAppContext(dpy, app);
179
180    pd = NewPerDisplay(dpy);
181    _XtHeapInit(&pd->heap);
182    pd->destroy_callbacks = NULL;
183    pd->region = XCreateRegion();
184    pd->case_cvt = NULL;
185    pd->defaultKeycodeTranslator = XtTranslateKey;
186    pd->keysyms_serial = 0;
187    pd->keysyms = NULL;
188    XDisplayKeycodes(dpy, &pd->min_keycode, &pd->max_keycode);
189    pd->modKeysyms = NULL;
190    pd->modsToKeysyms = NULL;
191    pd->appContext = app;
192    pd->name = XrmStringToName(name);
193    pd->class = XrmStringToClass(classname);
194    pd->being_destroyed = False;
195    pd->GClist = NULL;
196    pd->pixmap_tab = NULL;
197    pd->language = NULL;
198    pd->rv = False;
199    pd->last_event.xany.serial = 0;
200    pd->last_timestamp = 0;
201    _XtAllocTMContext(pd);
202    pd->mapping_callbacks = NULL;
203
204    pd->pdi.grabList = NULL;
205    pd->pdi.trace = NULL;
206    pd->pdi.traceDepth = 0;
207    pd->pdi.traceMax = 0;
208    pd->pdi.focusWidget = NULL;
209    pd->pdi.activatingKey = 0;
210    pd->pdi.keyboard.grabType = XtNoServerGrab;
211    pd->pdi.pointer.grabType  = XtNoServerGrab;
212    _XtAllocWWTable(pd);
213    pd->per_screen_db = (XrmDatabase *)__XtCalloc(ScreenCount(dpy),
214						sizeof(XrmDatabase));
215    pd->cmd_db = (XrmDatabase)NULL;
216    pd->server_db = (XrmDatabase)NULL;
217    pd->dispatcher_list = NULL;
218    pd->ext_select_list = NULL;
219    pd->ext_select_count = 0;
220    pd->hook_object = NULL;
221#if 0
222    pd->hook_object = _XtCreate("hooks", "Hooks", hookObjectClass,
223	(Widget)NULL, (Screen*)DefaultScreenOfDisplay(dpy),
224	(ArgList)NULL, 0, (XtTypedArgList)NULL, 0,
225	(ConstraintWidgetClass)NULL);
226#endif
227
228#ifndef X_NO_RESOURCE_CONFIGURATION_MANAGEMENT
229    pd->rcm_init = XInternAtom (dpy, RCM_INIT, 0);
230    pd->rcm_data = XInternAtom (dpy, RCM_DATA, 0);
231#endif
232
233    return pd;
234}
235
236Display *XtOpenDisplay(
237	XtAppContext app,
238	_Xconst char* displayName,
239	_Xconst char* applName,
240	_Xconst char* className,
241	XrmOptionDescRec *urlist,
242	Cardinal num_urs,
243	int *argc,
244	String *argv)
245{
246	Display *d;
247	XrmDatabase db = 0;
248	XtPerDisplay pd;
249	String language = NULL;
250
251	LOCK_APP(app);
252	LOCK_PROCESS;
253	/* parse the command line for name, display, and/or language */
254	db = _XtPreparseCommandLine(urlist, num_urs, *argc, argv,
255				(String *)&applName,
256				(String *)(displayName ? NULL : &displayName),
257				(app->process->globalLangProcRec.proc ?
258				&language : NULL));
259	UNLOCK_PROCESS;
260	d = XOpenDisplay(displayName);
261
262	if (! applName && !(applName = getenv("RESOURCE_NAME"))) {
263	    if (*argc > 0 && argv[0] && *argv[0]) {
264#ifdef WIN32
265		char *ptr = strrchr(argv[0], '\\');
266#else
267		char *ptr = strrchr(argv[0], '/');
268#endif
269#ifdef __UNIXOS2__
270		char *dot_ptr,*ptr2;
271		ptr2 = strrchr(argv[0],'\\');
272		if (ptr2 > ptr) ptr = ptr2;
273		dot_ptr = strrchr(argv[0],'.');
274		if (dot_ptr && (dot_ptr > ptr)) *dot_ptr='\0';
275#endif  /* This will remove the .exe suffix under OS/2 */
276
277		if (ptr) applName = ++ptr;
278		else applName = argv[0];
279	    } else
280		applName = "main";
281	}
282
283	if (d) {
284	    pd = InitPerDisplay(d, app, applName, className);
285	    pd->language = language;
286	    _XtDisplayInitialize(d, pd, applName, urlist, num_urs, argc, argv);
287	} else {
288	    int len;
289	    displayName = XDisplayName(displayName);
290	    len = strlen (displayName);
291	    app->display_name_tried = (String) __XtMalloc (len + 1);
292	    strncpy ((char*) app->display_name_tried, displayName, len + 1);
293	    app->display_name_tried[len] = '\0';
294	}
295	if (db) XrmDestroyDatabase(db);
296	UNLOCK_APP(app);
297	return d;
298}
299
300Display *
301_XtAppInit(
302	XtAppContext * app_context_return,
303	String application_class,
304	XrmOptionDescRec *options,
305	Cardinal num_options,
306	int *argc_in_out,
307	String **argv_in_out,
308	String * fallback_resources)
309{
310    String *saved_argv;
311    int i;
312    Display *dpy;
313
314/*
315 * Save away argv and argc so we can set the properties later
316 */
317
318    saved_argv = (String *)
319	__XtMalloc( (Cardinal)((*argc_in_out + 1) * sizeof(String)) );
320
321    for (i = 0 ; i < *argc_in_out ; i++) saved_argv[i] = (*argv_in_out)[i];
322    saved_argv[i] = NULL;	/* NULL terminate that sucker. */
323
324
325    *app_context_return = XtCreateApplicationContext();
326
327    LOCK_APP((*app_context_return));
328    if (fallback_resources) /* save a procedure call */
329	XtAppSetFallbackResources(*app_context_return, fallback_resources);
330
331    dpy = XtOpenDisplay(*app_context_return, (String) NULL, NULL,
332			application_class,
333			options, num_options, argc_in_out, *argv_in_out);
334
335    if (!dpy) {
336	String param = (*app_context_return)->display_name_tried;
337	Cardinal param_count = 1;
338	XtErrorMsg("invalidDisplay","xtInitialize",XtCXtToolkitError,
339                   "Can't open display: %s", &param, &param_count);
340	XtFree((char *) (*app_context_return)->display_name_tried);
341    }
342    *argv_in_out = saved_argv;
343    UNLOCK_APP((*app_context_return));
344    return dpy;
345}
346
347void
348XtDisplayInitialize(
349	XtAppContext app,
350	Display *dpy,
351	_Xconst char* name,
352	_Xconst char* classname,
353	XrmOptionDescRec *urlist,
354	Cardinal num_urs,
355	int *argc,
356	String *argv
357	)
358{
359    XtPerDisplay pd;
360    XrmDatabase db = 0;
361
362    LOCK_APP(app);
363    pd = InitPerDisplay(dpy, app, name, classname);
364    LOCK_PROCESS;
365    if (app->process->globalLangProcRec.proc)
366	/* pre-parse the command line for the language resource */
367	db = _XtPreparseCommandLine(urlist, num_urs, *argc, argv, NULL, NULL,
368				    &pd->language);
369    UNLOCK_PROCESS;
370    _XtDisplayInitialize(dpy, pd, name, urlist, num_urs, argc, argv);
371    if (db) XrmDestroyDatabase(db);
372    UNLOCK_APP(app);
373}
374
375XtAppContext XtCreateApplicationContext(void)
376{
377	XtAppContext app = XtNew(XtAppStruct);
378#ifdef XTHREADS
379	app->lock_info = NULL;
380	app->lock = NULL;
381	app->unlock = NULL;
382	app->yield_lock = NULL;
383	app->restore_lock = NULL;
384	app->free_lock = NULL;
385#endif
386	INIT_APP_LOCK(app);
387	LOCK_APP(app);
388	LOCK_PROCESS;
389	app->process = _XtGetProcessContext();
390	app->next = app->process->appContextList;
391	app->process->appContextList = app;
392	app->langProcRec.proc = app->process->globalLangProcRec.proc;
393	app->langProcRec.closure = app->process->globalLangProcRec.closure;
394	app->destroy_callbacks = NULL;
395	app->list = NULL;
396	app->count = app->max = app->last = 0;
397	app->timerQueue = NULL;
398	app->workQueue = NULL;
399	app->signalQueue = NULL;
400	app->input_list = NULL;
401	app->outstandingQueue = NULL;
402	app->errorDB = NULL;
403	_XtSetDefaultErrorHandlers(&app->errorMsgHandler,
404		&app->warningMsgHandler, &app->errorHandler,
405		&app->warningHandler);
406	app->action_table = NULL;
407	_XtSetDefaultSelectionTimeout(&app->selectionTimeout);
408	_XtSetDefaultConverterTable(&app->converterTable);
409	app->sync = app->being_destroyed = app->error_inited = FALSE;
410	app->in_phase2_destroy = NULL;
411#ifndef USE_POLL
412	FD_ZERO(&app->fds.rmask);
413	FD_ZERO(&app->fds.wmask);
414	FD_ZERO(&app->fds.emask);
415#endif
416	app->fds.nfds = 0;
417	app->input_count = app->input_max = 0;
418	_XtHeapInit(&app->heap);
419	app->fallback_resources = NULL;
420	_XtPopupInitialize(app);
421	app->action_hook_list = NULL;
422	app->block_hook_list = NULL;
423	app->destroy_list_size = app->destroy_count = app->dispatch_level = 0;
424	app->destroy_list = NULL;
425#ifndef NO_IDENTIFY_WINDOWS
426	app->identify_windows = False;
427#endif
428	app->free_bindings = NULL;
429	app->display_name_tried = NULL;
430	app->dpy_destroy_count = 0;
431	app->dpy_destroy_list = NULL;
432	app->exit_flag = FALSE;
433	app->rebuild_fdlist = TRUE;
434	UNLOCK_PROCESS;
435	UNLOCK_APP(app);
436	return app;
437}
438
439void XtAppSetExitFlag (
440    XtAppContext app)
441{
442    LOCK_APP(app);
443    app->exit_flag = TRUE;
444    UNLOCK_APP(app);
445}
446
447Boolean XtAppGetExitFlag (
448    XtAppContext app)
449{
450    Boolean retval;
451    LOCK_APP(app);
452    retval = app->exit_flag;
453    UNLOCK_APP(app);
454    return retval;
455}
456
457static void DestroyAppContext(XtAppContext app)
458{
459	XtAppContext* prev_app;
460
461	prev_app = &app->process->appContextList;
462	while (app->count-- > 0) XtCloseDisplay(app->list[app->count]);
463	if (app->list != NULL) XtFree((char *)app->list);
464	_XtFreeConverterTable(app->converterTable);
465	_XtCacheFlushTag(app, (XtPointer)&app->heap);
466	_XtFreeActions(app->action_table);
467	if (app->destroy_callbacks != NULL) {
468	    XtCallCallbackList((Widget) NULL,
469			       (XtCallbackList)app->destroy_callbacks,
470			       (XtPointer)app);
471	    _XtRemoveAllCallbacks(&app->destroy_callbacks);
472	}
473	while (app->timerQueue) XtRemoveTimeOut((XtIntervalId)app->timerQueue);
474	while (app->workQueue) XtRemoveWorkProc((XtWorkProcId)app->workQueue);
475	while (app->signalQueue) XtRemoveSignal((XtSignalId)app->signalQueue);
476	if (app->input_list) _XtRemoveAllInputs(app);
477	XtFree((char*)app->destroy_list);
478	_XtHeapFree(&app->heap);
479	while (*prev_app != app) prev_app = &(*prev_app)->next;
480	*prev_app = app->next;
481	if (app->process->defaultAppContext == app)
482	    app->process->defaultAppContext = NULL;
483	if (app->free_bindings) _XtDoFreeBindings (app);
484	FREE_APP_LOCK(app);
485	XtFree((char *)app);
486}
487
488static XtAppContext* appDestroyList = NULL;
489int _XtAppDestroyCount = 0;
490
491void XtDestroyApplicationContext(XtAppContext app)
492{
493	LOCK_APP(app);
494	if (app->being_destroyed) {
495	    UNLOCK_APP(app);
496	    return;
497	}
498
499	if (_XtSafeToDestroy(app)) {
500	    LOCK_PROCESS;
501	    DestroyAppContext(app);
502	    UNLOCK_PROCESS;
503	} else {
504	    app->being_destroyed = TRUE;
505	    LOCK_PROCESS;
506	    _XtAppDestroyCount++;
507	    appDestroyList =
508		    (XtAppContext *) XtRealloc((char *) appDestroyList,
509		    (unsigned) (_XtAppDestroyCount * sizeof(XtAppContext)));
510	    appDestroyList[_XtAppDestroyCount-1] = app;
511	    UNLOCK_PROCESS;
512	    UNLOCK_APP(app);
513	}
514}
515
516void _XtDestroyAppContexts(void)
517{
518	int i,ii;
519	XtAppContext apps[8];
520	XtAppContext* pApps;
521
522	pApps = XtStackAlloc (sizeof (XtAppContext) * _XtAppDestroyCount, apps);
523
524	for (i = ii = 0; i < _XtAppDestroyCount; i++) {
525	    if (_XtSafeToDestroy(appDestroyList[i]))
526		DestroyAppContext(appDestroyList[i]);
527	    else
528		pApps[ii++] = appDestroyList[i];
529	}
530	_XtAppDestroyCount = ii;
531	if (_XtAppDestroyCount == 0) {
532	    XtFree((char *) appDestroyList);
533	    appDestroyList = NULL;
534	} else {
535	    for (i = 0; i < ii; i++)
536		appDestroyList[i] = pApps[i];
537	}
538	XtStackFree ((XtPointer) pApps, apps);
539}
540
541XrmDatabase XtDatabase(Display *dpy)
542{
543    XrmDatabase retval;
544    DPY_TO_APPCON(dpy);
545
546    LOCK_APP(app);
547    retval = XrmGetDatabase(dpy);
548    UNLOCK_APP(app);
549    return retval;
550}
551
552PerDisplayTablePtr _XtperDisplayList = NULL;
553
554XtPerDisplay _XtSortPerDisplayList(Display *dpy)
555{
556	register PerDisplayTablePtr pd, opd = NULL;
557
558	LOCK_PROCESS;
559	for (pd = _XtperDisplayList;
560	     pd != NULL && pd->dpy != dpy;
561	     pd = pd->next) {
562	    opd = pd;
563	}
564
565	if (pd == NULL) {
566	    XtErrorMsg(XtNnoPerDisplay, "getPerDisplay", XtCXtToolkitError,
567		    "Couldn't find per display information",
568		    (String *) NULL, (Cardinal *)NULL);
569	}
570
571	if (pd != _XtperDisplayList) {	/* move it to the front */
572	    /* opd points to the previous one... */
573
574	    opd->next = pd->next;
575	    pd->next = _XtperDisplayList;
576	    _XtperDisplayList = pd;
577	}
578	UNLOCK_PROCESS;
579	return &(pd->perDpy);
580}
581
582XtAppContext XtDisplayToApplicationContext(Display *dpy)
583{
584	XtAppContext retval;
585
586	retval = _XtGetPerDisplay(dpy)->appContext;
587	return retval;
588}
589
590static void CloseDisplay(Display *dpy)
591{
592        register XtPerDisplay xtpd;
593	register PerDisplayTablePtr pd, opd = NULL;
594	XrmDatabase db;
595	int i;
596
597	XtDestroyWidget(XtHooksOfDisplay(dpy));
598
599	LOCK_PROCESS;
600	for (pd = _XtperDisplayList;
601	     pd != NULL && pd->dpy != dpy;
602	     pd = pd->next){
603	    opd = pd;
604	}
605
606	if (pd == NULL) {
607	    XtErrorMsg(XtNnoPerDisplay, "closeDisplay", XtCXtToolkitError,
608		    "Couldn't find per display information",
609		    (String *) NULL, (Cardinal *)NULL);
610	}
611
612	if (pd == _XtperDisplayList) _XtperDisplayList = pd->next;
613	else opd->next = pd->next;
614
615	xtpd = &(pd->perDpy);
616
617        if (xtpd != NULL) {
618	    if (xtpd->destroy_callbacks != NULL) {
619		XtCallCallbackList((Widget) NULL,
620				   (XtCallbackList)xtpd->destroy_callbacks,
621				   (XtPointer)xtpd);
622		_XtRemoveAllCallbacks(&xtpd->destroy_callbacks);
623	    }
624	    if (xtpd->mapping_callbacks != NULL)
625		_XtRemoveAllCallbacks(&xtpd->mapping_callbacks);
626	    XtDeleteFromAppContext(dpy, xtpd->appContext);
627	    if (xtpd->keysyms)
628		XFree((char *) xtpd->keysyms);
629            XtFree((char *) xtpd->modKeysyms);
630            XtFree((char *) xtpd->modsToKeysyms);
631            xtpd->keysyms_per_keycode = 0;
632            xtpd->being_destroyed = FALSE;
633            xtpd->keysyms = NULL;
634            xtpd->modKeysyms = NULL;
635            xtpd->modsToKeysyms = NULL;
636	    XDestroyRegion(xtpd->region);
637	    _XtCacheFlushTag(xtpd->appContext, (XtPointer)&xtpd->heap);
638	    _XtGClistFree(dpy, xtpd);
639	    XtFree((char*)xtpd->pdi.trace);
640	    _XtHeapFree(&xtpd->heap);
641	    _XtFreeWWTable(xtpd);
642	    xtpd->per_screen_db[DefaultScreen(dpy)] = (XrmDatabase)NULL;
643	    for (i = ScreenCount(dpy); --i >= 0; ) {
644		db = xtpd->per_screen_db[i];
645		if (db)
646		    XrmDestroyDatabase(db);
647	    }
648	    XtFree((char *)xtpd->per_screen_db);
649	    if ((db = XrmGetDatabase(dpy)))
650		XrmDestroyDatabase(db);
651	    if (xtpd->cmd_db)
652		XrmDestroyDatabase(xtpd->cmd_db);
653	    if (xtpd->server_db)
654		XrmDestroyDatabase(xtpd->server_db);
655	    XtFree(xtpd->language);
656	    if (xtpd->dispatcher_list != NULL)
657		XtFree((char *) xtpd->dispatcher_list);
658	    if (xtpd->ext_select_list != NULL)
659		XtFree((char *) xtpd->ext_select_list);
660        }
661	XtFree((char*)pd);
662	XrmSetDatabase(dpy, (XrmDatabase)NULL);
663	XCloseDisplay(dpy);
664	UNLOCK_PROCESS;
665}
666
667void XtCloseDisplay(Display *dpy)
668{
669	XtPerDisplay pd;
670	XtAppContext app = XtDisplayToApplicationContext(dpy);
671
672	LOCK_APP(app);
673	pd = _XtGetPerDisplay(dpy);
674	if (pd->being_destroyed) {
675	    UNLOCK_APP(app);
676	    return;
677	}
678
679	if (_XtSafeToDestroy(app)) CloseDisplay(dpy);
680	else {
681	    pd->being_destroyed = TRUE;
682	    app->dpy_destroy_count++;
683	    app->dpy_destroy_list = (Display **)
684		XtRealloc((char *) app->dpy_destroy_list,
685		    (unsigned) (app->dpy_destroy_count * sizeof(Display *)));
686	    app->dpy_destroy_list[app->dpy_destroy_count-1] = dpy;
687	}
688	UNLOCK_APP(app);
689}
690
691void _XtCloseDisplays(XtAppContext app)
692{
693	int i;
694
695	LOCK_APP(app);
696	for (i = 0; i < app->dpy_destroy_count; i++) {
697	    CloseDisplay(app->dpy_destroy_list[i]);
698	}
699	app->dpy_destroy_count = 0;
700	XtFree((char *) app->dpy_destroy_list);
701	app->dpy_destroy_list = NULL;
702	UNLOCK_APP(app);
703}
704
705XtAppContext XtWidgetToApplicationContext(Widget w)
706{
707	XtAppContext retval;
708
709	retval = _XtGetPerDisplay(XtDisplayOfObject(w))->appContext;
710	return retval;
711}
712
713
714void XtGetApplicationNameAndClass(
715    Display *dpy,
716    String *name_return,
717    String *class_return)
718{
719    XtPerDisplay pd;
720
721    pd = _XtGetPerDisplay(dpy);
722    *name_return = XrmQuarkToString(pd->name);
723    *class_return = XrmQuarkToString(pd->class);
724}
725
726XtPerDisplay _XtGetPerDisplay (Display* display)
727{
728    XtPerDisplay retval;
729
730    LOCK_PROCESS;
731    retval = ((_XtperDisplayList != NULL &&
732	      _XtperDisplayList->dpy == display)
733	      ? &_XtperDisplayList->perDpy
734	      : _XtSortPerDisplayList(display));
735    UNLOCK_PROCESS;
736    return retval;
737}
738
739XtPerDisplayInputRec* _XtGetPerDisplayInput(Display* display)
740{
741    XtPerDisplayInputRec* retval;
742    LOCK_PROCESS;
743    retval = ((_XtperDisplayList != NULL &&
744	      _XtperDisplayList->dpy == display)
745	      ? &_XtperDisplayList->perDpy.pdi
746	      : &_XtSortPerDisplayList(display)->pdi);
747    UNLOCK_PROCESS;
748    return retval;
749}
750
751void XtGetDisplays(
752    XtAppContext app_context,
753    Display*** dpy_return,
754    Cardinal* num_dpy_return)
755{
756    int ii;
757    LOCK_APP(app_context);
758    *num_dpy_return = app_context->count;
759    *dpy_return = (Display**)__XtMalloc(app_context->count * sizeof(Display*));
760    for (ii = 0; ii < app_context->count; ii++)
761	(*dpy_return)[ii] = app_context->list[ii];
762    UNLOCK_APP(app_context);
763}
764