1 /***********************************************************
2 Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved.
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
_XtGetProcessContext(void)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
_XtDefaultAppContext(void)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
AddToAppContext(Display * d,XtAppContext app)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 = (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 
141 static void
XtDeleteFromAppContext(Display * d,register XtAppContext app)142 XtDeleteFromAppContext(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
NewPerDisplay(Display * dpy)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
InitPerDisplay(Display * dpy,XtAppContext app,_Xconst char * name,_Xconst char * classname)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 *
XtOpenDisplay(XtAppContext app,_Xconst _XtString displayName,_Xconst _XtString applName,_Xconst _XtString className,XrmOptionDescRec * urlist,Cardinal num_urs,int * argc,_XtString * argv)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 *
_XtAppInit(XtAppContext * app_context_return,String application_class,XrmOptionDescRec * options,Cardinal num_options,int * argc_in_out,_XtString ** argv_in_out,String * fallback_resources)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 
380 void
XtDisplayInitialize(XtAppContext app,Display * dpy,_Xconst _XtString name,_Xconst _XtString classname,XrmOptionDescRec * urlist,Cardinal num_urs,int * argc,_XtString * argv)381 XtDisplayInitialize(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 
407 XtAppContext
XtCreateApplicationContext(void)408 XtCreateApplicationContext(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 
473 void
XtAppSetExitFlag(XtAppContext app)474 XtAppSetExitFlag(XtAppContext app)
475 {
476     LOCK_APP(app);
477     app->exit_flag = TRUE;
478     UNLOCK_APP(app);
479 }
480 
481 Boolean
XtAppGetExitFlag(XtAppContext app)482 XtAppGetExitFlag(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 
492 static void
DestroyAppContext(XtAppContext app)493 DestroyAppContext(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 
532 static XtAppContext *appDestroyList = NULL;
533 int _XtAppDestroyCount = 0;
534 
535 void
XtDestroyApplicationContext(XtAppContext app)536 XtDestroyApplicationContext(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 
563 void
_XtDestroyAppContexts(void)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 
591 XrmDatabase
XtDatabase(Display * dpy)592 XtDatabase(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 
604 PerDisplayTablePtr _XtperDisplayList = NULL;
605 
606 XtPerDisplay
_XtSortPerDisplayList(Display * dpy)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 
635 XtAppContext
XtDisplayToApplicationContext(Display * dpy)636 XtDisplayToApplicationContext(Display *dpy)
637 {
638     XtAppContext retval;
639 
640     retval = _XtGetPerDisplay(dpy)->appContext;
641     return retval;
642 }
643 
644 static void
CloseDisplay(Display * dpy)645 CloseDisplay(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 
724 void
XtCloseDisplay(Display * dpy)725 XtCloseDisplay(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 
751 void
_XtCloseDisplays(XtAppContext app)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 
766 XtAppContext
XtWidgetToApplicationContext(Widget w)767 XtWidgetToApplicationContext(Widget w)
768 {
769     XtAppContext retval;
770 
771     retval = _XtGetPerDisplay(XtDisplayOfObject(w))->appContext;
772     return retval;
773 }
774 
775 void
XtGetApplicationNameAndClass(Display * dpy,String * name_return,String * class_return)776 XtGetApplicationNameAndClass(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 
787 XtPerDisplay
_XtGetPerDisplay(Display * display)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 
800 XtPerDisplayInputRec *
_XtGetPerDisplayInput(Display * display)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 
813 void
XtGetDisplays(XtAppContext app_context,Display *** dpy_return,Cardinal * num_dpy_return)814 XtGetDisplays(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