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, 1994, 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/* Make sure all wm properties can make it out of the resource manager */
72444c061aSmrg
73444c061aSmrg#ifdef HAVE_CONFIG_H
74444c061aSmrg#include <config.h>
75444c061aSmrg#endif
76444c061aSmrg#include "IntrinsicI.h"
77444c061aSmrg#include "StringDefs.h"
78444c061aSmrg#include "CoreP.h"
79444c061aSmrg#include "ShellP.h"
80444c061aSmrg#include <stdio.h>
81444c061aSmrg#include <X11/Xlocale.h>
82444c061aSmrg#ifdef XTHREADS
83444c061aSmrg#include <X11/Xthreads.h>
84444c061aSmrg#endif
85444c061aSmrg#ifndef WIN32
86444c061aSmrg#define X_INCLUDE_PWD_H
87444c061aSmrg#define XOS_USE_XT_LOCKING
88444c061aSmrg#include <X11/Xos_r.h>
89444c061aSmrg#endif
90444c061aSmrg
91444c061aSmrg#include <stdlib.h>
92444c061aSmrg
93444c061aSmrg/* some unspecified magic number of expected search levels for Xrm */
94444c061aSmrg#define SEARCH_LIST_SIZE 1000
95444c061aSmrg
96444c061aSmrg/*
97444c061aSmrg This is a set of default records describing the command line arguments that
98444c061aSmrg Xlib will parse and set into the resource data base.
99444c061aSmrg
100444c061aSmrg This list is applied before the users list to enforce these defaults.  This is
101444c061aSmrg policy, which the toolkit avoids but I hate differing programs at this level.
102444c061aSmrg*/
103444c061aSmrg
104a3bd7f05Smrg/* *INDENT-OFF* */
105444c061aSmrgstatic XrmOptionDescRec const opTable[] = {
106a3bd7f05Smrg{"+rv",               "*reverseVideo",     XrmoptionNoArg,   (XtPointer) "off"},
107a3bd7f05Smrg{"+synchronous",      "*synchronous",      XrmoptionNoArg,   (XtPointer) "off"},
108a3bd7f05Smrg{"-background",       "*background",       XrmoptionSepArg,  (XtPointer) NULL},
109a3bd7f05Smrg{"-bd",               "*borderColor",      XrmoptionSepArg,  (XtPointer) NULL},
110a3bd7f05Smrg{"-bg",               "*background",       XrmoptionSepArg,  (XtPointer) NULL},
111a3bd7f05Smrg{"-bordercolor",      "*borderColor",      XrmoptionSepArg,  (XtPointer) NULL},
112a3bd7f05Smrg{"-borderwidth",      ".borderWidth",      XrmoptionSepArg,  (XtPointer) NULL},
113a3bd7f05Smrg{"-bw",               ".borderWidth",      XrmoptionSepArg,  (XtPointer) NULL},
114a3bd7f05Smrg{"-display",          ".display",          XrmoptionSepArg,  (XtPointer) NULL},
115a3bd7f05Smrg{"-fg",               "*foreground",       XrmoptionSepArg,  (XtPointer) NULL},
116a3bd7f05Smrg{"-fn",               "*font",             XrmoptionSepArg,  (XtPointer) NULL},
117a3bd7f05Smrg{"-font",             "*font",             XrmoptionSepArg,  (XtPointer) NULL},
118a3bd7f05Smrg{"-foreground",       "*foreground",       XrmoptionSepArg,  (XtPointer) NULL},
119a3bd7f05Smrg{"-geometry",         ".geometry",         XrmoptionSepArg,  (XtPointer) NULL},
120a3bd7f05Smrg{"-iconic",           ".iconic",           XrmoptionNoArg,   (XtPointer) "on"},
121a3bd7f05Smrg{"-name",             ".name",             XrmoptionSepArg,  (XtPointer) NULL},
122a3bd7f05Smrg{"-reverse",          "*reverseVideo",     XrmoptionNoArg,   (XtPointer) "on"},
123a3bd7f05Smrg{"-rv",               "*reverseVideo",     XrmoptionNoArg,   (XtPointer) "on"},
124a3bd7f05Smrg{"-selectionTimeout", ".selectionTimeout", XrmoptionSepArg,  (XtPointer) NULL},
125a3bd7f05Smrg{"-synchronous",      "*synchronous",      XrmoptionNoArg,   (XtPointer) "on"},
126a3bd7f05Smrg{"-title",            ".title",            XrmoptionSepArg,  (XtPointer) NULL},
127a3bd7f05Smrg{"-xnllanguage",      ".xnlLanguage",      XrmoptionSepArg,  (XtPointer) NULL},
128a3bd7f05Smrg{"-xrm",              NULL,                XrmoptionResArg,  (XtPointer) NULL},
129a3bd7f05Smrg{"-xtsessionID",      ".sessionID",        XrmoptionSepArg,  (XtPointer) NULL},
130444c061aSmrg};
131a3bd7f05Smrg/* *INDENT-ON* */
132444c061aSmrg
133444c061aSmrg/*
134444c061aSmrg * GetHostname - emulates gethostname() on non-bsd systems.
135444c061aSmrg */
136444c061aSmrg
137a3bd7f05Smrgstatic void
138a3bd7f05SmrgGetHostname(char *buf, int maxlen)
139444c061aSmrg{
140444c061aSmrg    if (maxlen <= 0 || buf == NULL)
141a3bd7f05Smrg        return;
142444c061aSmrg
143444c061aSmrg    buf[0] = '\0';
144a3bd7f05Smrg    (void) gethostname(buf, (size_t) maxlen);
145a3bd7f05Smrg    buf[maxlen - 1] = '\0';
146444c061aSmrg}
147444c061aSmrg
148444c061aSmrg
1492265a131Smrg#if defined (WIN32) || defined(__CYGWIN__)
150444c061aSmrg/*
151444c061aSmrg * The Symbol _XtInherit is used in two different manners.
152444c061aSmrg * First it could be used as a generic function and second
153444c061aSmrg * as an absolute address reference, which will be used to
154444c061aSmrg * check the initialisation process of several other libraries.
155fdf6a26fSmrg * Because of this the symbol must be accessible by all
156444c061aSmrg * client dll's and applications.  In unix environments
157444c061aSmrg * this is no problem, because the used shared libraries
158fdf6a26fSmrg * format (elf) supports this immediately.  Under Windows
159444c061aSmrg * this isn't true, because a functions address in a dll
160444c061aSmrg * is different from the same function in another dll or
161444c061aSmrg * applications, because the used Portable Executable
162444c061aSmrg * File adds a code stub to each client to provide the
163444c061aSmrg * exported symbol name.  This stub uses an indirect
164444c061aSmrg * pointer to get the original symbol address, which is
165444c061aSmrg * then jumped to, like in this example:
166444c061aSmrg *
167444c061aSmrg * --- client ---                                     --- dll ----
168444c061aSmrg *  ...
169444c061aSmrg *  call foo
170444c061aSmrg *
171444c061aSmrg * foo: jmp (*_imp_foo)               ---->           foo: ....
172444c061aSmrg *      nop
173444c061aSmrg *      nop
174444c061aSmrg *
175444c061aSmrg * _imp_foo: .long <index of foo in dll export table, is
176a3bd7f05Smrg *                  set to the real address by the runtime linker>
177444c061aSmrg *
178444c061aSmrg * Now it is clear why the clients symbol foo isn't the same
179444c061aSmrg * as in the dll and we can think about how to deal which
180444c061aSmrg * this two above mentioned requirements, to export this
181444c061aSmrg * symbol to all clients and to allow calling this symbol
182444c061aSmrg * as a function.  The solution I've used exports the
183444c061aSmrg * symbol _XtInherit as data symbol, because global data
184444c061aSmrg * symbols are exported to all clients.  But how to deal
185444c061aSmrg * with the second requirement, that this symbol should
186444c061aSmrg * be used as function.  The Trick is to build a little
187444c061aSmrg * code stub in the data section in the exact manner as
188444c061aSmrg * above explained.  This is done with the assembler code
189444c061aSmrg * below.
190444c061aSmrg *
191444c061aSmrg * Ralf Habacker
192444c061aSmrg *
193444c061aSmrg * References:
194444c061aSmrg * msdn          http://msdn.microsoft.com/msdnmag/issues/02/02/PE/PE.asp
195444c061aSmrg * cygwin-xfree: http://www.cygwin.com/ml/cygwin-xfree/2003-10/msg00000.html
196444c061aSmrg */
197444c061aSmrg
198339a7c43Smrg#ifdef __x86_64__
199a3bd7f05Smrgasm(".section .trampoline, \"dwx\" \n\
200339a7c43Smrg .globl _XtInherit        \n\
201339a7c43Smrg _XtInherit:              \n\
202339a7c43Smrg    jmp *_y(%rip)         \n\
203339a7c43Smrg_y: .quad __XtInherit     \n\
204339a7c43Smrg    .text                 \n");
205339a7c43Smrg#else
206a3bd7f05Smrgasm(".data\n\
207444c061aSmrg .globl __XtInherit        \n\
208444c061aSmrg __XtInherit:      jmp *_y \n\
209444c061aSmrg  _y: .long ___XtInherit   \n\
210444c061aSmrg    .text                 \n");
211339a7c43Smrg#endif
212444c061aSmrg
213444c061aSmrg#define _XtInherit __XtInherit
214444c061aSmrg#endif
215444c061aSmrg
216a3bd7f05Smrgvoid
217a3bd7f05Smrg_XtInherit(void)
218444c061aSmrg{
219a3bd7f05Smrg    XtErrorMsg("invalidProcedure", "inheritanceProc", XtCXtToolkitError,
220a3bd7f05Smrg               "Unresolved inheritance operation", NULL, NULL);
221444c061aSmrg}
222444c061aSmrg
223a3bd7f05Smrgvoid
224a3bd7f05SmrgXtToolkitInitialize(void)
225444c061aSmrg{
226444c061aSmrg    static Boolean initialized = False;
227444c061aSmrg
228444c061aSmrg    LOCK_PROCESS;
229444c061aSmrg    if (initialized) {
230a3bd7f05Smrg        UNLOCK_PROCESS;
231a3bd7f05Smrg        return;
232444c061aSmrg    }
233444c061aSmrg    initialized = True;
234444c061aSmrg    UNLOCK_PROCESS;
235444c061aSmrg    /* Resource management initialization */
236444c061aSmrg    XrmInitialize();
237444c061aSmrg    _XtResourceListInitialize();
238444c061aSmrg
239fdf6a26fSmrg    /* Other intrinsic initialization */
240444c061aSmrg    _XtConvertInitialize();
241444c061aSmrg    _XtEventInitialize();
242444c061aSmrg    _XtTranslateInitialize();
243444c061aSmrg
244444c061aSmrg    /* Some apps rely on old (broken) XtAppPeekEvent behavior */
245a3bd7f05Smrg    if (getenv("XTAPPPEEKEVENT_SKIPTIMER"))
246a3bd7f05Smrg        XtAppPeekEvent_SkipTimer = True;
247444c061aSmrg    else
248a3bd7f05Smrg        XtAppPeekEvent_SkipTimer = False;
249444c061aSmrg}
250444c061aSmrg
251a3bd7f05SmrgString
252a3bd7f05Smrg_XtGetUserName(_XtString dest, int len)
253444c061aSmrg{
254444c061aSmrg#ifdef WIN32
255444c061aSmrg    String ptr = NULL;
256444c061aSmrg
257444c061aSmrg    if ((ptr = getenv("USERNAME"))) {
258a3bd7f05Smrg        (void) strncpy(dest, ptr, len - 1);
259a3bd7f05Smrg        dest[len - 1] = '\0';
260a3bd7f05Smrg    }
261a3bd7f05Smrg    else
262a3bd7f05Smrg        *dest = '\0';
263444c061aSmrg#else
264444c061aSmrg#ifdef X_NEEDS_PWPARAMS
265444c061aSmrg    _Xgetpwparams pwparams;
266444c061aSmrg#endif
267444c061aSmrg    struct passwd *pw;
268a3bd7f05Smrg    char *ptr;
269444c061aSmrg
270444c061aSmrg    if ((ptr = getenv("USER"))) {
271a3bd7f05Smrg        (void) strncpy(dest, ptr, (size_t) (len - 1));
272a3bd7f05Smrg        dest[len - 1] = '\0';
273a3bd7f05Smrg    }
274a3bd7f05Smrg    else {
275a3bd7f05Smrg        if ((pw = _XGetpwuid(getuid(), pwparams)) != NULL) {
276a3bd7f05Smrg            (void) strncpy(dest, pw->pw_name, (size_t) (len - 1));
277a3bd7f05Smrg            dest[len - 1] = '\0';
278a3bd7f05Smrg        }
279a3bd7f05Smrg        else
280a3bd7f05Smrg            *dest = '\0';
281444c061aSmrg    }
282444c061aSmrg#endif
283444c061aSmrg    return dest;
284444c061aSmrg}
285444c061aSmrg
286a3bd7f05Smrgstatic String
287a3bd7f05SmrgGetRootDirName(_XtString dest, int len)
288444c061aSmrg{
289444c061aSmrg#ifdef WIN32
290444c061aSmrg    register char *ptr1;
291444c061aSmrg    register char *ptr2 = NULL;
292444c061aSmrg    int len1 = 0, len2 = 0;
293444c061aSmrg
294a3bd7f05Smrg    if (ptr1 = getenv("HOME")) {        /* old, deprecated */
295a3bd7f05Smrg        len1 = strlen(ptr1);
296a3bd7f05Smrg    }
297a3bd7f05Smrg    else if ((ptr1 = getenv("HOMEDRIVE")) && (ptr2 = getenv("HOMEDIR"))) {
298a3bd7f05Smrg        len1 = strlen(ptr1);
299a3bd7f05Smrg        len2 = strlen(ptr2);
300a3bd7f05Smrg    }
301a3bd7f05Smrg    else if (ptr2 = getenv("USERNAME")) {
302a3bd7f05Smrg        len1 = strlen(ptr1 = "/users/");
303a3bd7f05Smrg        len2 = strlen(ptr2);
304444c061aSmrg    }
305444c061aSmrg    if ((len1 + len2 + 1) < len)
306a3bd7f05Smrg        sprintf(dest, "%s%s", ptr1, (ptr2) ? ptr2 : "");
307444c061aSmrg    else
308a3bd7f05Smrg        *dest = '\0';
309444c061aSmrg#else
310444c061aSmrg#ifdef X_NEEDS_PWPARAMS
311444c061aSmrg    _Xgetpwparams pwparams;
312444c061aSmrg#endif
313444c061aSmrg    static char *ptr;
314444c061aSmrg
315444c061aSmrg    if (len <= 0 || dest == NULL)
316a3bd7f05Smrg        return NULL;
317444c061aSmrg
318444c061aSmrg    if ((ptr = getenv("HOME"))) {
319a3bd7f05Smrg        (void) strncpy(dest, ptr, (size_t) (len - 1));
320a3bd7f05Smrg        dest[len - 1] = '\0';
321a3bd7f05Smrg    }
322a3bd7f05Smrg    else {
3230568f49bSmrg        struct passwd *pw;
324a3bd7f05Smrg
325a3bd7f05Smrg        if ((ptr = getenv("USER")))
326a3bd7f05Smrg            pw = _XGetpwnam(ptr, pwparams);
327a3bd7f05Smrg        else
328a3bd7f05Smrg            pw = _XGetpwuid(getuid(), pwparams);
329a3bd7f05Smrg        if (pw != NULL) {
330a3bd7f05Smrg            (void) strncpy(dest, pw->pw_dir, (size_t) (len - 1));
331a3bd7f05Smrg            dest[len - 1] = '\0';
332a3bd7f05Smrg        }
333a3bd7f05Smrg        else
334a3bd7f05Smrg            *dest = '\0';
335444c061aSmrg    }
336444c061aSmrg#endif
337444c061aSmrg    return dest;
338444c061aSmrg}
339444c061aSmrg
340a3bd7f05Smrgstatic void
341a3bd7f05SmrgCombineAppUserDefaults(Display *dpy, XrmDatabase *pdb)
342444c061aSmrg{
343a3bd7f05Smrg    char *filename;
344a3bd7f05Smrg    char *path = NULL;
345444c061aSmrg    Boolean deallocate = False;
346444c061aSmrg
347444c061aSmrg    if (!(path = getenv("XUSERFILESEARCHPATH"))) {
3482265a131Smrg#if !defined(WIN32) || !defined(__MINGW32__)
349a3bd7f05Smrg        char *old_path;
350a3bd7f05Smrg        char homedir[PATH_MAX];
351a3bd7f05Smrg
352a3bd7f05Smrg        GetRootDirName(homedir, PATH_MAX);
353a3bd7f05Smrg        if (!(old_path = getenv("XAPPLRESDIR"))) {
354a3bd7f05Smrg            XtAsprintf(&path,
355a3bd7f05Smrg                       "%s/%%L/%%N%%C:%s/%%l/%%N%%C:%s/%%N%%C:%s/%%L/%%N:%s/%%l/%%N:%s/%%N",
356a3bd7f05Smrg                       homedir, homedir, homedir, homedir, homedir, homedir);
357a3bd7f05Smrg        }
358a3bd7f05Smrg        else {
359a3bd7f05Smrg            XtAsprintf(&path,
360a3bd7f05Smrg                       "%s/%%L/%%N%%C:%s/%%l/%%N%%C:%s/%%N%%C:%s/%%N%%C:%s/%%L/%%N:%s/%%l/%%N:%s/%%N:%s/%%N",
361a3bd7f05Smrg                       old_path, old_path, old_path, homedir,
362a3bd7f05Smrg                       old_path, old_path, old_path, homedir);
363a3bd7f05Smrg        }
364a3bd7f05Smrg        deallocate = True;
3652265a131Smrg#endif
366444c061aSmrg    }
367444c061aSmrg
368444c061aSmrg    filename = XtResolvePathname(dpy, NULL, NULL, NULL, path, NULL, 0, NULL);
369444c061aSmrg    if (filename) {
370a3bd7f05Smrg        (void) XrmCombineFileDatabase(filename, pdb, False);
371a3bd7f05Smrg        XtFree(filename);
372444c061aSmrg    }
373444c061aSmrg
374bdf0f55dSmrg    if (deallocate)
375a3bd7f05Smrg        XtFree(path);
376444c061aSmrg}
377444c061aSmrg
378a3bd7f05Smrgstatic void
379a3bd7f05SmrgCombineUserDefaults(Display *dpy, XrmDatabase *pdb)
380444c061aSmrg{
381444c061aSmrg    char *dpy_defaults = XResourceManagerString(dpy);
382444c061aSmrg
383444c061aSmrg    if (dpy_defaults) {
384a3bd7f05Smrg        XrmCombineDatabase(XrmGetStringDatabase(dpy_defaults), pdb, False);
385a3bd7f05Smrg    }
386a3bd7f05Smrg    else {
3870568f49bSmrg#ifdef __MINGW32__
388a3bd7f05Smrg        const char *slashDotXdefaults = "/Xdefaults";
3890568f49bSmrg#else
390a3bd7f05Smrg        const char *slashDotXdefaults = "/.Xdefaults";
3910568f49bSmrg#endif
392a3bd7f05Smrg        char filename[PATH_MAX];
393a3bd7f05Smrg
394a3bd7f05Smrg        (void) GetRootDirName(filename,
395a3bd7f05Smrg                              PATH_MAX - (int) strlen(slashDotXdefaults) - 1);
396a3bd7f05Smrg        (void) strcat(filename, slashDotXdefaults);
397a3bd7f05Smrg        (void) XrmCombineFileDatabase(filename, pdb, False);
398444c061aSmrg    }
399444c061aSmrg}
400444c061aSmrg
401a3bd7f05Smrgstatic Bool
402a3bd7f05SmrgStoreDBEntry(XrmDatabase *db _X_UNUSED,
403a3bd7f05Smrg             XrmBindingList bindings,
404a3bd7f05Smrg             XrmQuarkList quarks,
405a3bd7f05Smrg             XrmRepresentation *type,
406a3bd7f05Smrg             XrmValuePtr value,
407a3bd7f05Smrg             XPointer data)
408444c061aSmrg{
409a3bd7f05Smrg    XrmQPutResource((XrmDatabase *) data, bindings, quarks, *type, value);
410444c061aSmrg    return False;
411444c061aSmrg}
412444c061aSmrg
413a3bd7f05Smrgstatic XrmDatabase
414a3bd7f05SmrgCopyDB(XrmDatabase db)
415444c061aSmrg{
416444c061aSmrg    XrmDatabase copy = NULL;
417444c061aSmrg    XrmQuark empty = NULLQUARK;
418444c061aSmrg
419444c061aSmrg    XrmEnumerateDatabase(db, &empty, &empty, XrmEnumAllLevels,
420a3bd7f05Smrg                         StoreDBEntry, (XPointer) &copy);
421444c061aSmrg    return copy;
422444c061aSmrg}
423444c061aSmrg
424a3bd7f05Smrgstatic String
425a3bd7f05Smrg_XtDefaultLanguageProc(Display *dpy _X_UNUSED,
426a3bd7f05Smrg                       String xnl,
427a3bd7f05Smrg                       XtPointer closure _X_UNUSED)
428444c061aSmrg{
429a3bd7f05Smrg    if (!setlocale(LC_ALL, xnl))
430a3bd7f05Smrg        XtWarning("locale not supported by C library, locale unchanged");
431444c061aSmrg
432a3bd7f05Smrg    if (!XSupportsLocale()) {
433a3bd7f05Smrg        XtWarning("locale not supported by Xlib, locale set to C");
434a3bd7f05Smrg        setlocale(LC_ALL, "C");
435444c061aSmrg    }
436a3bd7f05Smrg    if (!XSetLocaleModifiers(""))
437a3bd7f05Smrg        XtWarning("X locale modifiers not supported, using default");
438444c061aSmrg
439a3bd7f05Smrg    return setlocale(LC_ALL, NULL);     /* re-query in case overwritten */
440444c061aSmrg}
441444c061aSmrg
442a3bd7f05SmrgXtLanguageProc
443a3bd7f05SmrgXtSetLanguageProc(XtAppContext app, XtLanguageProc proc, XtPointer closure)
444444c061aSmrg{
445a3bd7f05Smrg    XtLanguageProc old;
446444c061aSmrg
447444c061aSmrg    if (!proc) {
448a3bd7f05Smrg        proc = _XtDefaultLanguageProc;
449a3bd7f05Smrg        closure = NULL;
450444c061aSmrg    }
451444c061aSmrg
452444c061aSmrg    if (app) {
453a3bd7f05Smrg        LOCK_APP(app);
454a3bd7f05Smrg        LOCK_PROCESS;
455a3bd7f05Smrg        /* set langProcRec only for this application context */
456444c061aSmrg        old = app->langProcRec.proc;
457444c061aSmrg        app->langProcRec.proc = proc;
458444c061aSmrg        app->langProcRec.closure = closure;
459a3bd7f05Smrg        UNLOCK_PROCESS;
460a3bd7f05Smrg        UNLOCK_APP(app);
461a3bd7f05Smrg    }
462a3bd7f05Smrg    else {
463a3bd7f05Smrg        /* set langProcRec for all application contexts */
464444c061aSmrg        ProcessContext process;
465444c061aSmrg
466a3bd7f05Smrg        LOCK_PROCESS;
467444c061aSmrg        process = _XtGetProcessContext();
468444c061aSmrg        old = process->globalLangProcRec.proc;
469a3bd7f05Smrg        process->globalLangProcRec.proc = proc;
470a3bd7f05Smrg        process->globalLangProcRec.closure = closure;
471444c061aSmrg        app = process->appContextList;
472444c061aSmrg        while (app) {
473444c061aSmrg            app->langProcRec.proc = proc;
474444c061aSmrg            app->langProcRec.closure = closure;
475a3bd7f05Smrg            app = app->next;
476444c061aSmrg        }
477a3bd7f05Smrg        UNLOCK_PROCESS;
478444c061aSmrg    }
479444c061aSmrg    return (old ? old : _XtDefaultLanguageProc);
480444c061aSmrg}
481444c061aSmrg
482a3bd7f05SmrgXrmDatabase
483a3bd7f05SmrgXtScreenDatabase(Screen *screen)
484444c061aSmrg{
485444c061aSmrg    int scrno;
486444c061aSmrg    Bool doing_def;
487444c061aSmrg    XrmDatabase db, olddb;
488444c061aSmrg    XtPerDisplay pd;
489444c061aSmrg    Status do_fallback;
490444c061aSmrg    char *scr_resources;
491444c061aSmrg    Display *dpy = DisplayOfScreen(screen);
492a3bd7f05Smrg
493444c061aSmrg    DPY_TO_APPCON(dpy);
494a3bd7f05Smrg    if (dpy == NULL) {
495a3bd7f05Smrg        XtErrorMsg("nullDisplay",
496a3bd7f05Smrg                   "XtScreenDatabase", XtCXtToolkitError,
497a3bd7f05Smrg                   "XtScreenDatabase requires a non-NULL display",
498a3bd7f05Smrg                   NULL, NULL);
499a3bd7f05Smrg    }
500444c061aSmrg
501444c061aSmrg    LOCK_APP(app);
502444c061aSmrg    LOCK_PROCESS;
503444c061aSmrg    if (screen == DefaultScreenOfDisplay(dpy)) {
504a3bd7f05Smrg        scrno = DefaultScreen(dpy);
505a3bd7f05Smrg        doing_def = True;
506a3bd7f05Smrg    }
507a3bd7f05Smrg    else {
508a3bd7f05Smrg        scrno = XScreenNumberOfScreen(screen);
509a3bd7f05Smrg        doing_def = False;
510444c061aSmrg    }
511444c061aSmrg    pd = _XtGetPerDisplay(dpy);
512444c061aSmrg    if ((db = pd->per_screen_db[scrno])) {
513a3bd7f05Smrg        UNLOCK_PROCESS;
514a3bd7f05Smrg        UNLOCK_APP(app);
515a3bd7f05Smrg        return (doing_def ? XrmGetDatabase(dpy) : db);
516444c061aSmrg    }
517444c061aSmrg    scr_resources = XScreenResourceString(screen);
518444c061aSmrg
519444c061aSmrg    if (ScreenCount(dpy) == 1) {
520a3bd7f05Smrg        db = pd->cmd_db;
521a3bd7f05Smrg        pd->cmd_db = NULL;
522a3bd7f05Smrg    }
523a3bd7f05Smrg    else {
524a3bd7f05Smrg        db = CopyDB(pd->cmd_db);
525444c061aSmrg    }
526a3bd7f05Smrg    {                           /* Environment defaults */
527a3bd7f05Smrg        char filenamebuf[PATH_MAX];
528a3bd7f05Smrg        char *filename;
529a3bd7f05Smrg
530a3bd7f05Smrg        if (!(filename = getenv("XENVIRONMENT"))) {
531a3bd7f05Smrg            int len;
532444c061aSmrg
5332265a131Smrg#ifdef __MINGW32__
534a3bd7f05Smrg            const char *slashDotXdefaultsDash = "/Xdefaults-";
5352265a131Smrg#else
536a3bd7f05Smrg            const char *slashDotXdefaultsDash = "/.Xdefaults-";
5372265a131Smrg#endif
538444c061aSmrg
539a3bd7f05Smrg            (void) GetRootDirName(filename = filenamebuf,
540a3bd7f05Smrg                                  PATH_MAX -
541a3bd7f05Smrg                                  (int) strlen(slashDotXdefaultsDash) - 1);
542a3bd7f05Smrg            (void) strcat(filename, slashDotXdefaultsDash);
543a3bd7f05Smrg            len = (int) strlen(filename);
544a3bd7f05Smrg            GetHostname(filename + len, PATH_MAX - len);
545a3bd7f05Smrg        }
546a3bd7f05Smrg        (void) XrmCombineFileDatabase(filename, &db, False);
547444c061aSmrg    }
548a3bd7f05Smrg    if (scr_resources) {        /* Screen defaults */
549a3bd7f05Smrg        XrmCombineDatabase(XrmGetStringDatabase(scr_resources), &db, False);
550a3bd7f05Smrg        XFree(scr_resources);
551444c061aSmrg    }
552444c061aSmrg    /* Server or host defaults */
553444c061aSmrg    if (!pd->server_db)
554a3bd7f05Smrg        CombineUserDefaults(dpy, &db);
555444c061aSmrg    else {
556a3bd7f05Smrg        (void) XrmCombineDatabase(pd->server_db, &db, False);
557a3bd7f05Smrg        pd->server_db = NULL;
558444c061aSmrg    }
559444c061aSmrg
560444c061aSmrg    if (!db)
561a3bd7f05Smrg        db = XrmGetStringDatabase("");
562444c061aSmrg    pd->per_screen_db[scrno] = db;
563444c061aSmrg    olddb = XrmGetDatabase(dpy);
564444c061aSmrg    /* set database now, for XtResolvePathname to use */
565444c061aSmrg    XrmSetDatabase(dpy, db);
566444c061aSmrg    CombineAppUserDefaults(dpy, &db);
567444c061aSmrg    do_fallback = 1;
568a3bd7f05Smrg    {                           /* System app-defaults */
569a3bd7f05Smrg        char *filename;
570a3bd7f05Smrg
571a3bd7f05Smrg        if ((filename = XtResolvePathname(dpy, "app-defaults",
572a3bd7f05Smrg                                          NULL, NULL, NULL, NULL, 0, NULL))) {
573a3bd7f05Smrg            do_fallback = !XrmCombineFileDatabase(filename, &db, False);
574a3bd7f05Smrg            XtFree(filename);
575a3bd7f05Smrg        }
576444c061aSmrg    }
577444c061aSmrg    /* now restore old database, if need be */
578444c061aSmrg    if (!doing_def)
579a3bd7f05Smrg        XrmSetDatabase(dpy, olddb);
580a3bd7f05Smrg    if (do_fallback && pd->appContext->fallback_resources) {    /* Fallback defaults */
581444c061aSmrg        XrmDatabase fdb = NULL;
582a3bd7f05Smrg        String *res;
583444c061aSmrg
584a3bd7f05Smrg        for (res = pd->appContext->fallback_resources; *res; res++)
585a3bd7f05Smrg            XrmPutLineResource(&fdb, *res);
586a3bd7f05Smrg        (void) XrmCombineDatabase(fdb, &db, False);
587444c061aSmrg    }
588444c061aSmrg    UNLOCK_PROCESS;
589444c061aSmrg    UNLOCK_APP(app);
590444c061aSmrg    return db;
591444c061aSmrg}
592444c061aSmrg
593444c061aSmrg/*
594444c061aSmrg * Merge two option tables, allowing the second to over-ride the first,
595444c061aSmrg * so that ambiguous abbreviations can be noticed.  The merge attempts
596444c061aSmrg * to make the resulting table lexicographically sorted, but succeeds
597444c061aSmrg * only if the first source table is sorted.  Though it _is_ recommended
598444c061aSmrg * (for optimizations later in XrmParseCommand), it is not required
599444c061aSmrg * that either source table be sorted.
600444c061aSmrg *
601444c061aSmrg * Caller is responsible for freeing the returned option table.
602444c061aSmrg */
603444c061aSmrg
604a3bd7f05Smrgstatic void
605a3bd7f05Smrg_MergeOptionTables(const XrmOptionDescRec *src1,
606a3bd7f05Smrg                   Cardinal num_src1,
607a3bd7f05Smrg                   const XrmOptionDescRec *src2,
608a3bd7f05Smrg                   Cardinal num_src2,
609a3bd7f05Smrg                   XrmOptionDescRec **dst,
610a3bd7f05Smrg                   Cardinal *num_dst)
611444c061aSmrg{
612444c061aSmrg    XrmOptionDescRec *table, *endP;
6130568f49bSmrg    XrmOptionDescRec *opt1, *dstP;
6140568f49bSmrg    const XrmOptionDescRec *opt2;
615444c061aSmrg    int i1;
616444c061aSmrg    Cardinal i2;
617444c061aSmrg    int dst_len, order;
618a3bd7f05Smrg    enum { Check, NotSorted, IsSorted } sort_order = Check;
619444c061aSmrg
620fdf6a26fSmrg    *dst = table = XtMallocArray(num_src1 + num_src2,
621fdf6a26fSmrg                                 (Cardinal) sizeof(XrmOptionDescRec));
622444c061aSmrg
623fdf6a26fSmrg    (void) memcpy(table, src1, sizeof(XrmOptionDescRec) * num_src1);
624444c061aSmrg    if (num_src2 == 0) {
625a3bd7f05Smrg        *num_dst = num_src1;
626a3bd7f05Smrg        return;
627444c061aSmrg    }
628a3bd7f05Smrg    endP = &table[dst_len = (int) num_src1];
629a3bd7f05Smrg    for (opt2 = src2, i2 = 0; i2 < num_src2; opt2++, i2++) {
6300568f49bSmrg        XrmOptionDescRec *whereP;
6310568f49bSmrg        Boolean found;
6320568f49bSmrg
633a3bd7f05Smrg        found = False;
634a3bd7f05Smrg        whereP = endP - 1;      /* assume new option goes at the end */
635a3bd7f05Smrg        for (opt1 = table, i1 = 0; i1 < dst_len; opt1++, i1++) {
636a3bd7f05Smrg            /* have to walk the entire new table so new list is ordered
637a3bd7f05Smrg               (if src1 was ordered) */
638a3bd7f05Smrg            if (sort_order == Check && i1 > 0
639a3bd7f05Smrg                && strcmp(opt1->option, (opt1 - 1)->option) < 0)
640a3bd7f05Smrg                sort_order = NotSorted;
641a3bd7f05Smrg            if ((order = strcmp(opt1->option, opt2->option)) == 0) {
642a3bd7f05Smrg                /* same option names; just overwrite opt1 with opt2 */
643a3bd7f05Smrg                *opt1 = *opt2;
644a3bd7f05Smrg                found = True;
645a3bd7f05Smrg                break;
646a3bd7f05Smrg            }
647a3bd7f05Smrg            /* else */
648a3bd7f05Smrg            if (sort_order == IsSorted && order > 0) {
649a3bd7f05Smrg                /* insert before opt1 to preserve order */
650a3bd7f05Smrg                /* shift rest of table forward to make room for new entry */
651a3bd7f05Smrg                for (dstP = endP++; dstP > opt1; dstP--)
652a3bd7f05Smrg                    *dstP = *(dstP - 1);
653a3bd7f05Smrg                *opt1 = *opt2;
654a3bd7f05Smrg                dst_len++;
655a3bd7f05Smrg                found = True;
656a3bd7f05Smrg                break;
657a3bd7f05Smrg            }
658a3bd7f05Smrg            /* else */
659a3bd7f05Smrg            if (order < 0)
660a3bd7f05Smrg                /* opt2 sorts after opt1, so remember this position */
661a3bd7f05Smrg                whereP = opt1;
662a3bd7f05Smrg        }
663a3bd7f05Smrg        if (sort_order == Check && i1 == dst_len)
664a3bd7f05Smrg            sort_order = IsSorted;
665a3bd7f05Smrg        if (!found) {
666a3bd7f05Smrg            /* when we get here, whereP points to the last entry in the
667a3bd7f05Smrg               destination that sorts before "opt2".  Shift rest of table
668a3bd7f05Smrg               forward and insert "opt2" after whereP. */
669a3bd7f05Smrg            whereP++;
670a3bd7f05Smrg            for (dstP = endP++; dstP > whereP; dstP--)
671a3bd7f05Smrg                *dstP = *(dstP - 1);
672a3bd7f05Smrg            *whereP = *opt2;
673a3bd7f05Smrg            dst_len++;
674a3bd7f05Smrg        }
675444c061aSmrg    }
676a3bd7f05Smrg    *num_dst = (Cardinal) dst_len;
677444c061aSmrg}
678444c061aSmrg
679444c061aSmrg/* NOTE: name, class, and type must be permanent strings */
680a3bd7f05Smrgstatic Boolean
681a3bd7f05Smrg_GetResource(Display *dpy,
682a3bd7f05Smrg             XrmSearchList list,
683a3bd7f05Smrg             String name,
684a3bd7f05Smrg             String class,
685a3bd7f05Smrg             String type,
686a3bd7f05Smrg             XrmValue *value)
687444c061aSmrg{
688444c061aSmrg    XrmRepresentation db_type;
689444c061aSmrg    XrmValue db_value;
690444c061aSmrg    XrmName Qname = XrmPermStringToQuark(name);
691444c061aSmrg    XrmClass Qclass = XrmPermStringToQuark(class);
692444c061aSmrg    XrmRepresentation Qtype = XrmPermStringToQuark(type);
693444c061aSmrg
694444c061aSmrg    if (XrmQGetSearchResource(list, Qname, Qclass, &db_type, &db_value)) {
695a3bd7f05Smrg        if (db_type == Qtype) {
696a3bd7f05Smrg            if (Qtype == _XtQString)
697a3bd7f05Smrg                *(String *) value->addr = db_value.addr;
698a3bd7f05Smrg            else
699fdf6a26fSmrg                (void) memcpy(value->addr, db_value.addr, value->size);
700a3bd7f05Smrg            return True;
701a3bd7f05Smrg        }
702a3bd7f05Smrg        else {
703a3bd7f05Smrg            WidgetRec widget;   /* hack, hack */
704a3bd7f05Smrg
705a3bd7f05Smrg            memset(&widget, 0, sizeof(widget));
706a3bd7f05Smrg            widget.core.self = &widget;
707a3bd7f05Smrg            widget.core.widget_class = coreWidgetClass;
708a3bd7f05Smrg            widget.core.screen = (Screen *) DefaultScreenOfDisplay(dpy);
709a3bd7f05Smrg            XtInitializeWidgetClass(coreWidgetClass);
710a3bd7f05Smrg            if (_XtConvert(&widget, db_type, &db_value, Qtype, value, NULL)) {
711a3bd7f05Smrg                return True;
712a3bd7f05Smrg            }
713a3bd7f05Smrg        }
714444c061aSmrg    }
715444c061aSmrg    return False;
716444c061aSmrg}
717444c061aSmrg
718a3bd7f05SmrgXrmDatabase
719a3bd7f05Smrg_XtPreparseCommandLine(XrmOptionDescRec *urlist,
720a3bd7f05Smrg                       Cardinal num_urs,
721a3bd7f05Smrg                       int argc,
722a3bd7f05Smrg                       _XtString *argv, /* return */
723a3bd7f05Smrg                       String *applName,
724a3bd7f05Smrg                       String *displayName,
725a3bd7f05Smrg                       String *language)
726444c061aSmrg{
7272265a131Smrg    XrmDatabase db = NULL;
728444c061aSmrg    XrmOptionDescRec *options;
729444c061aSmrg    Cardinal num_options;
730444c061aSmrg    XrmName name_list[3];
731444c061aSmrg    XrmName class_list[3];
732444c061aSmrg    XrmRepresentation type;
733444c061aSmrg    XrmValue val;
7340568f49bSmrg    _XtString *targv;
735444c061aSmrg    int targc = argc;
736444c061aSmrg
737fdf6a26fSmrg    targv = XtMallocArray((Cardinal) argc, (Cardinal) sizeof(_XtString *));
738fdf6a26fSmrg    (void) memcpy(targv, argv, sizeof(char *) * (size_t) argc);
739444c061aSmrg    _MergeOptionTables(opTable, XtNumber(opTable), urlist, num_urs,
740a3bd7f05Smrg                       &options, &num_options);
741444c061aSmrg    name_list[0] = class_list[0] = XrmPermStringToQuark(".");
742444c061aSmrg    name_list[2] = class_list[2] = NULLQUARK;
7430568f49bSmrg    XrmParseCommand(&db, options, (int) num_options, ".", &targc, targv);
744444c061aSmrg    if (applName) {
745a3bd7f05Smrg        name_list[1] = XrmPermStringToQuark("name");
746a3bd7f05Smrg        if (XrmQGetResource(db, name_list, name_list, &type, &val) &&
747a3bd7f05Smrg            type == _XtQString)
748a3bd7f05Smrg            *applName = val.addr;
749444c061aSmrg    }
750444c061aSmrg    if (displayName) {
751a3bd7f05Smrg        name_list[1] = XrmPermStringToQuark("display");
752a3bd7f05Smrg        if (XrmQGetResource(db, name_list, name_list, &type, &val) &&
753a3bd7f05Smrg            type == _XtQString)
754a3bd7f05Smrg            *displayName = val.addr;
755444c061aSmrg    }
756444c061aSmrg    if (language) {
757a3bd7f05Smrg        name_list[1] = XrmPermStringToQuark("xnlLanguage");
758a3bd7f05Smrg        class_list[1] = XrmPermStringToQuark("XnlLanguage");
759a3bd7f05Smrg        if (XrmQGetResource(db, name_list, class_list, &type, &val) &&
760a3bd7f05Smrg            type == _XtQString)
761a3bd7f05Smrg            *language = val.addr;
762444c061aSmrg    }
763444c061aSmrg
764a3bd7f05Smrg    XtFree((char *) targv);
765a3bd7f05Smrg    XtFree((char *) options);
766444c061aSmrg    return db;
767444c061aSmrg}
768444c061aSmrg
769a3bd7f05Smrgstatic void
770a3bd7f05SmrgGetLanguage(Display *dpy, XtPerDisplay pd)
771444c061aSmrg{
772444c061aSmrg    XrmRepresentation type;
773444c061aSmrg    XrmValue value;
774444c061aSmrg    XrmName name_list[3];
775444c061aSmrg    XrmName class_list[3];
776444c061aSmrg
777444c061aSmrg    LOCK_PROCESS;
778a3bd7f05Smrg    if (!pd->language) {
779a3bd7f05Smrg        name_list[0] = pd->name;
780a3bd7f05Smrg        name_list[1] = XrmPermStringToQuark("xnlLanguage");
781a3bd7f05Smrg        class_list[0] = pd->class;
782a3bd7f05Smrg        class_list[1] = XrmPermStringToQuark("XnlLanguage");
783a3bd7f05Smrg        name_list[2] = class_list[2] = NULLQUARK;
784a3bd7f05Smrg        if (!pd->server_db)
785a3bd7f05Smrg            CombineUserDefaults(dpy, &pd->server_db);
786a3bd7f05Smrg        if (pd->server_db &&
787a3bd7f05Smrg            XrmQGetResource(pd->server_db, name_list, class_list, &type, &value)
788a3bd7f05Smrg            && type == _XtQString)
789a3bd7f05Smrg            pd->language = (char *) value.addr;
790444c061aSmrg    }
791444c061aSmrg
792444c061aSmrg    if (pd->appContext->langProcRec.proc) {
793a3bd7f05Smrg        if (!pd->language)
794a3bd7f05Smrg            pd->language = "";
795a3bd7f05Smrg        pd->language = (*pd->appContext->langProcRec.proc)
796a3bd7f05Smrg            (dpy, pd->language, pd->appContext->langProcRec.closure);
797444c061aSmrg    }
798a3bd7f05Smrg    else if (!pd->language || pd->language[0] == '\0')  /* R4 compatibility */
799a3bd7f05Smrg        pd->language = getenv("LANG");
800444c061aSmrg
801a3bd7f05Smrg    if (pd->language)
802a3bd7f05Smrg        pd->language = XtNewString(pd->language);
803444c061aSmrg    UNLOCK_PROCESS;
804444c061aSmrg}
805444c061aSmrg
806a3bd7f05Smrgstatic void
807a3bd7f05SmrgProcessInternalConnection(XtPointer client_data,
808a3bd7f05Smrg                          int *fd,
809a3bd7f05Smrg                          XtInputId *id _X_UNUSED)
810444c061aSmrg{
811a3bd7f05Smrg    XProcessInternalConnection((Display *) client_data, *fd);
812444c061aSmrg}
813444c061aSmrg
814a3bd7f05Smrgstatic void
815a3bd7f05SmrgConnectionWatch(Display *dpy,
816a3bd7f05Smrg                XPointer client_data,
817a3bd7f05Smrg                int fd,
818a3bd7f05Smrg                Bool opening,
819a3bd7f05Smrg                XPointer *watch_data)
820444c061aSmrg{
821a3bd7f05Smrg    XtInputId *iptr;
822444c061aSmrg    XtAppContext app = XtDisplayToApplicationContext(dpy);
823444c061aSmrg
824444c061aSmrg    if (opening) {
825a3bd7f05Smrg        iptr = (XtInputId *) __XtMalloc(sizeof(XtInputId));
826a3bd7f05Smrg        *iptr = XtAppAddInput(app, fd, (XtPointer) XtInputReadMask,
827a3bd7f05Smrg                              ProcessInternalConnection, client_data);
828a3bd7f05Smrg        *watch_data = (XPointer) iptr;
829a3bd7f05Smrg    }
830a3bd7f05Smrg    else {
831a3bd7f05Smrg        iptr = (XtInputId *) *watch_data;
832a3bd7f05Smrg        XtRemoveInput(*iptr);
833444c061aSmrg        (void) XtFree(*watch_data);
834444c061aSmrg    }
835444c061aSmrg}
836444c061aSmrg
837a3bd7f05Smrgvoid
838a3bd7f05Smrg_XtDisplayInitialize(Display *dpy,
839a3bd7f05Smrg                     XtPerDisplay pd,
840a3bd7f05Smrg                     _Xconst char *name,
841a3bd7f05Smrg                     XrmOptionDescRec *urlist,
842a3bd7f05Smrg                     Cardinal num_urs,
843a3bd7f05Smrg                     int *argc,
844a3bd7f05Smrg                     char **argv)
845444c061aSmrg{
846a3bd7f05Smrg    Boolean tmp_bool;
847a3bd7f05Smrg    XrmValue value;
848a3bd7f05Smrg    XrmOptionDescRec *options;
849a3bd7f05Smrg    Cardinal num_options;
850a3bd7f05Smrg    XrmDatabase db;
851a3bd7f05Smrg    XrmName name_list[2];
852a3bd7f05Smrg    XrmClass class_list[2];
853a3bd7f05Smrg    XrmHashTable *search_list;
854a3bd7f05Smrg    int search_list_size = SEARCH_LIST_SIZE;
855a3bd7f05Smrg
856a3bd7f05Smrg    GetLanguage(dpy, pd);
857a3bd7f05Smrg
858a3bd7f05Smrg    /* Parse the command line and remove Xt arguments from argv */
859a3bd7f05Smrg    _MergeOptionTables(opTable, XtNumber(opTable), urlist, num_urs,
860a3bd7f05Smrg                       &options, &num_options);
861a3bd7f05Smrg    XrmParseCommand(&pd->cmd_db, options, (int) num_options, name, argc, argv);
862a3bd7f05Smrg
863a3bd7f05Smrg    db = XtScreenDatabase(DefaultScreenOfDisplay(dpy));
864a3bd7f05Smrg
865a3bd7f05Smrg    if (!(search_list = (XrmHashTable *)
866a3bd7f05Smrg          ALLOCATE_LOCAL(SEARCH_LIST_SIZE * sizeof(XrmHashTable))))
867a3bd7f05Smrg        _XtAllocError(NULL);
868a3bd7f05Smrg    name_list[0] = pd->name;
869a3bd7f05Smrg    class_list[0] = pd->class;
870a3bd7f05Smrg    name_list[1] = NULLQUARK;
871a3bd7f05Smrg    class_list[1] = NULLQUARK;
872a3bd7f05Smrg
873a3bd7f05Smrg    while (!XrmQGetSearchList(db, name_list, class_list,
874a3bd7f05Smrg                              search_list, search_list_size)) {
875a3bd7f05Smrg        XrmHashTable *old = search_list;
876a3bd7f05Smrg        Cardinal size =
877a3bd7f05Smrg            (Cardinal) ((size_t) (search_list_size *= 2) *
878a3bd7f05Smrg                        sizeof(XrmHashTable));
879a3bd7f05Smrg        if (!(search_list = (XrmHashTable *) ALLOCATE_LOCAL(size)))
880a3bd7f05Smrg            _XtAllocError(NULL);
881fdf6a26fSmrg        (void) memcpy(search_list, old, (size >> 1));
882a3bd7f05Smrg        DEALLOCATE_LOCAL(old);
883a3bd7f05Smrg    }
884a3bd7f05Smrg
885a3bd7f05Smrg    value.size = sizeof(tmp_bool);
886a3bd7f05Smrg    value.addr = (XtPointer) &tmp_bool;
887a3bd7f05Smrg    if (_GetResource(dpy, search_list, "synchronous", "Synchronous",
888a3bd7f05Smrg                     XtRBoolean, &value)) {
889a3bd7f05Smrg        int i;
890a3bd7f05Smrg        Display **dpyP = pd->appContext->list;
891a3bd7f05Smrg
892a3bd7f05Smrg        pd->appContext->sync = tmp_bool;
893a3bd7f05Smrg        for (i = pd->appContext->count; i; dpyP++, i--) {
894a3bd7f05Smrg            (void) XSynchronize(*dpyP, (Bool) tmp_bool);
895a3bd7f05Smrg        }
896a3bd7f05Smrg    }
897a3bd7f05Smrg    else {
898a3bd7f05Smrg        (void) XSynchronize(dpy, (Bool) pd->appContext->sync);
899a3bd7f05Smrg    }
900a3bd7f05Smrg
901a3bd7f05Smrg    if (_GetResource(dpy, search_list, "reverseVideo", "ReverseVideo",
902a3bd7f05Smrg                     XtRBoolean, &value)
903a3bd7f05Smrg        && tmp_bool) {
904a3bd7f05Smrg        pd->rv = True;
905a3bd7f05Smrg    }
906a3bd7f05Smrg
907a3bd7f05Smrg    value.size = sizeof(pd->multi_click_time);
908a3bd7f05Smrg    value.addr = (XtPointer) &pd->multi_click_time;
909a3bd7f05Smrg    if (!_GetResource(dpy, search_list,
910a3bd7f05Smrg                      "multiClickTime", "MultiClickTime", XtRInt, &value)) {
911a3bd7f05Smrg        pd->multi_click_time = 200;
912a3bd7f05Smrg    }
913a3bd7f05Smrg
914a3bd7f05Smrg    value.size = sizeof(pd->appContext->selectionTimeout);
915a3bd7f05Smrg    value.addr = (XtPointer) &pd->appContext->selectionTimeout;
916a3bd7f05Smrg    (void) _GetResource(dpy, search_list,
917a3bd7f05Smrg                        "selectionTimeout", "SelectionTimeout", XtRInt, &value);
918444c061aSmrg
919444c061aSmrg#ifndef NO_IDENTIFY_WINDOWS
920a3bd7f05Smrg    value.size = sizeof(pd->appContext->identify_windows);
921a3bd7f05Smrg    value.addr = (XtPointer) &pd->appContext->identify_windows;
922a3bd7f05Smrg    (void) _GetResource(dpy, search_list,
923a3bd7f05Smrg                        "xtIdentifyWindows", "XtDebug", XtRBoolean, &value);
924444c061aSmrg#endif
925444c061aSmrg
926a3bd7f05Smrg    XAddConnectionWatch(dpy, ConnectionWatch, (XPointer) dpy);
927444c061aSmrg
928a3bd7f05Smrg    XtFree((XtPointer) options);
929a3bd7f05Smrg    DEALLOCATE_LOCAL(search_list);
930444c061aSmrg}
931444c061aSmrg
932a3bd7f05Smrg/*      Function Name: XtAppSetFallbackResources
933a3bd7f05Smrg *      Description: Sets the fallback resource list that will be loaded
934444c061aSmrg *                   at display initialization time.
935a3bd7f05Smrg *      Arguments: app_context - the app context.
936444c061aSmrg *                 specification_list - the resource specification list.
937a3bd7f05Smrg *      Returns: none.
938444c061aSmrg */
939444c061aSmrg
940444c061aSmrgvoid
941a3bd7f05SmrgXtAppSetFallbackResources(XtAppContext app_context, String *specification_list)
942444c061aSmrg{
943444c061aSmrg    LOCK_APP(app_context);
944444c061aSmrg    app_context->fallback_resources = specification_list;
945444c061aSmrg    UNLOCK_APP(app_context);
946444c061aSmrg}
947444c061aSmrg
948a3bd7f05SmrgWidget
949a3bd7f05SmrgXtOpenApplication(XtAppContext *app_context_return,
950a3bd7f05Smrg                  _Xconst char *application_class,
951a3bd7f05Smrg                  XrmOptionDescRec *options,
952a3bd7f05Smrg                  Cardinal num_options,
953a3bd7f05Smrg                  int *argc_in_out,
954a3bd7f05Smrg                  _XtString *argv_in_out,
955a3bd7f05Smrg                  String *fallback_resources,
956a3bd7f05Smrg                  WidgetClass widget_class,
957a3bd7f05Smrg                  ArgList args_in,
958a3bd7f05Smrg                  Cardinal num_args_in)
959444c061aSmrg{
960444c061aSmrg    XtAppContext app_con;
961a3bd7f05Smrg    Display *dpy;
962444c061aSmrg    register int saved_argc = *argc_in_out;
963444c061aSmrg    Widget root;
964444c061aSmrg    Arg args[3], *merged_args;
965444c061aSmrg    Cardinal num = 0;
966444c061aSmrg
967a3bd7f05Smrg    XtToolkitInitialize();      /* cannot be moved into _XtAppInit */
968444c061aSmrg
969a3bd7f05Smrg    dpy = _XtAppInit(&app_con, (String) application_class, options, num_options,
970a3bd7f05Smrg                     argc_in_out, &argv_in_out, fallback_resources);
971444c061aSmrg
972444c061aSmrg    LOCK_APP(app_con);
973a3bd7f05Smrg    XtSetArg(args[num], XtNscreen, DefaultScreenOfDisplay(dpy));
974a3bd7f05Smrg    num++;
975a3bd7f05Smrg    XtSetArg(args[num], XtNargc, saved_argc);
976a3bd7f05Smrg    num++;
977a3bd7f05Smrg    XtSetArg(args[num], XtNargv, argv_in_out);
978a3bd7f05Smrg    num++;
979444c061aSmrg
980444c061aSmrg    merged_args = XtMergeArgLists(args_in, num_args_in, args, num);
981444c061aSmrg    num += num_args_in;
982444c061aSmrg
983444c061aSmrg    root = XtAppCreateShell(NULL, application_class, widget_class, dpy,
984a3bd7f05Smrg                            merged_args, num);
985444c061aSmrg
986444c061aSmrg    if (app_context_return)
987a3bd7f05Smrg        *app_context_return = app_con;
988444c061aSmrg
989a3bd7f05Smrg    XtFree((XtPointer) merged_args);
990a3bd7f05Smrg    XtFree((XtPointer) argv_in_out);
991444c061aSmrg    UNLOCK_APP(app_con);
992444c061aSmrg    return root;
993444c061aSmrg}
994444c061aSmrg
995444c061aSmrgWidget
996a3bd7f05SmrgXtAppInitialize(XtAppContext *app_context_return,
997a3bd7f05Smrg                _Xconst char *application_class,
998a3bd7f05Smrg                XrmOptionDescRec *options,
999a3bd7f05Smrg                Cardinal num_options,
1000a3bd7f05Smrg                int *argc_in_out,
1001a3bd7f05Smrg                _XtString *argv_in_out,
1002a3bd7f05Smrg                String *fallback_resources,
1003a3bd7f05Smrg                ArgList args_in,
1004a3bd7f05Smrg                Cardinal num_args_in)
1005444c061aSmrg{
1006444c061aSmrg    return XtOpenApplication(app_context_return, application_class,
1007a3bd7f05Smrg                             options, num_options,
1008a3bd7f05Smrg                             argc_in_out, argv_in_out, fallback_resources,
1009a3bd7f05Smrg                             applicationShellWidgetClass, args_in, num_args_in);
1010444c061aSmrg}
1011444c061aSmrg
1012444c061aSmrgWidget
1013a3bd7f05SmrgXtInitialize(_Xconst _XtString name _X_UNUSED,
1014a3bd7f05Smrg             _Xconst _XtString classname,
1015a3bd7f05Smrg             XrmOptionDescRec *options,
1016a3bd7f05Smrg             Cardinal num_options,
1017a3bd7f05Smrg             int *argc,
1018a3bd7f05Smrg             _XtString *argv)
1019444c061aSmrg{
1020444c061aSmrg    Widget root;
1021444c061aSmrg    XtAppContext app_con;
1022444c061aSmrg    register ProcessContext process = _XtGetProcessContext();
1023444c061aSmrg
1024444c061aSmrg    root = XtAppInitialize(&app_con, classname, options, num_options,
1025a3bd7f05Smrg                           argc, argv, NULL, NULL, (Cardinal) 0);
1026444c061aSmrg
1027444c061aSmrg    LOCK_PROCESS;
1028444c061aSmrg    process->defaultAppContext = app_con;
1029444c061aSmrg    UNLOCK_PROCESS;
1030444c061aSmrg    return root;
1031444c061aSmrg}
1032