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