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