1444c061aSmrg/***********************************************************
2fdf6a26fSmrgCopyright (c) 1993, Oracle and/or its affiliates.
31477040fSmrg
41477040fSmrgPermission is hereby granted, free of charge, to any person obtaining a
51477040fSmrgcopy of this software and associated documentation files (the "Software"),
61477040fSmrgto deal in the Software without restriction, including without limitation
71477040fSmrgthe rights to use, copy, modify, merge, publish, distribute, sublicense,
81477040fSmrgand/or sell copies of the Software, and to permit persons to whom the
91477040fSmrgSoftware is furnished to do so, subject to the following conditions:
101477040fSmrg
111477040fSmrgThe above copyright notice and this permission notice (including the next
121477040fSmrgparagraph) shall be included in all copies or substantial portions of the
131477040fSmrgSoftware.
141477040fSmrg
151477040fSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
161477040fSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
171477040fSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
181477040fSmrgTHE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
191477040fSmrgLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
201477040fSmrgFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
211477040fSmrgDEALINGS IN THE SOFTWARE.
221477040fSmrg
231477040fSmrgCopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
24444c061aSmrg
25444c061aSmrg                        All Rights Reserved
26444c061aSmrg
27444c061aSmrgPermission to use, copy, modify, and distribute this software and its
28444c061aSmrgdocumentation for any purpose and without fee is hereby granted,
29444c061aSmrgprovided that the above copyright notice appear in all copies and that
30444c061aSmrgboth that copyright notice and this permission notice appear in
311477040fSmrgsupporting documentation, and that the name of Digital not be
32444c061aSmrgused in advertising or publicity pertaining to distribution of the
33444c061aSmrgsoftware without specific, written prior permission.
34444c061aSmrg
35444c061aSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
36444c061aSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
37444c061aSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
38444c061aSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
39444c061aSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
40444c061aSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
41444c061aSmrgSOFTWARE.
42444c061aSmrg
43444c061aSmrg******************************************************************/
44444c061aSmrg
45444c061aSmrg/*
46444c061aSmrg
47444c061aSmrgCopyright 1987, 1988, 1998  The Open Group
48444c061aSmrg
49444c061aSmrgPermission to use, copy, modify, distribute, and sell this software and its
50444c061aSmrgdocumentation for any purpose is hereby granted without fee, provided that
51444c061aSmrgthe above copyright notice appear in all copies and that both that
52444c061aSmrgcopyright notice and this permission notice appear in supporting
53444c061aSmrgdocumentation.
54444c061aSmrg
55444c061aSmrgThe above copyright notice and this permission notice shall be included in
56444c061aSmrgall copies or substantial portions of the Software.
57444c061aSmrg
58444c061aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59444c061aSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60444c061aSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
61444c061aSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
62444c061aSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
63444c061aSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
64444c061aSmrg
65444c061aSmrgExcept as contained in this notice, the name of The Open Group shall not be
66444c061aSmrgused in advertising or otherwise to promote the sale, use or other dealings
67444c061aSmrgin this Software without prior written authorization from The Open Group.
68444c061aSmrg
69444c061aSmrg*/
70444c061aSmrg
71444c061aSmrg#ifdef HAVE_CONFIG_H
72444c061aSmrg#include <config.h>
73444c061aSmrg#endif
74444c061aSmrg#include "IntrinsicI.h"
75444c061aSmrg#ifndef X_NO_RESOURCE_CONFIGURATION_MANAGEMENT
76444c061aSmrg#include "ResConfigP.h"
77444c061aSmrg#endif
78444c061aSmrg
79444c061aSmrg#include <stdlib.h>
80444c061aSmrg
81444c061aSmrg#ifdef XTHREADS
82a3bd7f05Smrgvoid (*_XtProcessLock) (void) = NULL;
83a3bd7f05Smrgvoid (*_XtProcessUnlock) (void) = NULL;
84a3bd7f05Smrgvoid (*_XtInitAppLock) (XtAppContext) = NULL;
85444c061aSmrg#endif
86444c061aSmrg
870568f49bSmrgstatic _Xconst _XtString XtNnoPerDisplay = "noPerDisplay";
88444c061aSmrg
89a3bd7f05SmrgProcessContext
90a3bd7f05Smrg_XtGetProcessContext(void)
91444c061aSmrg{
92444c061aSmrg    static ProcessContextRec processContextRec = {
93a3bd7f05Smrg        (XtAppContext) NULL,
94a3bd7f05Smrg        (XtAppContext) NULL,
95a3bd7f05Smrg        (ConverterTable) NULL,
96a3bd7f05Smrg        {(XtLanguageProc) NULL, (XtPointer) NULL}
97444c061aSmrg    };
98444c061aSmrg
99444c061aSmrg    return &processContextRec;
100444c061aSmrg}
101444c061aSmrg
102a3bd7f05SmrgXtAppContext
103a3bd7f05Smrg_XtDefaultAppContext(void)
104444c061aSmrg{
105444c061aSmrg    ProcessContext process = _XtGetProcessContext();
106444c061aSmrg    XtAppContext app;
107444c061aSmrg
108444c061aSmrg    LOCK_PROCESS;
109444c061aSmrg    if (process->defaultAppContext == NULL) {
110a3bd7f05Smrg        process->defaultAppContext = XtCreateApplicationContext();
111444c061aSmrg    }
112444c061aSmrg    app = process->defaultAppContext;
113444c061aSmrg    UNLOCK_PROCESS;
114444c061aSmrg    return app;
115444c061aSmrg}
116444c061aSmrg
117a3bd7f05Smrgstatic void
118a3bd7f05SmrgAddToAppContext(Display *d, XtAppContext app)
119444c061aSmrg{
120444c061aSmrg#define DISPLAYS_TO_ADD 4
121444c061aSmrg
122a3bd7f05Smrg    if (app->count >= app->max) {
123a3bd7f05Smrg        app->max = (short) (app->max + DISPLAYS_TO_ADD);
124fdf6a26fSmrg        app->list = XtReallocArray(app->list,
125fdf6a26fSmrg                                   (Cardinal) app->max,
126fdf6a26fSmrg                                   (Cardinal) sizeof(Display *));
127a3bd7f05Smrg    }
128444c061aSmrg
129a3bd7f05Smrg    app->list[app->count++] = d;
130a3bd7f05Smrg    app->rebuild_fdlist = TRUE;
1310568f49bSmrg#ifdef USE_POLL
132a3bd7f05Smrg    app->fds.nfds++;
1330568f49bSmrg#else
134a3bd7f05Smrg    if (ConnectionNumber(d) + 1 > app->fds.nfds) {
135a3bd7f05Smrg        app->fds.nfds = ConnectionNumber(d) + 1;
136a3bd7f05Smrg    }
137444c061aSmrg#endif
138444c061aSmrg#undef DISPLAYS_TO_ADD
139444c061aSmrg}
140444c061aSmrg
141a3bd7f05Smrgstatic void
142fdf6a26fSmrgXtDeleteFromAppContext(const Display *d, register XtAppContext app)
143444c061aSmrg{
144a3bd7f05Smrg    register int i;
145a3bd7f05Smrg
146a3bd7f05Smrg    for (i = 0; i < app->count; i++)
147a3bd7f05Smrg        if (app->list[i] == d)
148a3bd7f05Smrg            break;
149a3bd7f05Smrg
150a3bd7f05Smrg    if (i < app->count) {
151a3bd7f05Smrg        if (i <= app->last && app->last > 0)
152a3bd7f05Smrg            app->last--;
153a3bd7f05Smrg        for (i++; i < app->count; i++)
154a3bd7f05Smrg            app->list[i - 1] = app->list[i];
155a3bd7f05Smrg        app->count--;
156a3bd7f05Smrg    }
157a3bd7f05Smrg    app->rebuild_fdlist = TRUE;
1580568f49bSmrg#ifdef USE_POLL
159a3bd7f05Smrg    app->fds.nfds--;
1600568f49bSmrg#else
161a3bd7f05Smrg    if ((ConnectionNumber(d) + 1) == app->fds.nfds)
162a3bd7f05Smrg        app->fds.nfds--;
163a3bd7f05Smrg    else                        /* Unnecessary, just to be fool-proof */
164a3bd7f05Smrg        FD_CLR(ConnectionNumber(d), &app->fds.rmask);
165444c061aSmrg#endif
166444c061aSmrg}
167444c061aSmrg
168a3bd7f05Smrgstatic XtPerDisplay
169a3bd7f05SmrgNewPerDisplay(Display *dpy)
170444c061aSmrg{
171a3bd7f05Smrg    PerDisplayTablePtr pd;
172a3bd7f05Smrg
173a3bd7f05Smrg    pd = XtNew(PerDisplayTable);
174a3bd7f05Smrg
175a3bd7f05Smrg    LOCK_PROCESS;
176a3bd7f05Smrg    pd->dpy = dpy;
177a3bd7f05Smrg    pd->next = _XtperDisplayList;
178a3bd7f05Smrg    _XtperDisplayList = pd;
179a3bd7f05Smrg    UNLOCK_PROCESS;
180a3bd7f05Smrg    return &(pd->perDpy);
181444c061aSmrg}
182444c061aSmrg
183a3bd7f05Smrgstatic XtPerDisplay
184a3bd7f05SmrgInitPerDisplay(Display *dpy,
185a3bd7f05Smrg               XtAppContext app,
186a3bd7f05Smrg               _Xconst char *name,
187a3bd7f05Smrg               _Xconst char *classname)
188444c061aSmrg{
189444c061aSmrg    XtPerDisplay pd;
190444c061aSmrg
191444c061aSmrg    AddToAppContext(dpy, app);
192444c061aSmrg
193444c061aSmrg    pd = NewPerDisplay(dpy);
194444c061aSmrg    _XtHeapInit(&pd->heap);
195444c061aSmrg    pd->destroy_callbacks = NULL;
196444c061aSmrg    pd->region = XCreateRegion();
197444c061aSmrg    pd->case_cvt = NULL;
198444c061aSmrg    pd->defaultKeycodeTranslator = XtTranslateKey;
199444c061aSmrg    pd->keysyms_serial = 0;
200444c061aSmrg    pd->keysyms = NULL;
201444c061aSmrg    XDisplayKeycodes(dpy, &pd->min_keycode, &pd->max_keycode);
202444c061aSmrg    pd->modKeysyms = NULL;
203444c061aSmrg    pd->modsToKeysyms = NULL;
204444c061aSmrg    pd->appContext = app;
205444c061aSmrg    pd->name = XrmStringToName(name);
206444c061aSmrg    pd->class = XrmStringToClass(classname);
207444c061aSmrg    pd->being_destroyed = False;
208444c061aSmrg    pd->GClist = NULL;
209444c061aSmrg    pd->pixmap_tab = NULL;
210444c061aSmrg    pd->language = NULL;
211444c061aSmrg    pd->rv = False;
212444c061aSmrg    pd->last_event.xany.serial = 0;
213444c061aSmrg    pd->last_timestamp = 0;
214444c061aSmrg    _XtAllocTMContext(pd);
215444c061aSmrg    pd->mapping_callbacks = NULL;
216444c061aSmrg
217444c061aSmrg    pd->pdi.grabList = NULL;
218444c061aSmrg    pd->pdi.trace = NULL;
219444c061aSmrg    pd->pdi.traceDepth = 0;
220444c061aSmrg    pd->pdi.traceMax = 0;
221444c061aSmrg    pd->pdi.focusWidget = NULL;
222444c061aSmrg    pd->pdi.activatingKey = 0;
223444c061aSmrg    pd->pdi.keyboard.grabType = XtNoServerGrab;
224a3bd7f05Smrg    pd->pdi.pointer.grabType = XtNoServerGrab;
225a3bd7f05Smrg
226444c061aSmrg    _XtAllocWWTable(pd);
227a3bd7f05Smrg    pd->per_screen_db = (XrmDatabase *) __XtCalloc((Cardinal) ScreenCount(dpy),
228a3bd7f05Smrg                                                   (Cardinal)
229a3bd7f05Smrg                                                   sizeof(XrmDatabase));
230a3bd7f05Smrg    pd->cmd_db = (XrmDatabase) NULL;
231a3bd7f05Smrg    pd->server_db = (XrmDatabase) NULL;
232444c061aSmrg    pd->dispatcher_list = NULL;
233444c061aSmrg    pd->ext_select_list = NULL;
234444c061aSmrg    pd->ext_select_count = 0;
235444c061aSmrg    pd->hook_object = NULL;
236444c061aSmrg#if 0
237444c061aSmrg    pd->hook_object = _XtCreate("hooks", "Hooks", hookObjectClass,
238a3bd7f05Smrg                                (Widget) NULL,
239a3bd7f05Smrg                                (Screen *) DefaultScreenOfDisplay(dpy),
240a3bd7f05Smrg                                (ArgList) NULL, 0, (XtTypedArgList) NULL, 0,
241a3bd7f05Smrg                                (ConstraintWidgetClass) NULL);
242444c061aSmrg#endif
243444c061aSmrg
244444c061aSmrg#ifndef X_NO_RESOURCE_CONFIGURATION_MANAGEMENT
245a3bd7f05Smrg    pd->rcm_init = XInternAtom(dpy, RCM_INIT, 0);
246a3bd7f05Smrg    pd->rcm_data = XInternAtom(dpy, RCM_DATA, 0);
247444c061aSmrg#endif
248444c061aSmrg
249444c061aSmrg    return pd;
250444c061aSmrg}
251444c061aSmrg
252a3bd7f05Smrg#define THIS_FUNC "XtOpenDisplay"
253a3bd7f05SmrgDisplay *
254a3bd7f05SmrgXtOpenDisplay(XtAppContext app,
255a3bd7f05Smrg              _Xconst _XtString displayName,
256a3bd7f05Smrg              _Xconst _XtString applName,
257a3bd7f05Smrg              _Xconst _XtString className,
258a3bd7f05Smrg              XrmOptionDescRec *urlist,
259a3bd7f05Smrg              Cardinal num_urs,
260a3bd7f05Smrg              int *argc,
261a3bd7f05Smrg              _XtString *argv)
262444c061aSmrg{
263a3bd7f05Smrg    Display *d;
264a3bd7f05Smrg    XrmDatabase db = NULL;
265a3bd7f05Smrg    String language = NULL;
266a3bd7f05Smrg
267a3bd7f05Smrg    LOCK_APP(app);
268a3bd7f05Smrg    LOCK_PROCESS;
269a3bd7f05Smrg    /* parse the command line for name, display, and/or language */
270a3bd7f05Smrg    db = _XtPreparseCommandLine(urlist, num_urs, *argc, argv,
271a3bd7f05Smrg                                (String *) &applName,
272a3bd7f05Smrg                                (String *) (displayName ? NULL : &displayName),
273a3bd7f05Smrg                                (app->process->globalLangProcRec.proc ?
274a3bd7f05Smrg                                 &language : NULL));
275a3bd7f05Smrg    UNLOCK_PROCESS;
276a3bd7f05Smrg    d = XOpenDisplay(displayName);
277a3bd7f05Smrg    if (d != NULL) {
278a3bd7f05Smrg        if (ScreenCount(d) <= 0) {
279a3bd7f05Smrg            XtErrorMsg("nullDisplay",
280a3bd7f05Smrg                       THIS_FUNC, XtCXtToolkitError,
281a3bd7f05Smrg                       THIS_FUNC " requires a non-NULL display",
282a3bd7f05Smrg                       NULL, NULL);
283a3bd7f05Smrg        }
284a3bd7f05Smrg        if (DefaultScreen(d) < 0 || DefaultScreen(d) >= ScreenCount(d)) {
285a3bd7f05Smrg            XtWarningMsg("nullDisplay",
286a3bd7f05Smrg                         THIS_FUNC, XtCXtToolkitError,
287a3bd7f05Smrg                         THIS_FUNC " default screen is invalid (ignoring)",
288a3bd7f05Smrg                         NULL, NULL);
289a3bd7f05Smrg            DefaultScreen(d) = 0;
290a3bd7f05Smrg        }
291a3bd7f05Smrg    }
292a3bd7f05Smrg
293a3bd7f05Smrg    if (!applName && !(applName = getenv("RESOURCE_NAME"))) {
294a3bd7f05Smrg        if (*argc > 0 && argv[0] && *argv[0]) {
295444c061aSmrg#ifdef WIN32
296a3bd7f05Smrg            char *ptr = strrchr(argv[0], '\\');
297444c061aSmrg#else
298a3bd7f05Smrg            char *ptr = strrchr(argv[0], '/');
299444c061aSmrg#endif
300444c061aSmrg
301a3bd7f05Smrg            if (ptr)
302a3bd7f05Smrg                applName = ++ptr;
303a3bd7f05Smrg            else
304a3bd7f05Smrg                applName = argv[0];
305a3bd7f05Smrg        }
306a3bd7f05Smrg        else
307a3bd7f05Smrg            applName = "main";
308a3bd7f05Smrg    }
309a3bd7f05Smrg
310a3bd7f05Smrg    if (d) {
311a3bd7f05Smrg        XtPerDisplay pd;
312a3bd7f05Smrg
313a3bd7f05Smrg        pd = InitPerDisplay(d, app, applName, className);
314a3bd7f05Smrg        pd->language = language;
315a3bd7f05Smrg        _XtDisplayInitialize(d, pd, applName, urlist, num_urs, argc, argv);
316a3bd7f05Smrg    }
317a3bd7f05Smrg    else {
318a3bd7f05Smrg        int len;
319a3bd7f05Smrg
320a3bd7f05Smrg        displayName = XDisplayName(displayName);
321a3bd7f05Smrg        len = (int) strlen(displayName);
322a3bd7f05Smrg        app->display_name_tried = (_XtString) __XtMalloc((Cardinal) (len + 1));
323a3bd7f05Smrg        strncpy((char *) app->display_name_tried, displayName,
324a3bd7f05Smrg                (size_t) (len + 1));
325a3bd7f05Smrg        app->display_name_tried[len] = '\0';
326a3bd7f05Smrg    }
327a3bd7f05Smrg    if (db)
328a3bd7f05Smrg        XrmDestroyDatabase(db);
329a3bd7f05Smrg    UNLOCK_APP(app);
330a3bd7f05Smrg    return d;
331444c061aSmrg}
332444c061aSmrg
333444c061aSmrgDisplay *
334a3bd7f05Smrg_XtAppInit(XtAppContext *app_context_return,
335a3bd7f05Smrg           String application_class,
336a3bd7f05Smrg           XrmOptionDescRec *options,
337a3bd7f05Smrg           Cardinal num_options,
338a3bd7f05Smrg           int *argc_in_out,
339a3bd7f05Smrg           _XtString **argv_in_out,
340a3bd7f05Smrg           String *fallback_resources)
341444c061aSmrg{
3420568f49bSmrg    _XtString *saved_argv;
343444c061aSmrg    int i;
344444c061aSmrg    Display *dpy;
345444c061aSmrg
346a3bd7f05Smrg    /*
347a3bd7f05Smrg     * Save away argv and argc so we can set the properties later
348a3bd7f05Smrg     */
349fdf6a26fSmrg    saved_argv = XtMallocArray((Cardinal) *argc_in_out + 1,
350fdf6a26fSmrg                               (Cardinal) sizeof(_XtString));
351444c061aSmrg
352a3bd7f05Smrg    for (i = 0; i < *argc_in_out; i++)
353a3bd7f05Smrg        saved_argv[i] = (*argv_in_out)[i];
354a3bd7f05Smrg    saved_argv[i] = NULL;       /* NULL terminate that sucker. */
355444c061aSmrg
356444c061aSmrg    *app_context_return = XtCreateApplicationContext();
357444c061aSmrg
358444c061aSmrg    LOCK_APP((*app_context_return));
359a3bd7f05Smrg    if (fallback_resources)     /* save a procedure call */
360a3bd7f05Smrg        XtAppSetFallbackResources(*app_context_return, fallback_resources);
361444c061aSmrg
3620568f49bSmrg    dpy = XtOpenDisplay(*app_context_return, NULL, NULL,
363a3bd7f05Smrg                        application_class,
364a3bd7f05Smrg                        options, num_options, argc_in_out, *argv_in_out);
365444c061aSmrg
366444c061aSmrg    if (!dpy) {
367a3bd7f05Smrg        String param = (*app_context_return)->display_name_tried;
368a3bd7f05Smrg        Cardinal param_count = 1;
369a3bd7f05Smrg
370a3bd7f05Smrg        XtErrorMsg("invalidDisplay", "xtInitialize", XtCXtToolkitError,
371444c061aSmrg                   "Can't open display: %s", &param, &param_count);
372a3bd7f05Smrg        XtFree((char *) (*app_context_return)->display_name_tried);
373444c061aSmrg    }
374444c061aSmrg    *argv_in_out = saved_argv;
375444c061aSmrg    UNLOCK_APP((*app_context_return));
376444c061aSmrg    return dpy;
377444c061aSmrg}
378444c061aSmrg
379444c061aSmrgvoid
380a3bd7f05SmrgXtDisplayInitialize(XtAppContext app,
381a3bd7f05Smrg                    Display *dpy,
382a3bd7f05Smrg                    _Xconst _XtString name,
383a3bd7f05Smrg                    _Xconst _XtString classname,
384a3bd7f05Smrg                    XrmOptionDescRec *urlist,
385a3bd7f05Smrg                    Cardinal num_urs,
386a3bd7f05Smrg                    int *argc,
387a3bd7f05Smrg                    _XtString *argv)
388444c061aSmrg{
389444c061aSmrg    XtPerDisplay pd;
3902265a131Smrg    XrmDatabase db = NULL;
391444c061aSmrg
392444c061aSmrg    LOCK_APP(app);
393444c061aSmrg    pd = InitPerDisplay(dpy, app, name, classname);
394444c061aSmrg    LOCK_PROCESS;
395444c061aSmrg    if (app->process->globalLangProcRec.proc)
396a3bd7f05Smrg        /* pre-parse the command line for the language resource */
397a3bd7f05Smrg        db = _XtPreparseCommandLine(urlist, num_urs, *argc, argv, NULL, NULL,
398a3bd7f05Smrg                                    &pd->language);
399444c061aSmrg    UNLOCK_PROCESS;
400444c061aSmrg    _XtDisplayInitialize(dpy, pd, name, urlist, num_urs, argc, argv);
401a3bd7f05Smrg    if (db)
402a3bd7f05Smrg        XrmDestroyDatabase(db);
403444c061aSmrg    UNLOCK_APP(app);
404444c061aSmrg}
405444c061aSmrg
406a3bd7f05SmrgXtAppContext
407a3bd7f05SmrgXtCreateApplicationContext(void)
408444c061aSmrg{
409a3bd7f05Smrg    XtAppContext app = XtNew(XtAppStruct);
410a3bd7f05Smrg
411444c061aSmrg#ifdef XTHREADS
412a3bd7f05Smrg    app->lock_info = NULL;
413a3bd7f05Smrg    app->lock = NULL;
414a3bd7f05Smrg    app->unlock = NULL;
415a3bd7f05Smrg    app->yield_lock = NULL;
416a3bd7f05Smrg    app->restore_lock = NULL;
417a3bd7f05Smrg    app->free_lock = NULL;
418444c061aSmrg#endif
419a3bd7f05Smrg    INIT_APP_LOCK(app);
420a3bd7f05Smrg    LOCK_APP(app);
421a3bd7f05Smrg    LOCK_PROCESS;
422a3bd7f05Smrg    app->process = _XtGetProcessContext();
423a3bd7f05Smrg    app->next = app->process->appContextList;
424a3bd7f05Smrg    app->process->appContextList = app;
425a3bd7f05Smrg    app->langProcRec.proc = app->process->globalLangProcRec.proc;
426a3bd7f05Smrg    app->langProcRec.closure = app->process->globalLangProcRec.closure;
427a3bd7f05Smrg    app->destroy_callbacks = NULL;
428a3bd7f05Smrg    app->list = NULL;
429a3bd7f05Smrg    app->count = app->max = app->last = 0;
430a3bd7f05Smrg    app->timerQueue = NULL;
431a3bd7f05Smrg    app->workQueue = NULL;
432a3bd7f05Smrg    app->signalQueue = NULL;
433a3bd7f05Smrg    app->input_list = NULL;
434a3bd7f05Smrg    app->outstandingQueue = NULL;
435a3bd7f05Smrg    app->errorDB = NULL;
436a3bd7f05Smrg    _XtSetDefaultErrorHandlers(&app->errorMsgHandler,
437a3bd7f05Smrg                               &app->warningMsgHandler, &app->errorHandler,
438a3bd7f05Smrg                               &app->warningHandler);
439a3bd7f05Smrg    app->action_table = NULL;
440a3bd7f05Smrg    _XtSetDefaultSelectionTimeout(&app->selectionTimeout);
441a3bd7f05Smrg    _XtSetDefaultConverterTable(&app->converterTable);
442a3bd7f05Smrg    app->sync = app->being_destroyed = app->error_inited = FALSE;
443a3bd7f05Smrg    app->in_phase2_destroy = NULL;
444444c061aSmrg#ifndef USE_POLL
445a3bd7f05Smrg    FD_ZERO(&app->fds.rmask);
446a3bd7f05Smrg    FD_ZERO(&app->fds.wmask);
447a3bd7f05Smrg    FD_ZERO(&app->fds.emask);
448444c061aSmrg#endif
449a3bd7f05Smrg    app->fds.nfds = 0;
450a3bd7f05Smrg    app->input_count = app->input_max = 0;
451a3bd7f05Smrg    _XtHeapInit(&app->heap);
452a3bd7f05Smrg    app->fallback_resources = NULL;
453a3bd7f05Smrg    _XtPopupInitialize(app);
454a3bd7f05Smrg    app->action_hook_list = NULL;
455a3bd7f05Smrg    app->block_hook_list = NULL;
456a3bd7f05Smrg    app->destroy_list_size = app->destroy_count = app->dispatch_level = 0;
457a3bd7f05Smrg    app->destroy_list = NULL;
458444c061aSmrg#ifndef NO_IDENTIFY_WINDOWS
459a3bd7f05Smrg    app->identify_windows = False;
460444c061aSmrg#endif
461a3bd7f05Smrg    app->free_bindings = NULL;
462a3bd7f05Smrg    app->display_name_tried = NULL;
463a3bd7f05Smrg    app->dpy_destroy_count = 0;
464a3bd7f05Smrg    app->dpy_destroy_list = NULL;
465a3bd7f05Smrg    app->exit_flag = FALSE;
466a3bd7f05Smrg    app->rebuild_fdlist = TRUE;
467a3bd7f05Smrg    UNLOCK_PROCESS;
468a3bd7f05Smrg    UNLOCK_APP(app);
469a3bd7f05Smrg    return app;
470444c061aSmrg}
471444c061aSmrg
472a3bd7f05Smrgvoid
473a3bd7f05SmrgXtAppSetExitFlag(XtAppContext app)
474444c061aSmrg{
475444c061aSmrg    LOCK_APP(app);
476444c061aSmrg    app->exit_flag = TRUE;
477444c061aSmrg    UNLOCK_APP(app);
478444c061aSmrg}
479444c061aSmrg
480a3bd7f05SmrgBoolean
481a3bd7f05SmrgXtAppGetExitFlag(XtAppContext app)
482444c061aSmrg{
483444c061aSmrg    Boolean retval;
484a3bd7f05Smrg
485444c061aSmrg    LOCK_APP(app);
486444c061aSmrg    retval = app->exit_flag;
487444c061aSmrg    UNLOCK_APP(app);
488444c061aSmrg    return retval;
489444c061aSmrg}
490444c061aSmrg
491a3bd7f05Smrgstatic void
492a3bd7f05SmrgDestroyAppContext(XtAppContext app)
493444c061aSmrg{
494a3bd7f05Smrg    XtAppContext *prev_app;
495a3bd7f05Smrg
496a3bd7f05Smrg    prev_app = &app->process->appContextList;
497a3bd7f05Smrg    while (app->count-- > 0)
498a3bd7f05Smrg        XtCloseDisplay(app->list[app->count]);
499a3bd7f05Smrg    if (app->list != NULL)
500a3bd7f05Smrg        XtFree((char *) app->list);
501a3bd7f05Smrg    _XtFreeConverterTable(app->converterTable);
502a3bd7f05Smrg    _XtCacheFlushTag(app, (XtPointer) &app->heap);
503a3bd7f05Smrg    _XtFreeActions(app->action_table);
504a3bd7f05Smrg    if (app->destroy_callbacks != NULL) {
505a3bd7f05Smrg        XtCallCallbackList((Widget) NULL,
506a3bd7f05Smrg                           (XtCallbackList) app->destroy_callbacks,
507a3bd7f05Smrg                           (XtPointer) app);
508a3bd7f05Smrg        _XtRemoveAllCallbacks(&app->destroy_callbacks);
509a3bd7f05Smrg    }
510a3bd7f05Smrg    while (app->timerQueue)
511a3bd7f05Smrg        XtRemoveTimeOut((XtIntervalId) app->timerQueue);
512a3bd7f05Smrg    while (app->workQueue)
513a3bd7f05Smrg        XtRemoveWorkProc((XtWorkProcId) app->workQueue);
514a3bd7f05Smrg    while (app->signalQueue)
515a3bd7f05Smrg        XtRemoveSignal((XtSignalId) app->signalQueue);
516a3bd7f05Smrg    if (app->input_list)
517a3bd7f05Smrg        _XtRemoveAllInputs(app);
518a3bd7f05Smrg    XtFree((char *) app->destroy_list);
519a3bd7f05Smrg    _XtHeapFree(&app->heap);
520a3bd7f05Smrg    while (*prev_app != app)
521a3bd7f05Smrg        prev_app = &(*prev_app)->next;
522a3bd7f05Smrg    *prev_app = app->next;
523a3bd7f05Smrg    if (app->process->defaultAppContext == app)
524a3bd7f05Smrg        app->process->defaultAppContext = NULL;
525a3bd7f05Smrg    if (app->free_bindings)
526a3bd7f05Smrg        _XtDoFreeBindings(app);
527a3bd7f05Smrg    FREE_APP_LOCK(app);
528a3bd7f05Smrg    XtFree((char *) app);
529444c061aSmrg}
530444c061aSmrg
531a3bd7f05Smrgstatic XtAppContext *appDestroyList = NULL;
532444c061aSmrgint _XtAppDestroyCount = 0;
533444c061aSmrg
534a3bd7f05Smrgvoid
535a3bd7f05SmrgXtDestroyApplicationContext(XtAppContext app)
536444c061aSmrg{
537a3bd7f05Smrg    LOCK_APP(app);
538a3bd7f05Smrg    if (app->being_destroyed) {
539a3bd7f05Smrg        UNLOCK_APP(app);
540a3bd7f05Smrg        return;
541a3bd7f05Smrg    }
542a3bd7f05Smrg
543a3bd7f05Smrg    if (_XtSafeToDestroy(app)) {
544a3bd7f05Smrg        LOCK_PROCESS;
545a3bd7f05Smrg        DestroyAppContext(app);
546a3bd7f05Smrg        UNLOCK_PROCESS;
547a3bd7f05Smrg    }
548a3bd7f05Smrg    else {
549a3bd7f05Smrg        app->being_destroyed = TRUE;
550a3bd7f05Smrg        LOCK_PROCESS;
551a3bd7f05Smrg        _XtAppDestroyCount++;
552fdf6a26fSmrg        appDestroyList = XtReallocArray(appDestroyList,
553fdf6a26fSmrg                                        (Cardinal) _XtAppDestroyCount,
554fdf6a26fSmrg                                        (Cardinal) sizeof(XtAppContext));
555a3bd7f05Smrg        appDestroyList[_XtAppDestroyCount - 1] = app;
556a3bd7f05Smrg        UNLOCK_PROCESS;
557a3bd7f05Smrg        UNLOCK_APP(app);
558a3bd7f05Smrg    }
559444c061aSmrg}
560444c061aSmrg
561a3bd7f05Smrgvoid
562a3bd7f05Smrg_XtDestroyAppContexts(void)
563444c061aSmrg{
564a3bd7f05Smrg    int i, ii;
565a3bd7f05Smrg    XtAppContext apps[8];
566a3bd7f05Smrg    XtAppContext *pApps;
567a3bd7f05Smrg
568a3bd7f05Smrg    pApps =
569a3bd7f05Smrg        XtStackAlloc(sizeof(XtAppContext) * (size_t) _XtAppDestroyCount, apps);
570a3bd7f05Smrg
571a3bd7f05Smrg    for (i = ii = 0; i < _XtAppDestroyCount; i++) {
572a3bd7f05Smrg        if (_XtSafeToDestroy(appDestroyList[i]))
573a3bd7f05Smrg            DestroyAppContext(appDestroyList[i]);
574a3bd7f05Smrg        else
575a3bd7f05Smrg            pApps[ii++] = appDestroyList[i];
576a3bd7f05Smrg    }
577a3bd7f05Smrg    _XtAppDestroyCount = ii;
578a3bd7f05Smrg    if (_XtAppDestroyCount == 0) {
579a3bd7f05Smrg        XtFree((char *) appDestroyList);
580a3bd7f05Smrg        appDestroyList = NULL;
581a3bd7f05Smrg    }
582a3bd7f05Smrg    else {
583a3bd7f05Smrg        for (i = 0; i < ii; i++)
584a3bd7f05Smrg            appDestroyList[i] = pApps[i];
585a3bd7f05Smrg    }
586a3bd7f05Smrg    XtStackFree((XtPointer) pApps, apps);
587444c061aSmrg}
588444c061aSmrg
589a3bd7f05SmrgXrmDatabase
590a3bd7f05SmrgXtDatabase(Display *dpy)
591444c061aSmrg{
592444c061aSmrg    XrmDatabase retval;
593a3bd7f05Smrg
594444c061aSmrg    DPY_TO_APPCON(dpy);
595444c061aSmrg
596444c061aSmrg    LOCK_APP(app);
597444c061aSmrg    retval = XrmGetDatabase(dpy);
598444c061aSmrg    UNLOCK_APP(app);
599444c061aSmrg    return retval;
600444c061aSmrg}
601444c061aSmrg
602444c061aSmrgPerDisplayTablePtr _XtperDisplayList = NULL;
603444c061aSmrg
604a3bd7f05SmrgXtPerDisplay
605a3bd7f05Smrg_XtSortPerDisplayList(Display *dpy)
606444c061aSmrg{
607a3bd7f05Smrg    register PerDisplayTablePtr pd, opd = NULL;
608a3bd7f05Smrg    XtPerDisplay result = NULL;
609a3bd7f05Smrg
610a3bd7f05Smrg    LOCK_PROCESS;
611a3bd7f05Smrg    for (pd = _XtperDisplayList; pd != NULL && pd->dpy != dpy; pd = pd->next) {
612a3bd7f05Smrg        opd = pd;
613a3bd7f05Smrg    }
614a3bd7f05Smrg
615a3bd7f05Smrg    if (pd == NULL) {
616a3bd7f05Smrg        XtErrorMsg(XtNnoPerDisplay, "getPerDisplay", XtCXtToolkitError,
617a3bd7f05Smrg                   "Couldn't find per display information", NULL, NULL);
618a3bd7f05Smrg    }
619a3bd7f05Smrg    else {
620a3bd7f05Smrg        if (pd != _XtperDisplayList) {  /* move it to the front */
621a3bd7f05Smrg            /* opd points to the previous one... */
622a3bd7f05Smrg
623a3bd7f05Smrg            opd->next = pd->next;
624a3bd7f05Smrg            pd->next = _XtperDisplayList;
625a3bd7f05Smrg            _XtperDisplayList = pd;
626a3bd7f05Smrg        }
627a3bd7f05Smrg        result = &(pd->perDpy);
628a3bd7f05Smrg    }
629a3bd7f05Smrg    UNLOCK_PROCESS;
630a3bd7f05Smrg    return result;
631444c061aSmrg}
632444c061aSmrg
633a3bd7f05SmrgXtAppContext
634a3bd7f05SmrgXtDisplayToApplicationContext(Display *dpy)
635444c061aSmrg{
636a3bd7f05Smrg    XtAppContext retval;
637444c061aSmrg
638a3bd7f05Smrg    retval = _XtGetPerDisplay(dpy)->appContext;
639a3bd7f05Smrg    return retval;
640444c061aSmrg}
641444c061aSmrg
642a3bd7f05Smrgstatic void
643a3bd7f05SmrgCloseDisplay(Display *dpy)
644444c061aSmrg{
645a3bd7f05Smrg    register XtPerDisplay xtpd = NULL;
646a3bd7f05Smrg    register PerDisplayTablePtr pd, opd = NULL;
647a3bd7f05Smrg    XrmDatabase db;
648a3bd7f05Smrg
649a3bd7f05Smrg    XtDestroyWidget(XtHooksOfDisplay(dpy));
650a3bd7f05Smrg
651a3bd7f05Smrg    LOCK_PROCESS;
652a3bd7f05Smrg    for (pd = _XtperDisplayList; pd != NULL && pd->dpy != dpy; pd = pd->next) {
653a3bd7f05Smrg        opd = pd;
654a3bd7f05Smrg    }
655a3bd7f05Smrg
656a3bd7f05Smrg    if (pd == NULL) {
657a3bd7f05Smrg        XtErrorMsg(XtNnoPerDisplay, "closeDisplay", XtCXtToolkitError,
658a3bd7f05Smrg                   "Couldn't find per display information", NULL, NULL);
659a3bd7f05Smrg    }
660a3bd7f05Smrg    else {
661a3bd7f05Smrg
662a3bd7f05Smrg        if (pd == _XtperDisplayList)
663a3bd7f05Smrg            _XtperDisplayList = pd->next;
664a3bd7f05Smrg        else
665a3bd7f05Smrg            opd->next = pd->next;
666a3bd7f05Smrg
667a3bd7f05Smrg        xtpd = &(pd->perDpy);
668a3bd7f05Smrg    }
669a3bd7f05Smrg
670a3bd7f05Smrg    if (xtpd != NULL) {
671a3bd7f05Smrg        int i;
672a3bd7f05Smrg
673a3bd7f05Smrg        if (xtpd->destroy_callbacks != NULL) {
674a3bd7f05Smrg            XtCallCallbackList((Widget) NULL,
675a3bd7f05Smrg                               (XtCallbackList) xtpd->destroy_callbacks,
676a3bd7f05Smrg                               (XtPointer) xtpd);
677a3bd7f05Smrg            _XtRemoveAllCallbacks(&xtpd->destroy_callbacks);
678a3bd7f05Smrg        }
679a3bd7f05Smrg        if (xtpd->mapping_callbacks != NULL)
680a3bd7f05Smrg            _XtRemoveAllCallbacks(&xtpd->mapping_callbacks);
681a3bd7f05Smrg        XtDeleteFromAppContext(dpy, xtpd->appContext);
682a3bd7f05Smrg        if (xtpd->keysyms)
683a3bd7f05Smrg            XFree((char *) xtpd->keysyms);
684a3bd7f05Smrg        XtFree((char *) xtpd->modKeysyms);
685a3bd7f05Smrg        XtFree((char *) xtpd->modsToKeysyms);
686a3bd7f05Smrg        xtpd->keysyms_per_keycode = 0;
687a3bd7f05Smrg        xtpd->being_destroyed = FALSE;
688a3bd7f05Smrg        xtpd->keysyms = NULL;
689a3bd7f05Smrg        xtpd->modKeysyms = NULL;
690a3bd7f05Smrg        xtpd->modsToKeysyms = NULL;
691a3bd7f05Smrg        XDestroyRegion(xtpd->region);
692a3bd7f05Smrg        _XtCacheFlushTag(xtpd->appContext, (XtPointer) &xtpd->heap);
693a3bd7f05Smrg        _XtGClistFree(dpy, xtpd);
694a3bd7f05Smrg        XtFree((char *) xtpd->pdi.trace);
695a3bd7f05Smrg        _XtHeapFree(&xtpd->heap);
696a3bd7f05Smrg        _XtFreeWWTable(xtpd);
697a3bd7f05Smrg        xtpd->per_screen_db[DefaultScreen(dpy)] = (XrmDatabase) NULL;
698a3bd7f05Smrg        for (i = ScreenCount(dpy); --i >= 0;) {
699a3bd7f05Smrg            db = xtpd->per_screen_db[i];
700a3bd7f05Smrg            if (db)
701a3bd7f05Smrg                XrmDestroyDatabase(db);
702444c061aSmrg        }
703a3bd7f05Smrg        XtFree((char *) xtpd->per_screen_db);
704a3bd7f05Smrg        if ((db = XrmGetDatabase(dpy)))
705a3bd7f05Smrg            XrmDestroyDatabase(db);
706a3bd7f05Smrg        if (xtpd->cmd_db)
707a3bd7f05Smrg            XrmDestroyDatabase(xtpd->cmd_db);
708a3bd7f05Smrg        if (xtpd->server_db)
709a3bd7f05Smrg            XrmDestroyDatabase(xtpd->server_db);
710a3bd7f05Smrg        XtFree((_XtString) xtpd->language);
711a3bd7f05Smrg        if (xtpd->dispatcher_list != NULL)
712a3bd7f05Smrg            XtFree((char *) xtpd->dispatcher_list);
713a3bd7f05Smrg        if (xtpd->ext_select_list != NULL)
714a3bd7f05Smrg            XtFree((char *) xtpd->ext_select_list);
715a3bd7f05Smrg    }
716a3bd7f05Smrg    XtFree((char *) pd);
717a3bd7f05Smrg    XrmSetDatabase(dpy, (XrmDatabase) NULL);
718a3bd7f05Smrg    XCloseDisplay(dpy);
719a3bd7f05Smrg    UNLOCK_PROCESS;
720444c061aSmrg}
721444c061aSmrg
722a3bd7f05Smrgvoid
723a3bd7f05SmrgXtCloseDisplay(Display *dpy)
724444c061aSmrg{
725a3bd7f05Smrg    XtPerDisplay pd;
726a3bd7f05Smrg    XtAppContext app = XtDisplayToApplicationContext(dpy);
727a3bd7f05Smrg
728a3bd7f05Smrg    LOCK_APP(app);
729a3bd7f05Smrg    pd = _XtGetPerDisplay(dpy);
730a3bd7f05Smrg    if (pd->being_destroyed) {
731a3bd7f05Smrg        UNLOCK_APP(app);
732a3bd7f05Smrg        return;
733a3bd7f05Smrg    }
734a3bd7f05Smrg
735a3bd7f05Smrg    if (_XtSafeToDestroy(app))
736a3bd7f05Smrg        CloseDisplay(dpy);
737a3bd7f05Smrg    else {
738a3bd7f05Smrg        pd->being_destroyed = TRUE;
739a3bd7f05Smrg        app->dpy_destroy_count++;
740fdf6a26fSmrg        app->dpy_destroy_list = XtReallocArray(app->dpy_destroy_list,
741fdf6a26fSmrg                                               (Cardinal) app->dpy_destroy_count,
742fdf6a26fSmrg                                               (Cardinal) sizeof(Display *));
743a3bd7f05Smrg        app->dpy_destroy_list[app->dpy_destroy_count - 1] = dpy;
744a3bd7f05Smrg    }
745a3bd7f05Smrg    UNLOCK_APP(app);
746444c061aSmrg}
747444c061aSmrg
748a3bd7f05Smrgvoid
749a3bd7f05Smrg_XtCloseDisplays(XtAppContext app)
750444c061aSmrg{
751a3bd7f05Smrg    int i;
752a3bd7f05Smrg
753a3bd7f05Smrg    LOCK_APP(app);
754a3bd7f05Smrg    for (i = 0; i < app->dpy_destroy_count; i++) {
755a3bd7f05Smrg        CloseDisplay(app->dpy_destroy_list[i]);
756a3bd7f05Smrg    }
757a3bd7f05Smrg    app->dpy_destroy_count = 0;
758a3bd7f05Smrg    XtFree((char *) app->dpy_destroy_list);
759a3bd7f05Smrg    app->dpy_destroy_list = NULL;
760a3bd7f05Smrg    UNLOCK_APP(app);
761444c061aSmrg}
762444c061aSmrg
763a3bd7f05SmrgXtAppContext
764a3bd7f05SmrgXtWidgetToApplicationContext(Widget w)
765444c061aSmrg{
766a3bd7f05Smrg    XtAppContext retval;
767444c061aSmrg
768a3bd7f05Smrg    retval = _XtGetPerDisplay(XtDisplayOfObject(w))->appContext;
769a3bd7f05Smrg    return retval;
770444c061aSmrg}
771444c061aSmrg
772a3bd7f05Smrgvoid
773a3bd7f05SmrgXtGetApplicationNameAndClass(Display *dpy,
774a3bd7f05Smrg                             String *name_return,
775a3bd7f05Smrg                             String *class_return)
776444c061aSmrg{
777444c061aSmrg    XtPerDisplay pd;
778444c061aSmrg
779444c061aSmrg    pd = _XtGetPerDisplay(dpy);
780444c061aSmrg    *name_return = XrmQuarkToString(pd->name);
781444c061aSmrg    *class_return = XrmQuarkToString(pd->class);
782444c061aSmrg}
783444c061aSmrg
784a3bd7f05SmrgXtPerDisplay
785a3bd7f05Smrg_XtGetPerDisplay(Display *display)
786444c061aSmrg{
787444c061aSmrg    XtPerDisplay retval;
788444c061aSmrg
789444c061aSmrg    LOCK_PROCESS;
790a3bd7f05Smrg    retval = ((_XtperDisplayList != NULL && _XtperDisplayList->dpy == display)
791a3bd7f05Smrg              ? &_XtperDisplayList->perDpy : _XtSortPerDisplayList(display));
792a3bd7f05Smrg
793444c061aSmrg    UNLOCK_PROCESS;
794444c061aSmrg    return retval;
795444c061aSmrg}
796444c061aSmrg
797a3bd7f05SmrgXtPerDisplayInputRec *
798a3bd7f05Smrg_XtGetPerDisplayInput(Display *display)
799444c061aSmrg{
800a3bd7f05Smrg    XtPerDisplayInputRec *retval;
801a3bd7f05Smrg
802444c061aSmrg    LOCK_PROCESS;
803a3bd7f05Smrg    retval = ((_XtperDisplayList != NULL && _XtperDisplayList->dpy == display)
804a3bd7f05Smrg              ? &_XtperDisplayList->perDpy.pdi
805a3bd7f05Smrg              : &_XtSortPerDisplayList(display)->pdi);
806444c061aSmrg    UNLOCK_PROCESS;
807444c061aSmrg    return retval;
808444c061aSmrg}
809444c061aSmrg
810a3bd7f05Smrgvoid
811a3bd7f05SmrgXtGetDisplays(XtAppContext app_context,
812a3bd7f05Smrg              Display ***dpy_return,
813a3bd7f05Smrg              Cardinal *num_dpy_return)
814444c061aSmrg{
815444c061aSmrg    int ii;
816a3bd7f05Smrg
817444c061aSmrg    LOCK_APP(app_context);
818a3bd7f05Smrg    *num_dpy_return = (Cardinal) app_context->count;
819fdf6a26fSmrg    *dpy_return = XtMallocArray((Cardinal) app_context->count,
820fdf6a26fSmrg                                (Cardinal) sizeof(Display *));
821444c061aSmrg    for (ii = 0; ii < app_context->count; ii++)
822a3bd7f05Smrg        (*dpy_return)[ii] = app_context->list[ii];
823444c061aSmrg    UNLOCK_APP(app_context);
824444c061aSmrg}
825