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