Home | History | Annotate | Line # | Download | only in src
      1 /***********************************************************
      2 Copyright (c) 1993, Oracle and/or its affiliates.
      3 
      4 Permission is hereby granted, free of charge, to any person obtaining a
      5 copy of this software and associated documentation files (the "Software"),
      6 to deal in the Software without restriction, including without limitation
      7 the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 and/or sell copies of the Software, and to permit persons to whom the
      9 Software is furnished to do so, subject to the following conditions:
     10 
     11 The above copyright notice and this permission notice (including the next
     12 paragraph) shall be included in all copies or substantial portions of the
     13 Software.
     14 
     15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21 DEALINGS IN THE SOFTWARE.
     22 
     23 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
     24 
     25                         All Rights Reserved
     26 
     27 Permission to use, copy, modify, and distribute this software and its
     28 documentation for any purpose and without fee is hereby granted,
     29 provided that the above copyright notice appear in all copies and that
     30 both that copyright notice and this permission notice appear in
     31 supporting documentation, and that the name of Digital not be
     32 used in advertising or publicity pertaining to distribution of the
     33 software without specific, written prior permission.
     34 
     35 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     36 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     37 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     38 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     39 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     40 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     41 SOFTWARE.
     42 
     43 ******************************************************************/
     44 
     45 /*
     46 
     47 Copyright 1987, 1988, 1998  The Open Group
     48 
     49 Permission to use, copy, modify, distribute, and sell this software and its
     50 documentation for any purpose is hereby granted without fee, provided that
     51 the above copyright notice appear in all copies and that both that
     52 copyright notice and this permission notice appear in supporting
     53 documentation.
     54 
     55 The above copyright notice and this permission notice shall be included in
     56 all copies or substantial portions of the Software.
     57 
     58 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     59 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     60 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     61 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     62 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     63 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     64 
     65 Except as contained in this notice, the name of The Open Group shall not be
     66 used in advertising or otherwise to promote the sale, use or other dealings
     67 in 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
     82 void (*_XtProcessLock) (void) = NULL;
     83 void (*_XtProcessUnlock) (void) = NULL;
     84 void (*_XtInitAppLock) (XtAppContext) = NULL;
     85 #endif
     86 
     87 static _Xconst _XtString XtNnoPerDisplay = "noPerDisplay";
     88 
     89 ProcessContext
     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 
    102 XtAppContext
    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 
    117 static void
    118 AddToAppContext(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 = XtReallocArray(app->list,
    125                                    (Cardinal) app->max,
    126                                    (Cardinal) 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 
    141 static void
    142 XtDeleteFromAppContext(const 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 
    168 static XtPerDisplay
    169 NewPerDisplay(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 
    183 static XtPerDisplay
    184 InitPerDisplay(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"
    253 Display *
    254 XtOpenDisplay(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 
    333 Display *
    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 = XtMallocArray((Cardinal) *argc_in_out + 1,
    350                                (Cardinal) sizeof(_XtString));
    351 
    352     for (i = 0; i < *argc_in_out; i++)
    353         saved_argv[i] = (*argv_in_out)[i];
    354     saved_argv[i] = NULL;       /* NULL terminate that sucker. */
    355 
    356     *app_context_return = XtCreateApplicationContext();
    357 
    358     LOCK_APP((*app_context_return));
    359     if (fallback_resources)     /* save a procedure call */
    360         XtAppSetFallbackResources(*app_context_return, fallback_resources);
    361 
    362     dpy = XtOpenDisplay(*app_context_return, NULL, NULL,
    363                         application_class,
    364                         options, num_options, argc_in_out, *argv_in_out);
    365 
    366     if (!dpy) {
    367         String param = (*app_context_return)->display_name_tried;
    368         Cardinal param_count = 1;
    369 
    370         XtErrorMsg("invalidDisplay", "xtInitialize", XtCXtToolkitError,
    371                    "Can't open display: %s", &param, &param_count);
    372         XtFree((char *) (*app_context_return)->display_name_tried);
    373     }
    374     *argv_in_out = saved_argv;
    375     UNLOCK_APP((*app_context_return));
    376     return dpy;
    377 }
    378 
    379 void
    380 XtDisplayInitialize(XtAppContext app,
    381                     Display *dpy,
    382                     _Xconst _XtString name,
    383                     _Xconst _XtString classname,
    384                     XrmOptionDescRec *urlist,
    385                     Cardinal num_urs,
    386                     int *argc,
    387                     _XtString *argv)
    388 {
    389     XtPerDisplay pd;
    390     XrmDatabase db = NULL;
    391 
    392     LOCK_APP(app);
    393     pd = InitPerDisplay(dpy, app, name, classname);
    394     LOCK_PROCESS;
    395     if (app->process->globalLangProcRec.proc)
    396         /* pre-parse the command line for the language resource */
    397         db = _XtPreparseCommandLine(urlist, num_urs, *argc, argv, NULL, NULL,
    398                                     &pd->language);
    399     UNLOCK_PROCESS;
    400     _XtDisplayInitialize(dpy, pd, name, urlist, num_urs, argc, argv);
    401     if (db)
    402         XrmDestroyDatabase(db);
    403     UNLOCK_APP(app);
    404 }
    405 
    406 XtAppContext
    407 XtCreateApplicationContext(void)
    408 {
    409     XtAppContext app = XtNew(XtAppStruct);
    410 
    411 #ifdef XTHREADS
    412     app->lock_info = NULL;
    413     app->lock = NULL;
    414     app->unlock = NULL;
    415     app->yield_lock = NULL;
    416     app->restore_lock = NULL;
    417     app->free_lock = NULL;
    418 #endif
    419     INIT_APP_LOCK(app);
    420     LOCK_APP(app);
    421     LOCK_PROCESS;
    422     app->process = _XtGetProcessContext();
    423     app->next = app->process->appContextList;
    424     app->process->appContextList = app;
    425     app->langProcRec.proc = app->process->globalLangProcRec.proc;
    426     app->langProcRec.closure = app->process->globalLangProcRec.closure;
    427     app->destroy_callbacks = NULL;
    428     app->list = NULL;
    429     app->count = app->max = app->last = 0;
    430     app->timerQueue = NULL;
    431     app->workQueue = NULL;
    432     app->signalQueue = NULL;
    433     app->input_list = NULL;
    434     app->outstandingQueue = NULL;
    435     app->errorDB = NULL;
    436     _XtSetDefaultErrorHandlers(&app->errorMsgHandler,
    437                                &app->warningMsgHandler, &app->errorHandler,
    438                                &app->warningHandler);
    439     app->action_table = NULL;
    440     _XtSetDefaultSelectionTimeout(&app->selectionTimeout);
    441     _XtSetDefaultConverterTable(&app->converterTable);
    442     app->sync = app->being_destroyed = app->error_inited = FALSE;
    443     app->in_phase2_destroy = NULL;
    444 #ifndef USE_POLL
    445     FD_ZERO(&app->fds.rmask);
    446     FD_ZERO(&app->fds.wmask);
    447     FD_ZERO(&app->fds.emask);
    448 #endif
    449     app->fds.nfds = 0;
    450     app->input_count = app->input_max = 0;
    451     _XtHeapInit(&app->heap);
    452     app->fallback_resources = NULL;
    453     _XtPopupInitialize(app);
    454     app->action_hook_list = NULL;
    455     app->block_hook_list = NULL;
    456     app->destroy_list_size = app->destroy_count = app->dispatch_level = 0;
    457     app->destroy_list = NULL;
    458 #ifndef NO_IDENTIFY_WINDOWS
    459     app->identify_windows = False;
    460 #endif
    461     app->free_bindings = NULL;
    462     app->display_name_tried = NULL;
    463     app->dpy_destroy_count = 0;
    464     app->dpy_destroy_list = NULL;
    465     app->exit_flag = FALSE;
    466     app->rebuild_fdlist = TRUE;
    467     UNLOCK_PROCESS;
    468     UNLOCK_APP(app);
    469     return app;
    470 }
    471 
    472 void
    473 XtAppSetExitFlag(XtAppContext app)
    474 {
    475     LOCK_APP(app);
    476     app->exit_flag = TRUE;
    477     UNLOCK_APP(app);
    478 }
    479 
    480 Boolean
    481 XtAppGetExitFlag(XtAppContext app)
    482 {
    483     Boolean retval;
    484 
    485     LOCK_APP(app);
    486     retval = app->exit_flag;
    487     UNLOCK_APP(app);
    488     return retval;
    489 }
    490 
    491 static void
    492 DestroyAppContext(XtAppContext app)
    493 {
    494     XtAppContext *prev_app;
    495 
    496     prev_app = &app->process->appContextList;
    497     while (app->count-- > 0)
    498         XtCloseDisplay(app->list[app->count]);
    499     if (app->list != NULL)
    500         XtFree((char *) app->list);
    501     _XtFreeConverterTable(app->converterTable);
    502     _XtCacheFlushTag(app, (XtPointer) &app->heap);
    503     _XtFreeActions(app->action_table);
    504     if (app->destroy_callbacks != NULL) {
    505         XtCallCallbackList((Widget) NULL,
    506                            (XtCallbackList) app->destroy_callbacks,
    507                            (XtPointer) app);
    508         _XtRemoveAllCallbacks(&app->destroy_callbacks);
    509     }
    510     while (app->timerQueue)
    511         XtRemoveTimeOut((XtIntervalId) app->timerQueue);
    512     while (app->workQueue)
    513         XtRemoveWorkProc((XtWorkProcId) app->workQueue);
    514     while (app->signalQueue)
    515         XtRemoveSignal((XtSignalId) app->signalQueue);
    516     if (app->input_list)
    517         _XtRemoveAllInputs(app);
    518     XtFree((char *) app->destroy_list);
    519     _XtHeapFree(&app->heap);
    520     while (*prev_app != app)
    521         prev_app = &(*prev_app)->next;
    522     *prev_app = app->next;
    523     if (app->process->defaultAppContext == app)
    524         app->process->defaultAppContext = NULL;
    525     if (app->free_bindings)
    526         _XtDoFreeBindings(app);
    527     FREE_APP_LOCK(app);
    528     XtFree((char *) app);
    529 }
    530 
    531 static XtAppContext *appDestroyList = NULL;
    532 int _XtAppDestroyCount = 0;
    533 
    534 void
    535 XtDestroyApplicationContext(XtAppContext app)
    536 {
    537     LOCK_APP(app);
    538     if (app->being_destroyed) {
    539         UNLOCK_APP(app);
    540         return;
    541     }
    542 
    543     if (_XtSafeToDestroy(app)) {
    544         LOCK_PROCESS;
    545         DestroyAppContext(app);
    546         UNLOCK_PROCESS;
    547     }
    548     else {
    549         app->being_destroyed = TRUE;
    550         LOCK_PROCESS;
    551         _XtAppDestroyCount++;
    552         appDestroyList = XtReallocArray(appDestroyList,
    553                                         (Cardinal) _XtAppDestroyCount,
    554                                         (Cardinal) sizeof(XtAppContext));
    555         appDestroyList[_XtAppDestroyCount - 1] = app;
    556         UNLOCK_PROCESS;
    557         UNLOCK_APP(app);
    558     }
    559 }
    560 
    561 void
    562 _XtDestroyAppContexts(void)
    563 {
    564     int i, ii;
    565     XtAppContext apps[8];
    566     XtAppContext *pApps;
    567 
    568     pApps =
    569         XtStackAlloc(sizeof(XtAppContext) * (size_t) _XtAppDestroyCount, apps);
    570 
    571     for (i = ii = 0; i < _XtAppDestroyCount; i++) {
    572         if (_XtSafeToDestroy(appDestroyList[i]))
    573             DestroyAppContext(appDestroyList[i]);
    574         else
    575             pApps[ii++] = appDestroyList[i];
    576     }
    577     _XtAppDestroyCount = ii;
    578     if (_XtAppDestroyCount == 0) {
    579         XtFree((char *) appDestroyList);
    580         appDestroyList = NULL;
    581     }
    582     else {
    583         for (i = 0; i < ii; i++)
    584             appDestroyList[i] = pApps[i];
    585     }
    586     XtStackFree((XtPointer) pApps, apps);
    587 }
    588 
    589 XrmDatabase
    590 XtDatabase(Display *dpy)
    591 {
    592     XrmDatabase retval;
    593 
    594     DPY_TO_APPCON(dpy);
    595 
    596     LOCK_APP(app);
    597     retval = XrmGetDatabase(dpy);
    598     UNLOCK_APP(app);
    599     return retval;
    600 }
    601 
    602 PerDisplayTablePtr _XtperDisplayList = NULL;
    603 
    604 XtPerDisplay
    605 _XtSortPerDisplayList(Display *dpy)
    606 {
    607     register PerDisplayTablePtr pd, opd = NULL;
    608     XtPerDisplay result = NULL;
    609 
    610     LOCK_PROCESS;
    611     for (pd = _XtperDisplayList; pd != NULL && pd->dpy != dpy; pd = pd->next) {
    612         opd = pd;
    613     }
    614 
    615     if (pd == NULL) {
    616         XtErrorMsg(XtNnoPerDisplay, "getPerDisplay", XtCXtToolkitError,
    617                    "Couldn't find per display information", NULL, NULL);
    618     }
    619     else {
    620         if (pd != _XtperDisplayList) {  /* move it to the front */
    621             /* opd points to the previous one... */
    622 
    623             opd->next = pd->next;
    624             pd->next = _XtperDisplayList;
    625             _XtperDisplayList = pd;
    626         }
    627         result = &(pd->perDpy);
    628     }
    629     UNLOCK_PROCESS;
    630     return result;
    631 }
    632 
    633 XtAppContext
    634 XtDisplayToApplicationContext(Display *dpy)
    635 {
    636     XtAppContext retval;
    637 
    638     retval = _XtGetPerDisplay(dpy)->appContext;
    639     return retval;
    640 }
    641 
    642 static void
    643 CloseDisplay(Display *dpy)
    644 {
    645     register XtPerDisplay xtpd = NULL;
    646     register PerDisplayTablePtr pd, opd = NULL;
    647     XrmDatabase db;
    648 
    649     XtDestroyWidget(XtHooksOfDisplay(dpy));
    650 
    651     LOCK_PROCESS;
    652     for (pd = _XtperDisplayList; pd != NULL && pd->dpy != dpy; pd = pd->next) {
    653         opd = pd;
    654     }
    655 
    656     if (pd == NULL) {
    657         XtErrorMsg(XtNnoPerDisplay, "closeDisplay", XtCXtToolkitError,
    658                    "Couldn't find per display information", NULL, NULL);
    659     }
    660     else {
    661 
    662         if (pd == _XtperDisplayList)
    663             _XtperDisplayList = pd->next;
    664         else
    665             opd->next = pd->next;
    666 
    667         xtpd = &(pd->perDpy);
    668     }
    669 
    670     if (xtpd != NULL) {
    671         int i;
    672 
    673         if (xtpd->destroy_callbacks != NULL) {
    674             XtCallCallbackList((Widget) NULL,
    675                                (XtCallbackList) xtpd->destroy_callbacks,
    676                                (XtPointer) xtpd);
    677             _XtRemoveAllCallbacks(&xtpd->destroy_callbacks);
    678         }
    679         if (xtpd->mapping_callbacks != NULL)
    680             _XtRemoveAllCallbacks(&xtpd->mapping_callbacks);
    681         XtDeleteFromAppContext(dpy, xtpd->appContext);
    682         if (xtpd->keysyms)
    683             XFree((char *) xtpd->keysyms);
    684         XtFree((char *) xtpd->modKeysyms);
    685         XtFree((char *) xtpd->modsToKeysyms);
    686         xtpd->keysyms_per_keycode = 0;
    687         xtpd->being_destroyed = FALSE;
    688         xtpd->keysyms = NULL;
    689         xtpd->modKeysyms = NULL;
    690         xtpd->modsToKeysyms = NULL;
    691         XDestroyRegion(xtpd->region);
    692         _XtCacheFlushTag(xtpd->appContext, (XtPointer) &xtpd->heap);
    693         _XtGClistFree(dpy, xtpd);
    694         XtFree((char *) xtpd->pdi.trace);
    695         _XtHeapFree(&xtpd->heap);
    696         _XtFreeWWTable(xtpd);
    697         xtpd->per_screen_db[DefaultScreen(dpy)] = (XrmDatabase) NULL;
    698         for (i = ScreenCount(dpy); --i >= 0;) {
    699             db = xtpd->per_screen_db[i];
    700             if (db)
    701                 XrmDestroyDatabase(db);
    702         }
    703         XtFree((char *) xtpd->per_screen_db);
    704         if ((db = XrmGetDatabase(dpy)))
    705             XrmDestroyDatabase(db);
    706         if (xtpd->cmd_db)
    707             XrmDestroyDatabase(xtpd->cmd_db);
    708         if (xtpd->server_db)
    709             XrmDestroyDatabase(xtpd->server_db);
    710         XtFree((_XtString) xtpd->language);
    711         if (xtpd->dispatcher_list != NULL)
    712             XtFree((char *) xtpd->dispatcher_list);
    713         if (xtpd->ext_select_list != NULL)
    714             XtFree((char *) xtpd->ext_select_list);
    715     }
    716     XtFree((char *) pd);
    717     XrmSetDatabase(dpy, (XrmDatabase) NULL);
    718     XCloseDisplay(dpy);
    719     UNLOCK_PROCESS;
    720 }
    721 
    722 void
    723 XtCloseDisplay(Display *dpy)
    724 {
    725     XtPerDisplay pd;
    726     XtAppContext app = XtDisplayToApplicationContext(dpy);
    727 
    728     LOCK_APP(app);
    729     pd = _XtGetPerDisplay(dpy);
    730     if (pd->being_destroyed) {
    731         UNLOCK_APP(app);
    732         return;
    733     }
    734 
    735     if (_XtSafeToDestroy(app))
    736         CloseDisplay(dpy);
    737     else {
    738         pd->being_destroyed = TRUE;
    739         app->dpy_destroy_count++;
    740         app->dpy_destroy_list = XtReallocArray(app->dpy_destroy_list,
    741                                                (Cardinal) app->dpy_destroy_count,
    742                                                (Cardinal) sizeof(Display *));
    743         app->dpy_destroy_list[app->dpy_destroy_count - 1] = dpy;
    744     }
    745     UNLOCK_APP(app);
    746 }
    747 
    748 void
    749 _XtCloseDisplays(XtAppContext app)
    750 {
    751     int i;
    752 
    753     LOCK_APP(app);
    754     for (i = 0; i < app->dpy_destroy_count; i++) {
    755         CloseDisplay(app->dpy_destroy_list[i]);
    756     }
    757     app->dpy_destroy_count = 0;
    758     XtFree((char *) app->dpy_destroy_list);
    759     app->dpy_destroy_list = NULL;
    760     UNLOCK_APP(app);
    761 }
    762 
    763 XtAppContext
    764 XtWidgetToApplicationContext(Widget w)
    765 {
    766     XtAppContext retval;
    767 
    768     retval = _XtGetPerDisplay(XtDisplayOfObject(w))->appContext;
    769     return retval;
    770 }
    771 
    772 void
    773 XtGetApplicationNameAndClass(Display *dpy,
    774                              String *name_return,
    775                              String *class_return)
    776 {
    777     XtPerDisplay pd;
    778 
    779     pd = _XtGetPerDisplay(dpy);
    780     *name_return = XrmQuarkToString(pd->name);
    781     *class_return = XrmQuarkToString(pd->class);
    782 }
    783 
    784 XtPerDisplay
    785 _XtGetPerDisplay(Display *display)
    786 {
    787     XtPerDisplay retval;
    788 
    789     LOCK_PROCESS;
    790     retval = ((_XtperDisplayList != NULL && _XtperDisplayList->dpy == display)
    791               ? &_XtperDisplayList->perDpy : _XtSortPerDisplayList(display));
    792 
    793     UNLOCK_PROCESS;
    794     return retval;
    795 }
    796 
    797 XtPerDisplayInputRec *
    798 _XtGetPerDisplayInput(Display *display)
    799 {
    800     XtPerDisplayInputRec *retval;
    801 
    802     LOCK_PROCESS;
    803     retval = ((_XtperDisplayList != NULL && _XtperDisplayList->dpy == display)
    804               ? &_XtperDisplayList->perDpy.pdi
    805               : &_XtSortPerDisplayList(display)->pdi);
    806     UNLOCK_PROCESS;
    807     return retval;
    808 }
    809 
    810 void
    811 XtGetDisplays(XtAppContext app_context,
    812               Display ***dpy_return,
    813               Cardinal *num_dpy_return)
    814 {
    815     int ii;
    816 
    817     LOCK_APP(app_context);
    818     *num_dpy_return = (Cardinal) app_context->count;
    819     *dpy_return = XtMallocArray((Cardinal) app_context->count,
    820                                 (Cardinal) sizeof(Display *));
    821     for (ii = 0; ii < app_context->count; ii++)
    822         (*dpy_return)[ii] = app_context->list[ii];
    823     UNLOCK_APP(app_context);
    824 }
    825