Resources.c revision a3bd7f05
1/***********************************************************
2Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved.
3
4Permission is hereby granted, free of charge, to any person obtaining a
5copy of this software and associated documentation files (the "Software"),
6to deal in the Software without restriction, including without limitation
7the rights to use, copy, modify, merge, publish, distribute, sublicense,
8and/or sell copies of the Software, and to permit persons to whom the
9Software is furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice (including the next
12paragraph) shall be included in all copies or substantial portions of the
13Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21DEALINGS IN THE SOFTWARE.
22
23Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
24
25                        All Rights Reserved
26
27Permission to use, copy, modify, and distribute this software and its
28documentation for any purpose and without fee is hereby granted,
29provided that the above copyright notice appear in all copies and that
30both that copyright notice and this permission notice appear in
31supporting documentation, and that the name of Digital not be
32used in advertising or publicity pertaining to distribution of the
33software without specific, written prior permission.
34
35DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
36ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
37DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
38ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
39WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
40ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
41SOFTWARE.
42
43******************************************************************/
44
45/*
46
47Copyright 1987, 1988, 1994, 1998  The Open Group
48
49Permission to use, copy, modify, distribute, and sell this software and its
50documentation for any purpose is hereby granted without fee, provided that
51the above copyright notice appear in all copies and that both that
52copyright notice and this permission notice appear in supporting
53documentation.
54
55The above copyright notice and this permission notice shall be included in
56all copies or substantial portions of the Software.
57
58THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
61OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
62AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
63CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
64
65Except as contained in this notice, the name of The Open Group shall not be
66used in advertising or otherwise to promote the sale, use or other dealings
67in this Software without prior written authorization from The Open Group.
68
69*/
70
71#ifdef HAVE_CONFIG_H
72#include <config.h>
73#endif
74#include "IntrinsicI.h"
75#include "VarargsI.h"
76#include "Shell.h"
77#include "ShellP.h"
78#include "StringDefs.h"
79#include <stdio.h>
80
81static XrmClass QBoolean, QString, QCallProc, QImmediate;
82static XrmName QinitialResourcesPersistent, QInitialResourcesPersistent;
83static XrmClass QTranslations, QTranslationTable;
84static XrmName Qtranslations, QbaseTranslations;
85static XrmName Qscreen;
86static XrmClass QScreen;
87
88void
89_XtCopyFromParent(Widget widget, int offset, XrmValue *value)
90{
91    if (widget->core.parent == NULL) {
92        XtAppWarningMsg(XtWidgetToApplicationContext(widget),
93                        "invalidParent", "xtCopyFromParent", XtCXtToolkitError,
94                        "CopyFromParent must have non-NULL parent", NULL, NULL);
95        value->addr = NULL;
96        return;
97    }
98    value->addr = (XPointer) (((char *) widget->core.parent) + offset);
99}                               /* _XtCopyFromParent */
100
101void
102_XtCopyFromArg(XtArgVal src, char *dst, register unsigned int size)
103{
104    if (size > sizeof(XtArgVal))
105        (void) memmove((char *) dst, (char *) src, (size_t) size);
106    else {
107        union {
108            long longval;
109#ifdef LONG64
110            int intval;
111#endif
112            short shortval;
113            char charval;
114            char *charptr;
115            XtPointer ptr;
116        } u;
117        char *p = (char *) &u;
118
119        if (size == sizeof(long))
120            u.longval = (long) src;
121#ifdef LONG64
122        else if (size == sizeof(int))
123            u.intval = (int) src;
124#endif
125        else if (size == sizeof(short))
126            u.shortval = (short) src;
127        else if (size == sizeof(char))
128            u.charval = (char) src;
129        else if (size == sizeof(XtPointer))
130            u.ptr = (XtPointer) src;
131        else if (size == sizeof(char *))
132            u.charptr = (char *) src;
133        else
134            p = (char *) &src;
135
136        (void) memmove(dst, p, (size_t) size);
137    }
138}                               /* _XtCopyFromArg */
139
140void
141_XtCopyToArg(char *src, XtArgVal *dst, register unsigned int size)
142{
143    if (!*dst) {
144#ifdef GETVALUES_BUG
145        /* old GetValues semantics (storing directly into arglists) are bad,
146         * but preserve for compatibility as long as arglist contains NULL.
147         */
148        union {
149            long longval;
150#ifdef LONG64
151            int intval;
152#endif
153            short shortval;
154            char charval;
155            char *charptr;
156            XtPointer ptr;
157        } u;
158
159        if (size <= sizeof(XtArgVal)) {
160            (void) memmove((char *) &u, (char *) src, (size_t) size);
161            if (size == sizeof(long))
162                *dst = (XtArgVal) u.longval;
163#ifdef LONG64
164            else if (size == sizeof(int))
165                *dst = (XtArgVal) u.intval;
166#endif
167            else if (size == sizeof(short))
168                *dst = (XtArgVal) u.shortval;
169            else if (size == sizeof(char))
170                *dst = (XtArgVal) u.charval;
171            else if (size == sizeof(char *))
172                *dst = (XtArgVal) u.charptr;
173            else if (size == sizeof(XtPointer))
174                *dst = (XtArgVal) u.ptr;
175            else
176                (void) memmove((char *) dst, (char *) src, (size_t) size);
177        }
178        else
179            (void) memmove((char *) dst, (char *) src, (size_t) size);
180#else
181        XtErrorMsg("invalidGetValues", "xtGetValues", XtCXtToolkitError,
182                   "NULL ArgVal in XtGetValues", NULL, NULL);
183#endif
184    }
185    else {
186        /* proper GetValues semantics: argval is pointer to destination */
187        (void) memmove((char *) *dst, (char *) src, (size_t) size);
188    }
189}                               /* _XtCopyToArg */
190
191static void
192CopyToArg(char *src, XtArgVal *dst, register unsigned int size)
193{
194    if (!*dst) {
195        /* old GetValues semantics (storing directly into arglists) are bad,
196         * but preserve for compatibility as long as arglist contains NULL.
197         */
198        union {
199            long longval;
200#ifdef LONG64
201            int intval;
202#endif
203            short shortval;
204            char charval;
205            char *charptr;
206            XtPointer ptr;
207        } u;
208
209        if (size <= sizeof(XtArgVal)) {
210            (void) memmove((char *) &u, (char *) src, (size_t) size);
211            if (size == sizeof(long))
212                *dst = (XtArgVal) u.longval;
213#ifdef LONG64
214            else if (size == sizeof(int))
215                *dst = (XtArgVal) u.intval;
216#endif
217            else if (size == sizeof(short))
218                *dst = (XtArgVal) u.shortval;
219            else if (size == sizeof(char))
220                *dst = (XtArgVal) u.charval;
221            else if (size == sizeof(char *))
222                *dst = (XtArgVal) u.charptr;
223            else if (size == sizeof(XtPointer))
224                *dst = (XtArgVal) u.ptr;
225            else
226                (void) memmove((char *) dst, (char *) src, (size_t) size);
227        }
228        else
229            (void) memmove((char *) dst, (char *) src, (size_t) size);
230    }
231    else {
232        /* proper GetValues semantics: argval is pointer to destination */
233        (void) memmove((char *) *dst, (char *) src, (size_t) size);
234    }
235}                               /* CopyToArg */
236
237static Cardinal
238CountTreeDepth(Widget w)
239{
240    Cardinal count;
241
242    for (count = 1; w != NULL; w = (Widget) w->core.parent)
243        count++;
244
245    return count;
246}
247
248static void
249GetNamesAndClasses(register Widget w,
250                   register XrmNameList names,
251                   register XrmClassList classes)
252{
253    register Cardinal length, j;
254    register XrmQuark t;
255    WidgetClass class;
256
257    /* Return null-terminated quark arrays, with length the number of
258       quarks (not including NULL) */
259
260    LOCK_PROCESS;
261    for (length = 0; w != NULL; w = (Widget) w->core.parent) {
262        names[length] = w->core.xrm_name;
263        class = XtClass(w);
264        /* KLUDGE KLUDGE KLUDGE KLUDGE */
265        if (w->core.parent == NULL && XtIsApplicationShell(w)) {
266            classes[length] =
267                ((ApplicationShellWidget) w)->application.xrm_class;
268        }
269        else
270            classes[length] = class->core_class.xrm_class;
271        length++;
272    }
273    UNLOCK_PROCESS;
274    /* They're in backwards order, flop them around */
275    for (j = 0; j < length / 2; j++) {
276        t = names[j];
277        names[j] = names[length - j - 1];
278        names[length - j - 1] = t;
279        t = classes[j];
280        classes[j] = classes[length - j - 1];
281        classes[length - j - 1] = t;
282    }
283    names[length] = NULLQUARK;
284    classes[length] = NULLQUARK;
285}                               /* GetNamesAndClasses */
286
287/* Spiffy fast compiled form of resource list.                          */
288/* XtResourceLists are compiled in-place into XrmResourceLists          */
289/* All atoms are replaced by quarks, and offsets are -offset-1 to       */
290/* indicate that this list has been compiled already                    */
291
292void
293_XtCompileResourceList(register XtResourceList resources,
294                       Cardinal num_resources)
295{
296    register Cardinal count;
297
298#define xrmres  ((XrmResourceList) resources)
299#define PSToQ   XrmPermStringToQuark
300
301    for (count = 0; count < num_resources; resources++, count++) {
302        xrmres->xrm_name = PSToQ(resources->resource_name);
303        xrmres->xrm_class = PSToQ(resources->resource_class);
304        xrmres->xrm_type = PSToQ(resources->resource_type);
305        xrmres->xrm_offset = (int)
306            (-(int) resources->resource_offset - 1);
307        xrmres->xrm_default_type = PSToQ(resources->default_type);
308    }
309#undef PSToQ
310#undef xrmres
311}                               /* _XtCompileResourceList */
312
313/* Like _XtCompileResourceList, but strings are not permanent */
314static void
315XrmCompileResourceListEphem(register XtResourceList resources,
316                            Cardinal num_resources)
317{
318    register Cardinal count;
319
320#define xrmres  ((XrmResourceList) resources)
321
322    for (count = 0; count < num_resources; resources++, count++) {
323        xrmres->xrm_name = StringToName(resources->resource_name);
324        xrmres->xrm_class = StringToClass(resources->resource_class);
325        xrmres->xrm_type = StringToQuark(resources->resource_type);
326        xrmres->xrm_offset = (int)
327            (-(int) resources->resource_offset - 1);
328        xrmres->xrm_default_type = StringToQuark(resources->default_type);
329    }
330#undef xrmres
331}                               /* XrmCompileResourceListEphem */
332
333static void
334BadSize(Cardinal size, XrmQuark name)
335{
336    String params[2];
337    Cardinal num_params = 2;
338
339    params[0] = (String) (long) size;
340    params[1] = XrmQuarkToString(name);
341    XtWarningMsg("invalidSizeOverride", "xtDependencies", XtCXtToolkitError,
342                 "Representation size %d must match superclass's to override %s",
343                 params, &num_params);
344}                               /* BadType */
345
346/*
347 * Create a new resource list, with the class resources following the
348 * superclass's resources.  If a resource in the class list overrides
349 * a superclass resource, then just replace the superclass entry in place.
350 *
351 * At the same time, add a level of indirection to the XtResourceList to
352 * create and XrmResourceList.
353 */
354void
355_XtDependencies(XtResourceList *class_resp,    /* VAR */
356                Cardinal *class_num_resp,      /* VAR */
357                XrmResourceList *super_res,
358                Cardinal super_num_res,
359                Cardinal super_widget_size)
360{
361    register XrmResourceList *new_res;
362    Cardinal new_num_res;
363    XrmResourceList class_res = (XrmResourceList) *class_resp;
364    Cardinal class_num_res = *class_num_resp;
365    register Cardinal i, j;
366    Cardinal new_next;
367
368    if (class_num_res == 0) {
369        /* Just point to superclass resource list */
370        *class_resp = (XtResourceList) super_res;
371        *class_num_resp = super_num_res;
372        return;
373    }
374
375    /* Allocate and initialize new_res with superclass resource pointers */
376    new_num_res = super_num_res + class_num_res;
377    new_res = (XrmResourceList *)
378        __XtMalloc((Cardinal) (new_num_res * sizeof(XrmResourceList)));
379    if (super_num_res > 0)
380        XtMemmove(new_res, super_res, super_num_res * sizeof(XrmResourceList));
381
382    /* Put pointers to class resource entries into new_res */
383    new_next = super_num_res;
384    for (i = 0; i < class_num_res; i++) {
385        if ((Cardinal) (-class_res[i].xrm_offset - 1) < super_widget_size) {
386            /* Probably an override of superclass resources--look for overlap */
387            for (j = 0; j < super_num_res; j++) {
388                if (class_res[i].xrm_offset == new_res[j]->xrm_offset) {
389                    /* Spec is silent on what fields subclass can override.
390                     * The only two of real concern are type & size.
391                     * Although allowing type to be over-ridden introduces
392                     * the possibility of errors, it's at present the only
393                     * reasonable way to allow a subclass to force a private
394                     * converter to be invoked for a subset of fields.
395                     */
396                    /* We do insist that size be identical to superclass */
397                    if (class_res[i].xrm_size != new_res[j]->xrm_size) {
398                        BadSize(class_res[i].xrm_size,
399                                (XrmQuark) class_res[i].xrm_name);
400                        class_res[i].xrm_size = new_res[j]->xrm_size;
401                    }
402                    new_res[j] = &(class_res[i]);
403                    new_num_res--;
404                    goto NextResource;
405                }
406            }                   /* for j */
407        }
408        /* Not an overlap, add an entry to new_res */
409        new_res[new_next++] = &(class_res[i]);
410 NextResource:;
411    }                           /* for i */
412
413    /* Okay, stuff new resources back into class record */
414    *class_resp = (XtResourceList) new_res;
415    *class_num_resp = new_num_res;
416}                               /* _XtDependencies */
417
418void
419_XtResourceDependencies(WidgetClass wc)
420{
421    WidgetClass sc;
422
423    sc = wc->core_class.superclass;
424    if (sc == NULL) {
425        _XtDependencies(&(wc->core_class.resources),
426                        &(wc->core_class.num_resources),
427                        (XrmResourceList *) NULL, (unsigned) 0, (unsigned) 0);
428    }
429    else {
430        _XtDependencies(&(wc->core_class.resources),
431                        &(wc->core_class.num_resources),
432                        (XrmResourceList *) sc->core_class.resources,
433                        sc->core_class.num_resources,
434                        sc->core_class.widget_size);
435    }
436}                               /* _XtResourceDependencies */
437
438void
439_XtConstraintResDependencies(ConstraintWidgetClass wc)
440{
441    if (wc == (ConstraintWidgetClass) constraintWidgetClass) {
442        _XtDependencies(&(wc->constraint_class.resources),
443                        &(wc->constraint_class.num_resources),
444                        (XrmResourceList *) NULL, (unsigned) 0, (unsigned) 0);
445    }
446    else {
447        ConstraintWidgetClass sc;
448
449        sc = (ConstraintWidgetClass) wc->core_class.superclass;
450        _XtDependencies(&(wc->constraint_class.resources),
451                        &(wc->constraint_class.num_resources),
452                        (XrmResourceList *) sc->constraint_class.resources,
453                        sc->constraint_class.num_resources,
454                        sc->constraint_class.constraint_size);
455    }
456}                               /* _XtConstraintResDependencies */
457
458XrmResourceList *
459_XtCreateIndirectionTable(XtResourceList resources, Cardinal num_resources)
460{
461    register Cardinal idx;
462    XrmResourceList *table;
463
464    table = (XrmResourceList *)
465        __XtMalloc((Cardinal) (num_resources * sizeof(XrmResourceList)));
466    for (idx = 0; idx < num_resources; idx++)
467        table[idx] = (XrmResourceList) (&(resources[idx]));
468    return table;
469}
470
471static XtCacheRef *
472GetResources(Widget widget,             /* Widget resources are associated with */
473             char *base,                /* Base address of memory to write to */
474             XrmNameList names,         /* Full inheritance name of widget */
475             XrmClassList classes,      /* Full inheritance class of widget     */
476             XrmResourceList *table,    /* The list of resources required.      */
477             unsigned num_resources,    /* number of items in resource list     */
478             XrmQuarkList quark_args,   /* Arg names quarkified                 */
479             ArgList args,              /* ArgList to override resources */
480             unsigned num_args,         /* number of items in arg list  */
481             XtTypedArgList typed_args, /* Typed arg list to override resources */
482             Cardinal *pNumTypedArgs,   /* number of items in typed arg list    */
483             Boolean tm_hack)           /* do baseTranslations                  */
484{
485/*
486 * assert: *pNumTypedArgs == 0 if num_args > 0
487 * assert: num_args == 0 if *pNumTypedArgs > 0
488 */
489#define SEARCHLISTLEN 100
490#define MAXRESOURCES  400
491
492    XrmValue value;
493    XrmQuark rawType;
494    XrmValue convValue;
495    XrmHashTable stackSearchList[SEARCHLISTLEN];
496    XrmHashTable *searchList = stackSearchList;
497    unsigned int searchListSize = SEARCHLISTLEN;
498    Boolean found[MAXRESOURCES];
499    int typed[MAXRESOURCES];
500    XtCacheRef cache_ref[MAXRESOURCES];
501    XtCacheRef *cache_ptr, *cache_base;
502    Boolean persistent_resources = True;
503    Boolean found_persistence = False;
504    int num_typed_args = (int) *pNumTypedArgs;
505    XrmDatabase db;
506    Boolean do_tm_hack = False;
507
508    if ((args == NULL) && (num_args != 0)) {
509        XtAppWarningMsg(XtWidgetToApplicationContext(widget),
510                        "invalidArgCount", "getResources", XtCXtToolkitError,
511                        "argument count > 0 on NULL argument list", NULL, NULL);
512        num_args = 0;
513    }
514    if (num_resources == 0) {
515        return NULL;
516    }
517    else if (num_resources >= MAXRESOURCES) {
518        XtAppWarningMsg(XtWidgetToApplicationContext(widget),
519                        "invalidResourceCount", "getResources",
520                        XtCXtToolkitError, "too many resources", NULL, NULL);
521        return NULL;
522    }
523    else if (table == NULL) {
524        XtAppWarningMsg(XtWidgetToApplicationContext(widget),
525                        "invalidResourceCount", "getResources",
526                        XtCXtToolkitError,
527                        "resource count > 0 on NULL resource list", NULL, NULL);
528        return NULL;
529    }
530
531    /* Mark each resource as not found on arg list */
532    memset((void *) found, 0, (size_t) (num_resources * sizeof(Boolean)));
533    memset((void *) typed, 0, (size_t) (num_resources * sizeof(int)));
534
535    /* Copy the args into the resources, mark each as found */
536    {
537        register ArgList arg;
538        register XtTypedArgList typed_arg;
539        register XrmName argName;
540        register Cardinal j;
541        register int i;
542        register XrmResourceList rx;
543        register XrmResourceList *res;
544
545        for (arg = args, i = 0; (Cardinal) i < num_args; i++, arg++) {
546            argName = quark_args[i];
547            if (argName == QinitialResourcesPersistent) {
548                persistent_resources = (Boolean) arg->value;
549                found_persistence = True;
550                continue;
551            }
552            for (j = 0, res = table; j < num_resources; j++, res++) {
553                rx = *res;
554                if (argName == rx->xrm_name) {
555                    _XtCopyFromArg(arg->value,
556                                   base - rx->xrm_offset - 1, rx->xrm_size);
557                    found[j] = TRUE;
558                    break;
559                }
560            }
561        }
562        for (typed_arg = typed_args, i = 0; i < num_typed_args;
563             i++, typed_arg++) {
564            register XrmRepresentation argType;
565
566            argName = quark_args[i];
567            argType = (typed_arg->type == NULL) ? NULLQUARK
568                : XrmStringToRepresentation(typed_arg->type);
569            if (argName == QinitialResourcesPersistent) {
570                persistent_resources = (Boolean) typed_arg->value;
571                found_persistence = True;
572                break;
573            }
574            for (j = 0, res = table; j < num_resources; j++, res++) {
575                rx = *res;
576                if (argName == rx->xrm_name) {
577                    if (argType != NULLQUARK && argType != rx->xrm_type) {
578                        typed[j] = i + 1;
579                    }
580                    else {
581                        _XtCopyFromArg(typed_arg->value,
582                                       base - rx->xrm_offset - 1, rx->xrm_size);
583                    }
584                    found[j] = TRUE;
585                    break;
586                }
587            }
588        }
589    }
590
591    /* Ask resource manager for a list of database levels that we can
592       do a single-level search on each resource */
593
594    db = XtScreenDatabase(XtScreenOfObject(widget));
595    while (!XrmQGetSearchList(db, names, classes,
596                              searchList, (int) searchListSize)) {
597        if (searchList == stackSearchList)
598            searchList = NULL;
599        searchList = (XrmHashTable *) XtRealloc((char *) searchList,
600                                                (Cardinal) (sizeof(XrmHashTable)
601                                                            * (searchListSize *=
602                                                               2)));
603    }
604
605    if (persistent_resources)
606        cache_base = NULL;
607    else
608        cache_base = cache_ref;
609    /* geez, this is an ugly mess */
610    if (XtIsShell(widget)) {
611        register XrmResourceList *res;
612        register Cardinal j;
613        Screen *oldscreen = widget->core.screen;
614
615        /* look up screen resource first, since real rdb depends on it */
616        for (res = table, j = 0; j < num_resources; j++, res++) {
617            if ((*res)->xrm_name != Qscreen)
618                continue;
619            if (typed[j]) {
620                register XtTypedArg *arg = typed_args + typed[j] - 1;
621                XrmQuark from_type;
622                XrmValue from_val, to_val;
623
624                from_type = StringToQuark(arg->type);
625                from_val.size = (Cardinal) arg->size;
626                if ((from_type == QString) ||
627                    ((unsigned) arg->size > sizeof(XtArgVal)))
628                    from_val.addr = (XPointer) arg->value;
629                else
630                    from_val.addr = (XPointer) &arg->value;
631                to_val.size = sizeof(Screen *);
632                to_val.addr = (XPointer) &widget->core.screen;
633                found[j] = _XtConvert(widget, from_type, &from_val,
634                                      QScreen, &to_val, cache_base);
635                if (cache_base && *cache_base)
636                    cache_base++;
637            }
638            if (!found[j]) {
639                if (XrmQGetSearchResource(searchList, Qscreen, QScreen,
640                                          &rawType, &value)) {
641                    if (rawType != QScreen) {
642                        convValue.size = sizeof(Screen *);
643                        convValue.addr = (XPointer) &widget->core.screen;
644                        (void) _XtConvert(widget, rawType, &value,
645                                          QScreen, &convValue, cache_base);
646                        if (cache_base && *cache_base)
647                            cache_base++;
648                    }
649                    else {
650                        widget->core.screen = *((Screen **) value.addr);
651                    }
652                }
653            }
654            break;
655        }
656        /* now get the database to use for the rest of the resources */
657        if (widget->core.screen != oldscreen) {
658            db = XtScreenDatabase(widget->core.screen);
659            while (!XrmQGetSearchList(db, names, classes,
660                                      searchList, (int) searchListSize)) {
661                if (searchList == stackSearchList)
662                    searchList = NULL;
663                searchList = (XrmHashTable *) XtRealloc((char *) searchList,
664                                                        (Cardinal) (sizeof
665                                                                    (XrmHashTable)
666                                                                    *
667                                                                    (searchListSize
668                                                                     *= 2)));
669            }
670        }
671    }
672
673    /* go to the resource manager for those resources not found yet */
674    /* if it's not in the resource database use the default value   */
675
676    {
677        register XrmResourceList rx;
678        register XrmResourceList *res;
679        register Cardinal j;
680        register XrmRepresentation xrm_type;
681        register XrmRepresentation xrm_default_type;
682        char char_val;
683        short short_val;
684        int int_val;
685        long long_val;
686        char *char_ptr;
687
688        if (!found_persistence) {
689            if (XrmQGetSearchResource(searchList, QinitialResourcesPersistent,
690                                      QInitialResourcesPersistent, &rawType,
691                                      &value)) {
692                if (rawType != QBoolean) {
693                    convValue.size = sizeof(Boolean);
694                    convValue.addr = (XPointer) &persistent_resources;
695                    (void) _XtConvert(widget, rawType, &value, QBoolean,
696                                      &convValue, NULL);
697                }
698                else
699                    persistent_resources = *(Boolean *) value.addr;
700            }
701        }
702        if (persistent_resources)
703            cache_ptr = NULL;
704        else if (cache_base)
705            cache_ptr = cache_base;
706        else
707            cache_ptr = cache_ref;
708
709        for (res = table, j = 0; j < num_resources; j++, res++) {
710            rx = *res;
711            xrm_type = (XrmRepresentation) rx->xrm_type;
712            if (typed[j]) {
713                register XtTypedArg *arg = typed_args + typed[j] - 1;
714
715                /*
716                 * This resource value has been specified as a typed arg and
717                 * has to be converted. Typed arg conversions are done here
718                 * to correctly interpose them with normal resource conversions.
719                 */
720                XrmQuark from_type;
721                XrmValue from_val, to_val;
722                Boolean converted;
723
724                from_type = StringToQuark(arg->type);
725                from_val.size = (Cardinal) arg->size;
726                if ((from_type == QString) ||
727                    ((unsigned) arg->size > sizeof(XtArgVal)))
728                    from_val.addr = (XPointer) arg->value;
729                else
730                    from_val.addr = (XPointer) &arg->value;
731                to_val.size = rx->xrm_size;
732                to_val.addr = base - rx->xrm_offset - 1;
733                converted = _XtConvert(widget, from_type, &from_val,
734                                       xrm_type, &to_val, cache_ptr);
735                if (converted) {
736
737                    /* Copy the converted value back into the typed argument.
738                     * normally the data should be <= sizeof(XtArgVal) and
739                     * is stored directly into the 'value' field .... BUT
740                     * if the resource size is greater than sizeof(XtArgVal)
741                     * then we dynamically alloc a block of store to hold the
742                     * data and zap a copy in there !!! .... freeing it later
743                     * the size field in the typed arg is negated to indicate
744                     * that the store pointed to by the value field is
745                     * dynamic .......
746                     * "freeing" happens in the case of _XtCreate after the
747                     * CallInitialize ..... other clients of GetResources
748                     * using typed args should be aware of the need to free
749                     * this store .....
750                     */
751
752                    if (rx->xrm_size > sizeof(XtArgVal)) {
753                        arg->value =
754                            (XtArgVal) (void *) __XtMalloc(rx->xrm_size);
755                        arg->size = -(arg->size);
756                    }
757                    else {      /* will fit - copy directly into value field */
758                        arg->value = (XtArgVal) NULL;
759                    }
760                    CopyToArg((char *) (base - rx->xrm_offset - 1),
761                              &arg->value, rx->xrm_size);
762
763                }
764                else {
765                    /* Conversion failed. Get default value. */
766                    found[j] = False;
767                }
768
769                if (cache_ptr && *cache_ptr)
770                    cache_ptr++;
771            }
772
773            if (!found[j]) {
774                Boolean already_copied = False;
775                Boolean have_value = False;
776
777                if (XrmQGetSearchResource(searchList,
778                                          (XrmName) rx->xrm_name,
779                                          (XrmClass) rx->xrm_class, &rawType,
780                                          &value)) {
781                    if (rawType != xrm_type) {
782                        convValue.size = rx->xrm_size;
783                        convValue.addr = (XPointer) (base - rx->xrm_offset - 1);
784                        already_copied = have_value =
785                            _XtConvert(widget, rawType, &value,
786                                       xrm_type, &convValue, cache_ptr);
787                        if (cache_ptr && *cache_ptr)
788                            cache_ptr++;
789                    }
790                    else
791                        have_value = True;
792                    if (have_value && rx->xrm_name == Qtranslations)
793                        do_tm_hack = True;
794                }
795                LOCK_PROCESS;
796                if (!have_value && ((rx->xrm_default_type == QImmediate)
797                                    || (rx->xrm_default_type == xrm_type)
798                                    || (rx->xrm_default_addr != NULL))) {
799                    /* Convert default value to proper type */
800                    xrm_default_type = (XrmRepresentation) rx->xrm_default_type;
801                    if (xrm_default_type == QCallProc) {
802                        (*(XtResourceDefaultProc) (rx->xrm_default_addr))
803                            (widget, -(rx->xrm_offset + 1), &value);
804
805                    }
806                    else if (xrm_default_type == QImmediate) {
807                        /* XtRImmediate == XtRString for type XtRString */
808                        if (xrm_type == QString) {
809                            value.addr = rx->xrm_default_addr;
810                        }
811                        else if (rx->xrm_size == sizeof(int)) {
812                            int_val = (int) (long) rx->xrm_default_addr;
813                            value.addr = (XPointer) &int_val;
814                        }
815                        else if (rx->xrm_size == sizeof(short)) {
816                            short_val = (short) (long) rx->xrm_default_addr;
817                            value.addr = (XPointer) &short_val;
818                        }
819                        else if (rx->xrm_size == sizeof(char)) {
820                            char_val = (char) (long) rx->xrm_default_addr;
821                            value.addr = (XPointer) &char_val;
822                        }
823                        else if (rx->xrm_size == sizeof(long)) {
824                            long_val = (long) rx->xrm_default_addr;
825                            value.addr = (XPointer) &long_val;
826                        }
827                        else if (rx->xrm_size == sizeof(char *)) {
828                            char_ptr = (char *) rx->xrm_default_addr;
829                            value.addr = (XPointer) &char_ptr;
830                        }
831                        else {
832                            value.addr = (XPointer) &(rx->xrm_default_addr);
833                        }
834                    }
835                    else if (xrm_default_type == xrm_type) {
836                        value.addr = rx->xrm_default_addr;
837                    }
838                    else {
839                        value.addr = rx->xrm_default_addr;
840                        if (xrm_default_type == QString) {
841                            value.size =
842                                (unsigned) strlen((char *) value.addr) + 1;
843                        }
844                        else {
845                            value.size = sizeof(XtPointer);
846                        }
847                        convValue.size = rx->xrm_size;
848                        convValue.addr = (XPointer) (base - rx->xrm_offset - 1);
849                        already_copied =
850                            _XtConvert(widget, xrm_default_type, &value,
851                                       xrm_type, &convValue, cache_ptr);
852                        if (!already_copied)
853                            value.addr = NULL;
854                        if (cache_ptr && *cache_ptr)
855                            cache_ptr++;
856                    }
857                }
858                if (!already_copied) {
859                    if (xrm_type == QString) {
860                        *((String *) (base - rx->xrm_offset - 1)) = value.addr;
861                    }
862                    else {
863                        if (value.addr != NULL) {
864                            XtMemmove(base - rx->xrm_offset - 1,
865                                      value.addr, rx->xrm_size);
866                        }
867                        else {
868                            /* didn't get value, initialize to NULL... */
869                            XtBZero(base - rx->xrm_offset - 1, rx->xrm_size);
870                        }
871                    }
872                }
873                UNLOCK_PROCESS;
874            }
875        }
876        for (res = table, j = 0; j < num_resources; j++, res++) {
877            if (!found[j] && typed[j]) {
878                /*
879                 * This resource value was specified as a typed arg.
880                 * However, the default value is being used here since
881                 * type type conversion failed, so we compress the list.
882                 */
883                register XtTypedArg *arg = typed_args + typed[j] - 1;
884                register int i;
885
886                for (i = num_typed_args - typed[j]; i > 0; i--, arg++) {
887                    *arg = *(arg + 1);
888                }
889                num_typed_args--;
890            }
891        }
892        if (tm_hack)
893            widget->core.tm.current_state = NULL;
894        if (tm_hack &&
895            (!widget->core.tm.translations ||
896             (do_tm_hack &&
897              widget->core.tm.translations->operation != XtTableReplace)) &&
898            XrmQGetSearchResource(searchList, QbaseTranslations,
899                                  QTranslations, &rawType, &value)) {
900            if (rawType != QTranslationTable) {
901                convValue.size = sizeof(XtTranslations);
902                convValue.addr = (XPointer) &widget->core.tm.current_state;
903                (void) _XtConvert(widget, rawType, &value,
904                                  QTranslationTable, &convValue, cache_ptr);
905                if (cache_ptr && *cache_ptr)
906                    cache_ptr++;
907            }
908            else {
909                /* value.addr can be NULL see: !already_copied */
910                if (value.addr)
911                    *((XtTranslations *) &widget->core.tm.current_state) =
912                        *((XtTranslations *) value.addr);
913            }
914        }
915    }
916    if ((Cardinal) num_typed_args != *pNumTypedArgs)
917        *pNumTypedArgs = (Cardinal) num_typed_args;
918    if (searchList != stackSearchList)
919        XtFree((char *) searchList);
920    if (!cache_ptr)
921        cache_ptr = cache_base;
922    if (cache_ptr && cache_ptr != cache_ref) {
923        int cache_ref_size = (int) (cache_ptr - cache_ref);
924        XtCacheRef *refs = (XtCacheRef *)
925            __XtMalloc((Cardinal)
926                       (sizeof(XtCacheRef) * (size_t) (cache_ref_size + 1)));
927
928        (void) memmove(refs, cache_ref,
929                       sizeof(XtCacheRef) * (size_t) cache_ref_size);
930        refs[cache_ref_size] = NULL;
931        return refs;
932    }
933    return (XtCacheRef *) NULL;
934}
935
936static void
937CacheArgs(ArgList args,
938          Cardinal num_args,
939          XtTypedArgList typed_args,
940          Cardinal num_typed_args,
941          XrmQuarkList quark_cache,
942          Cardinal num_quarks,
943          XrmQuarkList *pQuarks)        /* RETURN */
944{
945    register XrmQuarkList quarks;
946    register Cardinal i;
947    register Cardinal count;
948
949    count = (args != NULL) ? num_args : num_typed_args;
950
951    if (num_quarks < count) {
952        quarks =
953            (XrmQuarkList) __XtMalloc((Cardinal) (count * sizeof(XrmQuark)));
954    }
955    else {
956        quarks = quark_cache;
957    }
958    *pQuarks = quarks;
959
960    if (args != NULL) {
961        for (i = count; i; i--)
962            *quarks++ = StringToQuark((args++)->name);
963    }
964    else {
965        for (i = count; i; i--)
966            *quarks++ = StringToQuark((typed_args++)->name);
967    }
968}
969
970#define FreeCache(cache, pointer) \
971          if (cache != pointer) XtFree((char *)pointer)
972
973XtCacheRef *
974_XtGetResources(register Widget w,
975                ArgList args,
976                Cardinal num_args,
977                XtTypedArgList typed_args,
978                Cardinal *num_typed_args)
979{
980    XrmName *names, names_s[50];
981    XrmClass *classes, classes_s[50];
982    XrmQuark quark_cache[100];
983    XrmQuarkList quark_args;
984    WidgetClass wc;
985    XtCacheRef *cache_refs = NULL;
986    Cardinal count;
987
988    wc = XtClass(w);
989
990    count = CountTreeDepth(w);
991    names = (XrmName *) XtStackAlloc(count * sizeof(XrmName), names_s);
992    classes = (XrmClass *) XtStackAlloc(count * sizeof(XrmClass), classes_s);
993    if (names == NULL || classes == NULL) {
994        _XtAllocError(NULL);
995    }
996    else {
997
998        /* Get names, classes for widget and ancestors */
999        GetNamesAndClasses(w, names, classes);
1000
1001        /* Compile arg list into quarks */
1002        CacheArgs(args, num_args, typed_args, *num_typed_args, quark_cache,
1003                  XtNumber(quark_cache), &quark_args);
1004
1005        /* Get normal resources */
1006        LOCK_PROCESS;
1007        cache_refs = GetResources(w, (char *) w, names, classes,
1008                                  (XrmResourceList *) wc->core_class.resources,
1009                                  wc->core_class.num_resources, quark_args,
1010                                  args, num_args, typed_args, num_typed_args,
1011                                  XtIsWidget(w));
1012
1013        if (w->core.constraints != NULL) {
1014            ConstraintWidgetClass cwc;
1015            XtCacheRef *cache_refs_core;
1016
1017            cwc = (ConstraintWidgetClass) XtClass(w->core.parent);
1018            cache_refs_core =
1019                GetResources(w, (char *) w->core.constraints, names, classes,
1020                             (XrmResourceList *) cwc->constraint_class.
1021                             resources, cwc->constraint_class.num_resources,
1022                             quark_args, args, num_args, typed_args,
1023                             num_typed_args, False);
1024            XtFree((char *) cache_refs_core);
1025        }
1026        FreeCache(quark_cache, quark_args);
1027        UNLOCK_PROCESS;
1028        XtStackFree((XtPointer) names, names_s);
1029        XtStackFree((XtPointer) classes, classes_s);
1030    }
1031    return cache_refs;
1032}                               /* _XtGetResources */
1033
1034void
1035_XtGetSubresources(Widget w,                    /* Widget "parent" of subobject */
1036                   XtPointer base,              /* Base address to write to */
1037                   const char *name,            /* name of subobject        */
1038                   const char *class,           /* class of subobject       */
1039                   XtResourceList resources,    /* resource list for subobject    */
1040                   Cardinal num_resources,
1041                   ArgList args,                /* arg list to override resources */
1042                   Cardinal num_args,
1043                   XtTypedArgList typed_args,
1044                   Cardinal num_typed_args)
1045{
1046    XrmName *names, names_s[50];
1047    XrmClass *classes, classes_s[50];
1048    XrmQuark quark_cache[100];
1049    XrmQuarkList quark_args;
1050    XrmResourceList *table;
1051    Cardinal count, ntyped_args = num_typed_args;
1052    XtCacheRef *Resrc = NULL;
1053
1054    WIDGET_TO_APPCON(w);
1055
1056    if (num_resources == 0)
1057        return;
1058
1059    LOCK_APP(app);
1060    count = CountTreeDepth(w);
1061    count++;                    /* make sure there's enough room for name and class */
1062    names = (XrmName *) XtStackAlloc(count * sizeof(XrmName), names_s);
1063    classes = (XrmClass *) XtStackAlloc(count * sizeof(XrmClass), classes_s);
1064    if (names == NULL || classes == NULL) {
1065        _XtAllocError(NULL);
1066    }
1067    else {
1068        /* Get full name, class of subobject */
1069        GetNamesAndClasses(w, names, classes);
1070        count -= 2;
1071        names[count] = StringToName(name);
1072        classes[count] = StringToClass(class);
1073        count++;
1074        names[count] = NULLQUARK;
1075        classes[count] = NULLQUARK;
1076
1077        /* Compile arg list into quarks */
1078        CacheArgs(args, num_args, typed_args, num_typed_args,
1079                  quark_cache, XtNumber(quark_cache), &quark_args);
1080
1081        /* Compile resource list if needed */
1082        if (((int) resources->resource_offset) >= 0) {
1083            XrmCompileResourceListEphem(resources, num_resources);
1084        }
1085        table = _XtCreateIndirectionTable(resources, num_resources);
1086        Resrc =
1087            GetResources(w, (char *) base, names, classes, table, num_resources,
1088                         quark_args, args, num_args, typed_args, &ntyped_args,
1089                         False);
1090        FreeCache(quark_cache, quark_args);
1091        XtFree((char *) table);
1092        XtFree((char *) Resrc);
1093        XtStackFree((XtPointer) names, names_s);
1094        XtStackFree((XtPointer) classes, classes_s);
1095        UNLOCK_APP(app);
1096    }
1097}
1098
1099void
1100XtGetSubresources(Widget w,                     /* Widget "parent" of subobject */
1101                  XtPointer base,               /* Base address to write to */
1102                  _Xconst char *name,           /* name of subobject        */
1103                  _Xconst char *class,          /* class of subobject       */
1104                  XtResourceList resources,     /* resource list for subobject    */
1105                  Cardinal num_resources,
1106                  ArgList args,                 /* arg list to override resources */
1107                  Cardinal num_args)
1108{
1109    _XtGetSubresources(w, base, name, class, resources, num_resources, args,
1110                       num_args, NULL, 0);
1111}
1112
1113void
1114_XtGetApplicationResources(Widget w,            /* Application shell widget */
1115                           XtPointer base,      /* Base address to write to       */
1116                           XtResourceList resources,    /* resource list for subobject    */
1117                           Cardinal num_resources,
1118                           ArgList args,        /* arg list to override resources */
1119                           Cardinal num_args,
1120                           XtTypedArgList typed_args,
1121                           Cardinal num_typed_args)
1122{
1123    XrmName *names, names_s[50];
1124    XrmClass *classes, classes_s[50];
1125    XrmQuark quark_cache[100];
1126    XrmQuarkList quark_args;
1127    XrmResourceList *table;
1128    Cardinal ntyped_args = num_typed_args;
1129
1130#ifdef XTHREADS
1131    XtAppContext app;
1132#endif
1133    XtCacheRef *Resrc = NULL;
1134
1135    if (num_resources == 0)
1136        return;
1137
1138#ifdef XTHREADS
1139    if (w == NULL)
1140        app = _XtDefaultAppContext();
1141    else
1142        app = XtWidgetToApplicationContext(w);
1143#endif
1144
1145    LOCK_APP(app);
1146    /* Get full name, class of application */
1147    if (w == NULL) {
1148        /* hack for R2 compatibility */
1149        XtPerDisplay pd = _XtGetPerDisplay(_XtDefaultAppContext()->list[0]);
1150
1151        names = (XrmName *) XtStackAlloc(2 * sizeof(XrmName), names_s);
1152        classes = (XrmClass *) XtStackAlloc(2 * sizeof(XrmClass), classes_s);
1153        if (names == NULL || classes == NULL) {
1154            _XtAllocError(NULL);
1155        }
1156        else {
1157            names[0] = pd->name;
1158            names[1] = NULLQUARK;
1159            classes[0] = pd->class;
1160            classes[1] = NULLQUARK;
1161        }
1162    }
1163    else {
1164        Cardinal count = CountTreeDepth(w);
1165
1166        names = (XrmName *) XtStackAlloc(count * sizeof(XrmName), names_s);
1167        classes =
1168            (XrmClass *) XtStackAlloc(count * sizeof(XrmClass), classes_s);
1169        if (names == NULL || classes == NULL) {
1170            _XtAllocError(NULL);
1171        }
1172        else {
1173            GetNamesAndClasses(w, names, classes);
1174        }
1175    }
1176
1177    /* Compile arg list into quarks */
1178    CacheArgs(args, num_args, typed_args, num_typed_args, quark_cache,
1179              XtNumber(quark_cache), &quark_args);
1180    /* Compile resource list if needed */
1181    if (((int) resources->resource_offset) >= 0) {
1182        XrmCompileResourceListEphem(resources, num_resources);
1183    }
1184    table = _XtCreateIndirectionTable(resources, num_resources);
1185
1186    Resrc = GetResources(w, (char *) base, names, classes, table, num_resources,
1187                         quark_args, args, num_args,
1188                         typed_args, &ntyped_args, False);
1189    FreeCache(quark_cache, quark_args);
1190    XtFree((char *) table);
1191    XtFree((char *) Resrc);
1192    if (w != NULL) {
1193        XtStackFree((XtPointer) names, names_s);
1194        XtStackFree((XtPointer) classes, classes_s);
1195    }
1196    UNLOCK_APP(app);
1197}
1198
1199void
1200XtGetApplicationResources(Widget w,     /* Application shell widget       */
1201                          XtPointer base,       /* Base address to write to       */
1202                          XtResourceList resources,     /* resource list for subobject    */
1203                          Cardinal num_resources,
1204                          ArgList args, /* arg list to override resources */
1205                          Cardinal num_args)
1206{
1207    _XtGetApplicationResources(w, base, resources, num_resources, args,
1208                               num_args, NULL, 0);
1209}
1210
1211static Boolean initialized = FALSE;
1212
1213void
1214_XtResourceListInitialize(void)
1215{
1216    LOCK_PROCESS;
1217    if (initialized) {
1218        XtWarningMsg("initializationError", "xtInitialize", XtCXtToolkitError,
1219                     "Initializing Resource Lists twice", NULL, NULL);
1220        UNLOCK_PROCESS;
1221        return;
1222    }
1223    initialized = TRUE;
1224    UNLOCK_PROCESS;
1225
1226    QBoolean = XrmPermStringToQuark(XtCBoolean);
1227    QString = XrmPermStringToQuark(XtCString);
1228    QCallProc = XrmPermStringToQuark(XtRCallProc);
1229    QImmediate = XrmPermStringToQuark(XtRImmediate);
1230    QinitialResourcesPersistent =
1231        XrmPermStringToQuark(XtNinitialResourcesPersistent);
1232    QInitialResourcesPersistent =
1233        XrmPermStringToQuark(XtCInitialResourcesPersistent);
1234    Qtranslations = XrmPermStringToQuark(XtNtranslations);
1235    QbaseTranslations = XrmPermStringToQuark("baseTranslations");
1236    QTranslations = XrmPermStringToQuark(XtCTranslations);
1237    QTranslationTable = XrmPermStringToQuark(XtRTranslationTable);
1238    Qscreen = XrmPermStringToQuark(XtNscreen);
1239    QScreen = XrmPermStringToQuark(XtCScreen);
1240}
1241