1/***********************************************************
2Copyright (c) 1993, Oracle and/or its affiliates.
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) memcpy(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) memcpy(&u, 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) memcpy(&u, 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) (XtIntPtr) 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 = XtMallocArray(new_num_res, (Cardinal) sizeof(XrmResourceList));
378    if (super_num_res > 0)
379        memcpy(new_res, super_res, super_num_res * sizeof(XrmResourceList));
380
381    /* Put pointers to class resource entries into new_res */
382    new_next = super_num_res;
383    for (i = 0; i < class_num_res; i++) {
384        if ((Cardinal) (-class_res[i].xrm_offset - 1) < super_widget_size) {
385            /* Probably an override of superclass resources--look for overlap */
386            for (j = 0; j < super_num_res; j++) {
387                if (class_res[i].xrm_offset == new_res[j]->xrm_offset) {
388                    /* Spec is silent on what fields subclass can override.
389                     * The only two of real concern are type & size.
390                     * Although allowing type to be over-ridden introduces
391                     * the possibility of errors, it's at present the only
392                     * reasonable way to allow a subclass to force a private
393                     * converter to be invoked for a subset of fields.
394                     */
395                    /* We do insist that size be identical to superclass */
396                    if (class_res[i].xrm_size != new_res[j]->xrm_size) {
397                        BadSize(class_res[i].xrm_size,
398                                (XrmQuark) class_res[i].xrm_name);
399                        class_res[i].xrm_size = new_res[j]->xrm_size;
400                    }
401                    new_res[j] = &(class_res[i]);
402                    new_num_res--;
403                    goto NextResource;
404                }
405            }                   /* for j */
406        }
407        /* Not an overlap, add an entry to new_res */
408        new_res[new_next++] = &(class_res[i]);
409 NextResource:;
410    }                           /* for i */
411
412    /* Okay, stuff new resources back into class record */
413    *class_resp = (XtResourceList) new_res;
414    *class_num_resp = new_num_res;
415}                               /* _XtDependencies */
416
417void
418_XtResourceDependencies(WidgetClass wc)
419{
420    WidgetClass sc;
421
422    sc = wc->core_class.superclass;
423    if (sc == NULL) {
424        _XtDependencies(&(wc->core_class.resources),
425                        &(wc->core_class.num_resources),
426                        (XrmResourceList *) NULL, (unsigned) 0, (unsigned) 0);
427    }
428    else {
429        _XtDependencies(&(wc->core_class.resources),
430                        &(wc->core_class.num_resources),
431                        (XrmResourceList *) sc->core_class.resources,
432                        sc->core_class.num_resources,
433                        sc->core_class.widget_size);
434    }
435}                               /* _XtResourceDependencies */
436
437void
438_XtConstraintResDependencies(ConstraintWidgetClass wc)
439{
440    if (wc == (ConstraintWidgetClass) constraintWidgetClass) {
441        _XtDependencies(&(wc->constraint_class.resources),
442                        &(wc->constraint_class.num_resources),
443                        (XrmResourceList *) NULL, (unsigned) 0, (unsigned) 0);
444    }
445    else {
446        ConstraintWidgetClass sc;
447
448        sc = (ConstraintWidgetClass) wc->core_class.superclass;
449        _XtDependencies(&(wc->constraint_class.resources),
450                        &(wc->constraint_class.num_resources),
451                        (XrmResourceList *) sc->constraint_class.resources,
452                        sc->constraint_class.num_resources,
453                        sc->constraint_class.constraint_size);
454    }
455}                               /* _XtConstraintResDependencies */
456
457XrmResourceList *
458_XtCreateIndirectionTable(XtResourceList resources, Cardinal num_resources)
459{
460    register Cardinal idx;
461    XrmResourceList *table;
462
463    table = XtMallocArray(num_resources, (Cardinal) sizeof(XrmResourceList));
464    for (idx = 0; idx < num_resources; idx++)
465        table[idx] = (XrmResourceList) (&(resources[idx]));
466    return table;
467}
468
469static XtCacheRef *
470GetResources(Widget widget,             /* Widget resources are associated with */
471             char *base,                /* Base address of memory to write to */
472             XrmNameList names,         /* Full inheritance name of widget */
473             XrmClassList classes,      /* Full inheritance class of widget     */
474             XrmResourceList *table,    /* The list of resources required.      */
475             unsigned num_resources,    /* number of items in resource list     */
476             XrmQuarkList quark_args,   /* Arg names quarkified                 */
477             ArgList args,              /* ArgList to override resources */
478             unsigned num_args,         /* number of items in arg list  */
479             XtTypedArgList typed_args, /* Typed arg list to override resources */
480             Cardinal *pNumTypedArgs,   /* number of items in typed arg list    */
481             Boolean tm_hack)           /* do baseTranslations                  */
482{
483/*
484 * assert: *pNumTypedArgs == 0 if num_args > 0
485 * assert: num_args == 0 if *pNumTypedArgs > 0
486 */
487#define SEARCHLISTLEN 100
488#define MAXRESOURCES  400
489
490    XrmValue value;
491    XrmQuark rawType;
492    XrmValue convValue;
493    XrmHashTable stackSearchList[SEARCHLISTLEN];
494    XrmHashTable *searchList = stackSearchList;
495    unsigned int searchListSize = SEARCHLISTLEN;
496    Boolean found[MAXRESOURCES];
497    int typed[MAXRESOURCES];
498    XtCacheRef cache_ref[MAXRESOURCES];
499    XtCacheRef *cache_ptr, *cache_base;
500    Boolean persistent_resources = True;
501    Boolean found_persistence = False;
502    int num_typed_args = (int) *pNumTypedArgs;
503    XrmDatabase db;
504    Boolean do_tm_hack = False;
505
506    if ((args == NULL) && (num_args != 0)) {
507        XtAppWarningMsg(XtWidgetToApplicationContext(widget),
508                        "invalidArgCount", "getResources", XtCXtToolkitError,
509                        "argument count > 0 on NULL argument list", NULL, NULL);
510        num_args = 0;
511    }
512    if (num_resources == 0) {
513        return NULL;
514    }
515    else if (num_resources >= MAXRESOURCES) {
516        XtAppWarningMsg(XtWidgetToApplicationContext(widget),
517                        "invalidResourceCount", "getResources",
518                        XtCXtToolkitError, "too many resources", NULL, NULL);
519        return NULL;
520    }
521    else if (table == NULL) {
522        XtAppWarningMsg(XtWidgetToApplicationContext(widget),
523                        "invalidResourceCount", "getResources",
524                        XtCXtToolkitError,
525                        "resource count > 0 on NULL resource list", NULL, NULL);
526        return NULL;
527    }
528
529    /* Mark each resource as not found on arg list */
530    memset((void *) found, 0, (size_t) (num_resources * sizeof(Boolean)));
531    memset((void *) typed, 0, (size_t) (num_resources * sizeof(int)));
532
533    /* Copy the args into the resources, mark each as found */
534    {
535        register ArgList arg;
536        register XtTypedArgList typed_arg;
537        register XrmName argName;
538        register Cardinal j;
539        register int i;
540        register XrmResourceList rx;
541        register XrmResourceList *res;
542
543        for (arg = args, i = 0; (Cardinal) i < num_args; i++, arg++) {
544            argName = quark_args[i];
545            if (argName == QinitialResourcesPersistent) {
546                persistent_resources = (Boolean) arg->value;
547                found_persistence = True;
548                continue;
549            }
550            for (j = 0, res = table; j < num_resources; j++, res++) {
551                rx = *res;
552                if (argName == rx->xrm_name) {
553                    _XtCopyFromArg(arg->value,
554                                   base - rx->xrm_offset - 1, rx->xrm_size);
555                    found[j] = TRUE;
556                    break;
557                }
558            }
559        }
560        for (typed_arg = typed_args, i = 0; i < num_typed_args;
561             i++, typed_arg++) {
562            register XrmRepresentation argType;
563
564            argName = quark_args[i];
565            argType = (typed_arg->type == NULL) ? NULLQUARK
566                : XrmStringToRepresentation(typed_arg->type);
567            if (argName == QinitialResourcesPersistent) {
568                persistent_resources = (Boolean) typed_arg->value;
569                found_persistence = True;
570                break;
571            }
572            for (j = 0, res = table; j < num_resources; j++, res++) {
573                rx = *res;
574                if (argName == rx->xrm_name) {
575                    if (argType != NULLQUARK && argType != rx->xrm_type) {
576                        typed[j] = i + 1;
577                    }
578                    else {
579                        _XtCopyFromArg(typed_arg->value,
580                                       base - rx->xrm_offset - 1, rx->xrm_size);
581                    }
582                    found[j] = TRUE;
583                    break;
584                }
585            }
586        }
587    }
588
589    /* Ask resource manager for a list of database levels that we can
590       do a single-level search on each resource */
591
592    db = XtScreenDatabase(XtScreenOfObject(widget));
593    while (!XrmQGetSearchList(db, names, classes,
594                              searchList, (int) searchListSize)) {
595        if (searchList == stackSearchList)
596            searchList = NULL;
597        searchListSize *= 2;
598        searchList = XtReallocArray(searchList, searchListSize,
599                                    (Cardinal) sizeof(XrmHashTable));
600    }
601
602    if (persistent_resources)
603        cache_base = NULL;
604    else
605        cache_base = cache_ref;
606    /* geez, this is an ugly mess */
607    if (XtIsShell(widget)) {
608        register XrmResourceList *res;
609        register Cardinal j;
610        Screen *oldscreen = widget->core.screen;
611
612        /* look up screen resource first, since real rdb depends on it */
613        for (res = table, j = 0; j < num_resources; j++, res++) {
614            if ((*res)->xrm_name != Qscreen)
615                continue;
616            if (typed[j]) {
617                register XtTypedArg *arg = typed_args + typed[j] - 1;
618                XrmQuark from_type;
619                XrmValue from_val, to_val;
620
621                from_type = StringToQuark(arg->type);
622                from_val.size = (Cardinal) arg->size;
623                if ((from_type == QString) ||
624                    ((unsigned) arg->size > sizeof(XtArgVal)))
625                    from_val.addr = (XPointer) arg->value;
626                else
627                    from_val.addr = (XPointer) &arg->value;
628                to_val.size = sizeof(Screen *);
629                to_val.addr = (XPointer) &widget->core.screen;
630                found[j] = _XtConvert(widget, from_type, &from_val,
631                                      QScreen, &to_val, cache_base);
632                if (cache_base && *cache_base)
633                    cache_base++;
634            }
635            if (!found[j]) {
636                if (XrmQGetSearchResource(searchList, Qscreen, QScreen,
637                                          &rawType, &value)) {
638                    if (rawType != QScreen) {
639                        convValue.size = sizeof(Screen *);
640                        convValue.addr = (XPointer) &widget->core.screen;
641                        (void) _XtConvert(widget, rawType, &value,
642                                          QScreen, &convValue, cache_base);
643                        if (cache_base && *cache_base)
644                            cache_base++;
645                    }
646                    else {
647                        widget->core.screen = *((Screen **) value.addr);
648                    }
649                }
650            }
651            break;
652        }
653        /* now get the database to use for the rest of the resources */
654        if (widget->core.screen != oldscreen) {
655            db = XtScreenDatabase(widget->core.screen);
656            while (!XrmQGetSearchList(db, names, classes,
657                                      searchList, (int) searchListSize)) {
658                if (searchList == stackSearchList)
659                    searchList = NULL;
660                searchList = (XrmHashTable *) XtRealloc((char *) searchList,
661                                                        (Cardinal) (sizeof
662                                                                    (XrmHashTable)
663                                                                    *
664                                                                    (searchListSize
665                                                                     *= 2)));
666            }
667        }
668    }
669
670    /* go to the resource manager for those resources not found yet */
671    /* if it's not in the resource database use the default value   */
672
673    {
674        register XrmResourceList rx;
675        register XrmResourceList *res;
676        register Cardinal j;
677        register XrmRepresentation xrm_type;
678        register XrmRepresentation xrm_default_type;
679        char char_val;
680        short short_val;
681        int int_val;
682        long long_val;
683        char *char_ptr;
684
685        if (!found_persistence) {
686            if (XrmQGetSearchResource(searchList, QinitialResourcesPersistent,
687                                      QInitialResourcesPersistent, &rawType,
688                                      &value)) {
689                if (rawType != QBoolean) {
690                    convValue.size = sizeof(Boolean);
691                    convValue.addr = (XPointer) &persistent_resources;
692                    (void) _XtConvert(widget, rawType, &value, QBoolean,
693                                      &convValue, NULL);
694                }
695                else
696                    persistent_resources = *(Boolean *) value.addr;
697            }
698        }
699        if (persistent_resources)
700            cache_ptr = NULL;
701        else if (cache_base)
702            cache_ptr = cache_base;
703        else
704            cache_ptr = cache_ref;
705
706        for (res = table, j = 0; j < num_resources; j++, res++) {
707            rx = *res;
708            xrm_type = (XrmRepresentation) rx->xrm_type;
709            if (typed[j]) {
710                register XtTypedArg *arg = typed_args + typed[j] - 1;
711
712                /*
713                 * This resource value has been specified as a typed arg and
714                 * has to be converted. Typed arg conversions are done here
715                 * to correctly interpose them with normal resource conversions.
716                 */
717                XrmQuark from_type;
718                XrmValue from_val, to_val;
719                Boolean converted;
720
721                from_type = StringToQuark(arg->type);
722                from_val.size = (Cardinal) arg->size;
723                if ((from_type == QString) ||
724                    ((unsigned) arg->size > sizeof(XtArgVal)))
725                    from_val.addr = (XPointer) arg->value;
726                else
727                    from_val.addr = (XPointer) &arg->value;
728                to_val.size = rx->xrm_size;
729                to_val.addr = base - rx->xrm_offset - 1;
730                converted = _XtConvert(widget, from_type, &from_val,
731                                       xrm_type, &to_val, cache_ptr);
732                if (converted) {
733
734                    /* Copy the converted value back into the typed argument.
735                     * normally the data should be <= sizeof(XtArgVal) and
736                     * is stored directly into the 'value' field .... BUT
737                     * if the resource size is greater than sizeof(XtArgVal)
738                     * then we dynamically alloc a block of store to hold the
739                     * data and zap a copy in there !!! .... freeing it later
740                     * the size field in the typed arg is negated to indicate
741                     * that the store pointed to by the value field is
742                     * dynamic .......
743                     * "freeing" happens in the case of _XtCreate after the
744                     * CallInitialize ..... other clients of GetResources
745                     * using typed args should be aware of the need to free
746                     * this store .....
747                     */
748
749                    if (rx->xrm_size > sizeof(XtArgVal)) {
750                        arg->value =
751                            (XtArgVal) (void *) __XtMalloc(rx->xrm_size);
752                        arg->size = -(arg->size);
753                    }
754                    else {      /* will fit - copy directly into value field */
755                        arg->value = (XtArgVal) NULL;
756                    }
757                    CopyToArg((char *) (base - rx->xrm_offset - 1),
758                              &arg->value, rx->xrm_size);
759
760                }
761                else {
762                    /* Conversion failed. Get default value. */
763                    found[j] = False;
764                }
765
766                if (cache_ptr && *cache_ptr)
767                    cache_ptr++;
768            }
769
770            if (!found[j]) {
771                Boolean already_copied = False;
772                Boolean have_value = False;
773
774                if (XrmQGetSearchResource(searchList,
775                                          (XrmName) rx->xrm_name,
776                                          (XrmClass) rx->xrm_class, &rawType,
777                                          &value)) {
778                    if (rawType != xrm_type) {
779                        convValue.size = rx->xrm_size;
780                        convValue.addr = (XPointer) (base - rx->xrm_offset - 1);
781                        already_copied = have_value =
782                            _XtConvert(widget, rawType, &value,
783                                       xrm_type, &convValue, cache_ptr);
784                        if (cache_ptr && *cache_ptr)
785                            cache_ptr++;
786                    }
787                    else
788                        have_value = True;
789                    if (have_value && rx->xrm_name == Qtranslations)
790                        do_tm_hack = True;
791                }
792                LOCK_PROCESS;
793                if (!have_value && ((rx->xrm_default_type == QImmediate)
794                                    || (rx->xrm_default_type == xrm_type)
795                                    || (rx->xrm_default_addr != NULL))) {
796                    /* Convert default value to proper type */
797                    xrm_default_type = (XrmRepresentation) rx->xrm_default_type;
798                    if (xrm_default_type == QCallProc) {
799                        (*(XtResourceDefaultProc) (rx->xrm_default_addr))
800                            (widget, -(rx->xrm_offset + 1), &value);
801
802                    }
803                    else if (xrm_default_type == QImmediate) {
804                        /* XtRImmediate == XtRString for type XtRString */
805                        if (xrm_type == QString) {
806                            value.addr = rx->xrm_default_addr;
807                        }
808                        else if (rx->xrm_size == sizeof(int)) {
809                            int_val = (int) (long) rx->xrm_default_addr;
810                            value.addr = (XPointer) &int_val;
811                        }
812                        else if (rx->xrm_size == sizeof(short)) {
813                            short_val = (short) (long) rx->xrm_default_addr;
814                            value.addr = (XPointer) &short_val;
815                        }
816                        else if (rx->xrm_size == sizeof(char)) {
817                            char_val = (char) (long) rx->xrm_default_addr;
818                            value.addr = (XPointer) &char_val;
819                        }
820                        else if (rx->xrm_size == sizeof(long)) {
821                            long_val = (long) rx->xrm_default_addr;
822                            value.addr = (XPointer) &long_val;
823                        }
824                        else if (rx->xrm_size == sizeof(char *)) {
825                            char_ptr = (char *) rx->xrm_default_addr;
826                            value.addr = (XPointer) &char_ptr;
827                        }
828                        else {
829                            value.addr = (XPointer) &(rx->xrm_default_addr);
830                        }
831                    }
832                    else if (xrm_default_type == xrm_type) {
833                        value.addr = rx->xrm_default_addr;
834                    }
835                    else {
836                        value.addr = rx->xrm_default_addr;
837                        if (xrm_default_type == QString) {
838                            value.size =
839                                (unsigned) strlen((char *) value.addr) + 1;
840                        }
841                        else {
842                            value.size = sizeof(XtPointer);
843                        }
844                        convValue.size = rx->xrm_size;
845                        convValue.addr = (XPointer) (base - rx->xrm_offset - 1);
846                        already_copied =
847                            _XtConvert(widget, xrm_default_type, &value,
848                                       xrm_type, &convValue, cache_ptr);
849                        if (!already_copied)
850                            value.addr = NULL;
851                        if (cache_ptr && *cache_ptr)
852                            cache_ptr++;
853                    }
854                }
855                if (!already_copied) {
856                    if (xrm_type == QString) {
857                        *((String *) (base - rx->xrm_offset - 1)) = value.addr;
858                    }
859                    else {
860                        if (value.addr != NULL) {
861                            XtMemmove(base - rx->xrm_offset - 1,
862                                      value.addr, rx->xrm_size);
863                        }
864                        else {
865                            /* didn't get value, initialize to NULL... */
866                            XtBZero(base - rx->xrm_offset - 1, rx->xrm_size);
867                        }
868                    }
869                }
870                UNLOCK_PROCESS;
871            }
872        }
873        for (res = table, j = 0; j < num_resources; j++, res++) {
874            if (!found[j] && typed[j]) {
875                /*
876                 * This resource value was specified as a typed arg.
877                 * However, the default value is being used here since
878                 * type type conversion failed, so we compress the list.
879                 */
880                register XtTypedArg *arg = typed_args + typed[j] - 1;
881                register int i;
882
883                for (i = num_typed_args - typed[j]; i > 0; i--, arg++) {
884                    *arg = *(arg + 1);
885                }
886                num_typed_args--;
887            }
888        }
889        if (tm_hack)
890            widget->core.tm.current_state = NULL;
891        if (tm_hack &&
892            (!widget->core.tm.translations ||
893             (do_tm_hack &&
894              widget->core.tm.translations->operation != XtTableReplace)) &&
895            XrmQGetSearchResource(searchList, QbaseTranslations,
896                                  QTranslations, &rawType, &value)) {
897            if (rawType != QTranslationTable) {
898                convValue.size = sizeof(XtTranslations);
899                convValue.addr = (XPointer) &widget->core.tm.current_state;
900                (void) _XtConvert(widget, rawType, &value,
901                                  QTranslationTable, &convValue, cache_ptr);
902                if (cache_ptr && *cache_ptr)
903                    cache_ptr++;
904            }
905            else {
906                /* value.addr can be NULL see: !already_copied */
907                if (value.addr)
908                    *((XtTranslations *) &widget->core.tm.current_state) =
909                        *((XtTranslations *) value.addr);
910            }
911        }
912    }
913    if ((Cardinal) num_typed_args != *pNumTypedArgs)
914        *pNumTypedArgs = (Cardinal) num_typed_args;
915    if (searchList != stackSearchList)
916        XtFree((char *) searchList);
917    if (!cache_ptr)
918        cache_ptr = cache_base;
919    if (cache_ptr && cache_ptr != cache_ref) {
920        int cache_ref_size = (int) (cache_ptr - cache_ref);
921        XtCacheRef *refs = XtMallocArray((Cardinal) cache_ref_size + 1,
922                                         (Cardinal) sizeof(XtCacheRef));
923
924        (void) memcpy(refs, cache_ref,
925                      sizeof(XtCacheRef) * (size_t) cache_ref_size);
926        refs[cache_ref_size] = NULL;
927        return refs;
928    }
929    return (XtCacheRef *) NULL;
930}
931
932static void
933CacheArgs(ArgList args,
934          Cardinal num_args,
935          XtTypedArgList typed_args,
936          Cardinal num_typed_args,
937          XrmQuarkList quark_cache,
938          Cardinal num_quarks,
939          XrmQuarkList *pQuarks)        /* RETURN */
940{
941    register XrmQuarkList quarks;
942    register Cardinal i;
943    register Cardinal count;
944
945    count = (args != NULL) ? num_args : num_typed_args;
946
947    if (num_quarks < count) {
948        quarks = XtMallocArray(count, (Cardinal) sizeof(XrmQuark));
949    }
950    else {
951        quarks = quark_cache;
952    }
953    *pQuarks = quarks;
954
955    if (args != NULL) {
956        for (i = count; i; i--)
957            *quarks++ = StringToQuark((args++)->name);
958    }
959    else {
960        for (i = count; i; i--)
961            *quarks++ = StringToQuark((typed_args++)->name);
962    }
963}
964
965#define FreeCache(cache, pointer) \
966          if (cache != pointer) XtFree((char *)pointer)
967
968XtCacheRef *
969_XtGetResources(register Widget w,
970                ArgList args,
971                Cardinal num_args,
972                XtTypedArgList typed_args,
973                Cardinal *num_typed_args)
974{
975    XrmName *names, names_s[50];
976    XrmClass *classes, classes_s[50];
977    XrmQuark quark_cache[100];
978    XrmQuarkList quark_args;
979    WidgetClass wc;
980    XtCacheRef *cache_refs = NULL;
981    Cardinal count;
982
983    wc = XtClass(w);
984
985    count = CountTreeDepth(w);
986    names = (XrmName *) XtStackAlloc(count * sizeof(XrmName), names_s);
987    classes = (XrmClass *) XtStackAlloc(count * sizeof(XrmClass), classes_s);
988    if (names == NULL || classes == NULL) {
989        _XtAllocError(NULL);
990    }
991    else {
992
993        /* Get names, classes for widget and ancestors */
994        GetNamesAndClasses(w, names, classes);
995
996        /* Compile arg list into quarks */
997        CacheArgs(args, num_args, typed_args, *num_typed_args, quark_cache,
998                  XtNumber(quark_cache), &quark_args);
999
1000        /* Get normal resources */
1001        LOCK_PROCESS;
1002        cache_refs = GetResources(w, (char *) w, names, classes,
1003                                  (XrmResourceList *) wc->core_class.resources,
1004                                  wc->core_class.num_resources, quark_args,
1005                                  args, num_args, typed_args, num_typed_args,
1006                                  XtIsWidget(w));
1007
1008        if (w->core.constraints != NULL) {
1009            ConstraintWidgetClass cwc;
1010            XtCacheRef *cache_refs_core;
1011
1012            cwc = (ConstraintWidgetClass) XtClass(w->core.parent);
1013            cache_refs_core =
1014                GetResources(w, (char *) w->core.constraints, names, classes,
1015                             (XrmResourceList *) cwc->constraint_class.
1016                             resources, cwc->constraint_class.num_resources,
1017                             quark_args, args, num_args, typed_args,
1018                             num_typed_args, False);
1019            XtFree((char *) cache_refs_core);
1020        }
1021        FreeCache(quark_cache, quark_args);
1022        UNLOCK_PROCESS;
1023        XtStackFree((XtPointer) names, names_s);
1024        XtStackFree((XtPointer) classes, classes_s);
1025    }
1026    return cache_refs;
1027}                               /* _XtGetResources */
1028
1029void
1030_XtGetSubresources(Widget w,                    /* Widget "parent" of subobject */
1031                   XtPointer base,              /* Base address to write to */
1032                   const char *name,            /* name of subobject        */
1033                   const char *class,           /* class of subobject       */
1034                   XtResourceList resources,    /* resource list for subobject    */
1035                   Cardinal num_resources,
1036                   ArgList args,                /* arg list to override resources */
1037                   Cardinal num_args,
1038                   XtTypedArgList typed_args,
1039                   Cardinal num_typed_args)
1040{
1041    XrmName *names, names_s[50];
1042    XrmClass *classes, classes_s[50];
1043    XrmQuark quark_cache[100];
1044    XrmQuarkList quark_args;
1045    Cardinal count, ntyped_args = num_typed_args;
1046    XtCacheRef *Resrc = NULL;
1047
1048    WIDGET_TO_APPCON(w);
1049
1050    if (num_resources == 0)
1051        return;
1052
1053    LOCK_APP(app);
1054    count = CountTreeDepth(w);
1055    count++;                    /* make sure there's enough room for name and class */
1056    names = (XrmName *) XtStackAlloc(count * sizeof(XrmName), names_s);
1057    classes = (XrmClass *) XtStackAlloc(count * sizeof(XrmClass), classes_s);
1058    if (names == NULL || classes == NULL) {
1059        _XtAllocError(NULL);
1060    }
1061    else {
1062        XrmResourceList *table;
1063
1064        /* Get full name, class of subobject */
1065        GetNamesAndClasses(w, names, classes);
1066        count -= 2;
1067        names[count] = StringToName(name);
1068        classes[count] = StringToClass(class);
1069        count++;
1070        names[count] = NULLQUARK;
1071        classes[count] = NULLQUARK;
1072
1073        /* Compile arg list into quarks */
1074        CacheArgs(args, num_args, typed_args, num_typed_args,
1075                  quark_cache, XtNumber(quark_cache), &quark_args);
1076
1077        /* Compile resource list if needed */
1078        if (((int) resources->resource_offset) >= 0) {
1079            XrmCompileResourceListEphem(resources, num_resources);
1080        }
1081        table = _XtCreateIndirectionTable(resources, num_resources);
1082        Resrc =
1083            GetResources(w, (char *) base, names, classes, table, num_resources,
1084                         quark_args, args, num_args, typed_args, &ntyped_args,
1085                         False);
1086        FreeCache(quark_cache, quark_args);
1087        XtFree((char *) table);
1088        XtFree((char *) Resrc);
1089        XtStackFree((XtPointer) names, names_s);
1090        XtStackFree((XtPointer) classes, classes_s);
1091        UNLOCK_APP(app);
1092    }
1093}
1094
1095void
1096XtGetSubresources(Widget w,                     /* Widget "parent" of subobject */
1097                  XtPointer base,               /* Base address to write to */
1098                  _Xconst char *name,           /* name of subobject        */
1099                  _Xconst char *class,          /* class of subobject       */
1100                  XtResourceList resources,     /* resource list for subobject    */
1101                  Cardinal num_resources,
1102                  ArgList args,                 /* arg list to override resources */
1103                  Cardinal num_args)
1104{
1105    _XtGetSubresources(w, base, name, class, resources, num_resources, args,
1106                       num_args, NULL, 0);
1107}
1108
1109void
1110_XtGetApplicationResources(Widget w,            /* Application shell widget */
1111                           XtPointer base,      /* Base address to write to       */
1112                           XtResourceList resources,    /* resource list for subobject    */
1113                           Cardinal num_resources,
1114                           ArgList args,        /* arg list to override resources */
1115                           Cardinal num_args,
1116                           XtTypedArgList typed_args,
1117                           Cardinal num_typed_args)
1118{
1119    XrmName *names, names_s[50];
1120    XrmClass *classes, classes_s[50];
1121    XrmQuark quark_cache[100];
1122    XrmQuarkList quark_args;
1123    XrmResourceList *table;
1124    Cardinal ntyped_args = num_typed_args;
1125
1126#ifdef XTHREADS
1127    XtAppContext app;
1128#endif
1129    XtCacheRef *Resrc = NULL;
1130
1131    if (num_resources == 0)
1132        return;
1133
1134#ifdef XTHREADS
1135    if (w == NULL)
1136        app = _XtDefaultAppContext();
1137    else
1138        app = XtWidgetToApplicationContext(w);
1139#endif
1140
1141    LOCK_APP(app);
1142    /* Get full name, class of application */
1143    if (w == NULL) {
1144        /* hack for R2 compatibility */
1145        XtPerDisplay pd = _XtGetPerDisplay(_XtDefaultAppContext()->list[0]);
1146
1147        names = (XrmName *) XtStackAlloc(2 * sizeof(XrmName), names_s);
1148        classes = (XrmClass *) XtStackAlloc(2 * sizeof(XrmClass), classes_s);
1149        if (names == NULL || classes == NULL) {
1150            _XtAllocError(NULL);
1151        }
1152        else {
1153            names[0] = pd->name;
1154            names[1] = NULLQUARK;
1155            classes[0] = pd->class;
1156            classes[1] = NULLQUARK;
1157        }
1158    }
1159    else {
1160        Cardinal count = CountTreeDepth(w);
1161
1162        names = (XrmName *) XtStackAlloc(count * sizeof(XrmName), names_s);
1163        classes =
1164            (XrmClass *) XtStackAlloc(count * sizeof(XrmClass), classes_s);
1165        if (names == NULL || classes == NULL) {
1166            _XtAllocError(NULL);
1167        }
1168        else {
1169            GetNamesAndClasses(w, names, classes);
1170        }
1171    }
1172
1173    /* Compile arg list into quarks */
1174    CacheArgs(args, num_args, typed_args, num_typed_args, quark_cache,
1175              XtNumber(quark_cache), &quark_args);
1176    /* Compile resource list if needed */
1177    if (((int) resources->resource_offset) >= 0) {
1178        XrmCompileResourceListEphem(resources, num_resources);
1179    }
1180    table = _XtCreateIndirectionTable(resources, num_resources);
1181
1182    Resrc = GetResources(w, (char *) base, names, classes, table, num_resources,
1183                         quark_args, args, num_args,
1184                         typed_args, &ntyped_args, False);
1185    FreeCache(quark_cache, quark_args);
1186    XtFree((char *) table);
1187    XtFree((char *) Resrc);
1188    if (w != NULL) {
1189        XtStackFree((XtPointer) names, names_s);
1190        XtStackFree((XtPointer) classes, classes_s);
1191    }
1192    UNLOCK_APP(app);
1193}
1194
1195void
1196XtGetApplicationResources(Widget w,     /* Application shell widget       */
1197                          XtPointer base,       /* Base address to write to       */
1198                          XtResourceList resources,     /* resource list for subobject    */
1199                          Cardinal num_resources,
1200                          ArgList args, /* arg list to override resources */
1201                          Cardinal num_args)
1202{
1203    _XtGetApplicationResources(w, base, resources, num_resources, args,
1204                               num_args, NULL, 0);
1205}
1206
1207static Boolean initialized = FALSE;
1208
1209void
1210_XtResourceListInitialize(void)
1211{
1212    LOCK_PROCESS;
1213    if (initialized) {
1214        XtWarningMsg("initializationError", "xtInitialize", XtCXtToolkitError,
1215                     "Initializing Resource Lists twice", NULL, NULL);
1216        UNLOCK_PROCESS;
1217        return;
1218    }
1219    initialized = TRUE;
1220    UNLOCK_PROCESS;
1221
1222    QBoolean = XrmPermStringToQuark(XtCBoolean);
1223    QString = XrmPermStringToQuark(XtCString);
1224    QCallProc = XrmPermStringToQuark(XtRCallProc);
1225    QImmediate = XrmPermStringToQuark(XtRImmediate);
1226    QinitialResourcesPersistent =
1227        XrmPermStringToQuark(XtNinitialResourcesPersistent);
1228    QInitialResourcesPersistent =
1229        XrmPermStringToQuark(XtCInitialResourcesPersistent);
1230    Qtranslations = XrmPermStringToQuark(XtNtranslations);
1231    QbaseTranslations = XrmPermStringToQuark("baseTranslations");
1232    QTranslations = XrmPermStringToQuark(XtCTranslations);
1233    QTranslationTable = XrmPermStringToQuark(XtRTranslationTable);
1234    Qscreen = XrmPermStringToQuark(XtNscreen);
1235    QScreen = XrmPermStringToQuark(XtCScreen);
1236}
1237