1 /*
2  * Motif Tools Library, Version 3.1
3  * $Id: Symbols.c,v 1.2 2001/09/19 02:57:18 grmcdorman Exp $
4  *
5  * Written by David Flanagan.
6  * Copyright (c) 1992-2001 by David Flanagan.
7  * All Rights Reserved.  See the file COPYRIGHT for details.
8  * This is open source software.  See the file LICENSE for details.
9  * There is no warranty for this software.  See NO_WARRANTY for details.
10  *
11  * $Log: Symbols.c,v $
12  * Revision 1.2  2001/09/19 02:57:18  grmcdorman
13  * This change makes the following modifications:
14  *   A new program, printConfig, is provided. This is built by a
15  *   simple rule in the Makefile and not installed. It prints
16  *   significant defines from Xmt.tmpl.
17  *
18  *   XmtP.h is now generated from XmtP.h.in using printConfig. As
19  *   a result, code compiled outside of the Xmt Imakefiles will
20  *   have all of the Xmt.tmpl defines.
21  *
22  *   Source files are modified to use XmtP.h instead of Xmt.h.
23  *
24  *   WorkingBox.c is modified to use the new Progress widget.
25  *   It can be compiled in the old style if WORKINGBOX_USE_SCALE is
26  *   defined at compile time.
27  *
28  *   Because XmtP.h is generated dynamically, it is removed from CVS
29  *   with this check-in.
30  *
31  * Revision 1.1.1.1  2001/02/10 13:50:55  motiftools
32  * Initial import of Xmt310 to CVS
33  *
34  *
35  */
36 
37 #include <Xmt/XmtP.h>
38 #include <Xmt/Symbols.h>
39 #include <Xmt/Hash.h>
40 #include <Xmt/QuarksP.h>
41 #include <X11/IntrinsicP.h>
42 
43 /*
44  * values for the XmtSymbolRec mode field.
45  */
46 #define XmtSymbolABSOLUTE   1
47 #define XmtSymbolIMMEDIATE  2
48 #define XmtSymbolRESOURCE   3
49 
50 static XmtHashTable symbol_table = NULL;
51 
52 #if NeedFunctionPrototypes
GetResourceTypeAndSize(Widget w,String resource_name,XrmQuark * type,Cardinal * size)53 static void GetResourceTypeAndSize(Widget w, String resource_name,
54 				   XrmQuark *type, Cardinal *size)
55 #else
56 static void GetResourceTypeAndSize(w, resource_name, type, size)
57 Widget w;
58 String resource_name;
59 XrmQuark *type;
60 Cardinal *size;
61 #endif
62 {
63     int i;
64     Boolean found = False;
65     WidgetClass c = XtClass(w);
66     XtResourceList *list = (XtResourceList *) c->core_class.resources;
67     XrmQuark name = XrmStringToQuark(resource_name);
68 
69     /* check normal resources first */
70     /* Note that we assume knowledge of the compiled resource format */
71     for(i=0; i < c->core_class.num_resources; i++) {
72 	if ((list[i] != NULL) &&
73 	    ((XrmName)list[i]->resource_name == name)) {
74 	    found = True;
75 	    break;
76 	}
77     }
78 
79     /* check constraint resources if parent is constraint */
80     if (!found && XtParent(w) && XtIsConstraint(XtParent(w))) {
81 	ConstraintWidgetClass c =
82 	    (ConstraintWidgetClass) XtClass(XtParent(w));
83 	list = (XtResourceList *) c->constraint_class.resources;
84 	for(i = 0; i < c->constraint_class.num_resources; i++) {
85 	    if ((list[i] != NULL) &&
86 		((XrmName)list[i]->resource_name == name)) {
87 		found = True;
88 		break;
89 	    }
90 	}
91     }
92 
93     if (found) {
94 	*type = (XrmQuark)list[i]->resource_type;
95 	*size = list[i]->resource_size;
96     }
97 }
98 
99 /*
100  * s must be in static memory, or at least in memory that will never
101  * be freed.  s->name must be the same.  For statically declared arrays
102  * of symbols this is the usual case.  For dynamically created symbols,
103  * the programmer must make a copy of the name in allocated memory.
104  */
105 #if NeedFunctionPrototypes
XmtRegisterSymbol(XmtSymbol s)106 void XmtRegisterSymbol(XmtSymbol s)
107 #else
108 void XmtRegisterSymbol(s)
109 XmtSymbol s;
110 #endif
111 {
112     XrmName name;
113 
114     if (symbol_table == NULL)
115 	symbol_table = XmtHashTableCreate(3);
116 
117     if (s->addr == 0) {  /* symbol is an immediate value */
118 	/*
119 	 * if size > sizeof(XtPointer), an immediate value won't
120 	 * actually fit, so issue error msg. and exit.
121 	 */
122 	if (s->size > sizeof(s->addr))
123 	    XmtErrorMsg("XmtSymbol", "size",
124 			"Symbol '%s' has size too big for immediate mode.",
125 			s->name);
126 	s->mode = XmtSymbolIMMEDIATE;
127 	s->type = (String)XrmStringToQuark(s->type);
128     }
129     else if (s->resource_name) {  /* symbol is a widget resource */
130 	GetResourceTypeAndSize((Widget)s->addr, s->resource_name,
131 			       (XrmQuark *) &s->type, &s->size);
132 	s->mode = XmtSymbolRESOURCE;
133     }
134     else {
135 	s->mode = XmtSymbolABSOLUTE;
136 	s->type = (String)XrmStringToQuark(s->type);
137     }
138 
139     name = XrmPermStringToQuark(s->name);
140     XmtHashTableStore(symbol_table, (XtPointer)name, (XtPointer)s);
141 }
142 
143 
144 /*
145  * The symbol records and the string within must be permanently allocated
146  */
147 #if NeedFunctionPrototypes
XmtRegisterSymbols(XmtSymbolRec * syms,Cardinal num_syms)148 void XmtRegisterSymbols(XmtSymbolRec *syms, Cardinal num_syms)
149 #else
150 void XmtRegisterSymbols(syms, num_syms)
151 XmtSymbolRec *syms;
152 Cardinal num_syms;
153 #endif
154 {
155     int i;
156     for(i=0; i < num_syms; i++)	XmtRegisterSymbol(&syms[i]);
157 }
158 
159 /*
160  * All strings must be permanently allocated, and may not change
161  */
162 #if NeedVarargsPrototypes
XmtVaRegisterSymbols(StringConst name,...)163 void XmtVaRegisterSymbols(StringConst name, ...)
164 #else
165 void XmtVaRegisterSymbols(name, va_alist)
166 StringConst name;
167 va_dcl
168 #endif
169 {
170     va_list var;
171     XmtSymbol sym;
172 
173     Va_start(var, name);
174 
175     while(name) {
176 	sym = (XmtSymbol) XtCalloc(1, sizeof(XmtSymbolRec));
177 	sym->name = (String) name;
178 	sym->type = va_arg(var, String);
179 	sym->size = va_arg(var, int);
180 	sym->addr = va_arg(var, XtPointer);
181 	XmtRegisterSymbol(sym);
182 	name = va_arg(var, String);
183     }
184 
185     va_end(var);
186 }
187 
188 #if NeedFunctionPrototypes
XmtRegisterResourceList(XtPointer base,XtResourceList resources,Cardinal num_resources)189 void XmtRegisterResourceList(XtPointer base,
190 			     XtResourceList resources, Cardinal num_resources)
191 #else
192 void XmtRegisterResourceList(base, resources, num_resources)
193 XtPointer base;
194 XtResourceList resources;
195 Cardinal num_resources;
196 #endif
197 {
198     int i;
199     XmtSymbolRec *syms = (XmtSymbolRec *)XtCalloc(num_resources,
200 						  sizeof(XmtSymbolRec));
201 
202     /*
203      * This procedure knows about the Intrinsics compiled resource format.
204      * This is a little dangerous.
205      */
206     if (((int) resources[0].resource_offset) >= 0) { /* uncompiled */
207 	for(i=0; i < num_resources; i++) {
208 	    syms[i].name = resources[i].resource_name;
209 	    syms[i].type = resources[i].resource_type;
210 	    syms[i].size = resources[i].resource_size;
211 	    syms[i].addr = (XtPointer)
212 		(resources[i].resource_offset + (char *)base);
213 	}
214     }
215     else {  /* compiled */
216 #define tostring(s) XrmQuarkToString((XrmQuark)s)
217 	for(i=0; i < num_resources; i++) {
218 	    syms[i].name = tostring(resources[i].resource_name);
219 	    syms[i].type = tostring(resources[i].resource_type);
220 	    syms[i].size = resources[i].resource_size;
221 	    syms[i].addr = (XtPointer)
222 		(-resources[i].resource_offset - 1 + (char *)base);
223 	}
224 #undef tostring
225     }
226 
227     XmtRegisterSymbols(syms, num_resources);
228 }
229 
230 #if NeedFunctionPrototypes
XmtRegisterWidgetResource(StringConst name,Widget w,StringConst res)231 void XmtRegisterWidgetResource(StringConst name, Widget w, StringConst res)
232 #else
233 void XmtRegisterWidgetResource(name, w, res)
234 StringConst name;
235 Widget w;
236 StringConst res;
237 #endif
238 {
239     XmtSymbol s = (XmtSymbol) XtCalloc(1, sizeof(XmtSymbolRec));
240 
241     s->name = (String) name;
242     s->addr = (XtPointer) w;
243     s->resource_name = (String) res;
244     XmtRegisterSymbol(s);
245 }
246 
247 
248 #if NeedFunctionPrototypes
XmtLookupSymbol(StringConst name)249 XmtSymbol XmtLookupSymbol(StringConst name)
250 #else
251 XmtSymbol XmtLookupSymbol(name)
252 StringConst name;
253 #endif
254 {
255     XmtSymbol s;
256     XrmQuark q = XrmStringToQuark(name);
257 
258     if (!symbol_table) return NULL;
259     if (XmtHashTableLookup(symbol_table,(XtPointer)q, (XtPointer *)&s))
260 	return s;
261     else
262 	return NULL;
263 }
264 
265 #if NeedFunctionPrototypes
XmtSymbolSetValue(XmtSymbol s,XtArgVal value)266 void XmtSymbolSetValue(XmtSymbol s, XtArgVal value)
267 #else
268 void XmtSymbolSetValue(s, value)
269 XmtSymbol s;
270 XtArgVal value;
271 #endif
272 {
273     XmtSymbolCallbackRec *p;
274     extern void _XtCopyFromArg();
275     int index;
276 
277     /*
278      * Special case for XmtRBuffer type symbols.
279      * we copy the NULL-terminated string, and warn if it is too
280      * large for the buffer.
281      * XXX
282      * we should do sanity checking on buffer symbols.  They can only
283      * have ABSOLUTE addressing mode.
284      */
285     if (s->type == (String) XmtQBuffer) {
286 	int len = strlen((char *)value);
287 	if (len < s->size)
288 	    strcpy((char *)s->addr, (char *) value);
289 	else {
290 	    strncpy((char *)s->addr, (char *)value, s->size-1);
291 	    ((char *)s->addr)[s->size] = '\0';
292 	    XmtWarningMsg("XmtSymbolSetValue", "overflow",
293 		       "Symbol '%s': buffer overflow.\n\t%d characters lost.",
294 			  s->name, len - s->size +1);
295 	}
296     }
297     else {  /* anything other than buffer symbols */
298 	/*
299 	 * if this is an enumerated symbol, then the new value is the
300 	 * index into the supplied array of values, not the value itself.
301 	 */
302 	if (s->num_values > 0) {
303 	    index = (unsigned int) value;
304 	    if ((index >= s->num_values) || (index < 0)) {
305 		XmtWarningMsg("XmtSymbolSetValue", "badValue",
306 			      "symbol '%s' has no enumerated value for %d.",
307 			      s->name, index);
308 		return;
309 	    }
310 	    s->index = (unsigned short)index;
311 	    value = (XtArgVal)s->values[index];
312 	}
313 
314 	/* XXX
315 	 * machine dependencies?  Does this work on a Sparc?
316 	 */
317 	switch(s->mode) {
318 	case XmtSymbolABSOLUTE:
319 	    _XtCopyFromArg(value, s->addr, s->size);
320 	    break;
321 	case XmtSymbolIMMEDIATE:
322 	    _XtCopyFromArg(value, &s->addr, s->size);
323 	    break;
324 	case XmtSymbolRESOURCE:
325 	    XtVaSetValues((Widget)s->addr, s->resource_name, value, NULL);
326 	    break;
327 	}
328     }
329 
330     /*
331      * call notify procs.
332      */
333     for(p = s->callbacks; p; p = p->next)
334 	(*p->proc)(s, p->closure, value);
335 }
336 
337 #if NeedFunctionPrototypes
XmtSymbolSetTypedValue(Widget w,XmtSymbol s,String type,XtArgVal value,Cardinal size)338 Boolean XmtSymbolSetTypedValue(Widget w, XmtSymbol s, String type,
339 			       XtArgVal value, Cardinal size)
340 #else
341 Boolean XmtSymbolSetTypedValue(w, s, type, value, size)
342 Widget w;
343 XmtSymbol s;
344 String type;
345 XtArgVal value;
346 Cardinal size;
347 #endif
348 {
349     XrmQuark typeq = XrmStringToQuark(type);
350     XrmValue from, to;
351     XtArgVal converted_value;
352     Boolean status;
353     extern void _XtCopyToArg();
354 
355     /*
356      * if the types match, just call XmtSymbolSetValue().
357      * if the symbol is a buffer, and the value a string, that is a match.
358      */
359     if ((typeq == (XrmQuark) s->type) ||
360 	((typeq == XmtQString) && (s->type == (String) XmtQBuffer))) {
361 	XmtSymbolSetValue(s, value);
362 	return True;
363     }
364 
365     /*
366      * otherwise attempt to convert the value.
367      */
368     from.size = size;
369     if ((size > sizeof(XtArgVal)) ||
370 	(typeq == XmtQString) || (typeq == XmtQBuffer))
371 	from.addr = (XPointer) value;
372     else
373 	from.addr = (XPointer) &value;
374     /* let the converter return a value of the right type. */
375     to.addr = NULL;
376     to.size = s->size;
377     status = XtConvertAndStore(w, type, &from,
378 			       XrmQuarkToString((XrmQuark)s->type), &to);
379 
380     if (status) {
381 	converted_value = 0;  /* make func below store directly into us */
382 	_XtCopyToArg(to.addr, &converted_value, to.size);
383 	XmtSymbolSetValue(s, converted_value);
384     }
385     else {
386 	XmtWarningMsg("XmtSymbolSetTypedValue", "convert",
387 		      "Couldn't set symbol '%s'.", s->name);
388     }
389 
390     return status;
391 }
392 
393 #if NeedFunctionPrototypes
XmtSymbolGetValue(XmtSymbol s,XtArgVal * valuep)394 void XmtSymbolGetValue(XmtSymbol s, XtArgVal *valuep)
395 #else
396 void XmtSymbolGetValue(s, valuep)
397 XmtSymbol s;
398 XtArgVal *valuep;
399 #endif
400 {
401     extern void _XtCopyToArg();
402 
403     /*
404      * Special case for XmtRBuffer type symbols.
405      * Just return the address.
406      */
407     if (s->type == (String) XmtQBuffer) {
408 	*(char **)valuep = s->addr;
409 	return;
410     }
411 
412     switch(s->mode) {
413     case XmtSymbolABSOLUTE:
414 	_XtCopyToArg(s->addr, (XtArgVal *) &valuep, s->size);
415 	break;
416     case XmtSymbolIMMEDIATE:
417 	_XtCopyToArg(&s->addr, (XtArgVal *) &valuep, s->size);
418 	break;
419     case XmtSymbolRESOURCE:
420 	XtVaGetValues((Widget)s->addr, s->resource_name, valuep);
421 	break;
422     }
423 }
424 
425 #if NeedFunctionPrototypes
XmtSymbolGetScalarValue(XmtSymbol s)426 int XmtSymbolGetScalarValue(XmtSymbol s)
427 #else
428 int XmtSymbolGetScalarValue(s)
429 XmtSymbol s;
430 #endif
431 {
432     if (s->num_values > 0) return (int)s->index;
433     else
434 	XmtWarningMsg("XmtSymbolGetScalarValue", "badSymbol",
435 		      "symbol '%s' is not an enumerated value.",
436 		      s->name);
437     return -1;
438 }
439 
440 
441 #if NeedFunctionPrototypes
XmtSymbolAddCallback(XmtSymbol s,XmtSymbolCallbackProc proc,XtPointer closure)442 void XmtSymbolAddCallback(XmtSymbol s, XmtSymbolCallbackProc proc,
443 			  XtPointer closure)
444 #else
445 void XmtSymbolAddCallback(s, proc, closure)
446 XmtSymbol s;
447 XmtSymbolCallbackProc proc;
448 XtPointer closure;
449 #endif
450 {
451     XmtSymbolCallbackRec *cb = XtNew(XmtSymbolCallbackRec);
452     XmtSymbolCallbackRec *p;
453 
454     cb->proc = proc;
455     cb->closure = closure;
456     cb->next = NULL;
457     if (s->callbacks == NULL) s->callbacks = cb;
458     else {
459 	for(p = s->callbacks; p->next; p = p->next);
460 	p->next = cb;
461     }
462 }
463 
464 #if NeedFunctionPrototypes
XmtSymbolRemoveCallback(XmtSymbol s,XmtSymbolCallbackProc proc,XtPointer closure)465 void XmtSymbolRemoveCallback(XmtSymbol s, XmtSymbolCallbackProc proc,
466 			     XtPointer closure)
467 #else
468 void XmtSymbolRemoveCallback(s, proc, closure)
469 XmtSymbol s;
470 XmtSymbolCallbackProc proc;
471 XtPointer closure;
472 #endif
473 {
474     XmtSymbolCallbackRec *p, *q;
475 
476     for(q=NULL, p = s->callbacks; p; q=p, p = p->next)
477 	if ((p->proc == proc) && (p->closure == closure)) break;
478 
479     if (p) {
480 	if (!q) s->callbacks = p->next;
481 	else q->next = p->next;
482 	XtFree((char *)p);
483     }
484 }
485 
486 #if NeedFunctionPrototypes
XmtSymbolName(XmtSymbol s)487 String XmtSymbolName(XmtSymbol s)
488 #else
489 String XmtSymbolName(s)
490 XmtSymbol s;
491 #endif
492 {
493     return s->name;
494 }
495 
496 #if NeedFunctionPrototypes
XmtSymbolSize(XmtSymbol s)497 int XmtSymbolSize(XmtSymbol s)
498 #else
499 int XmtSymbolSize(s)
500 XmtSymbol s;
501 #endif
502 {
503     return s->size;
504 }
505 
506 #if NeedFunctionPrototypes
XmtSymbolTypeQuark(XmtSymbol s)507 XrmQuark XmtSymbolTypeQuark(XmtSymbol s)
508 #else
509 XrmQuark XmtSymbolTypeQuark(s)
510 XmtSymbol s;
511 #endif
512 {
513     return (XrmQuark) s->type;
514 }
515 
516 #if NeedFunctionPrototypes
XmtSymbolType(XmtSymbol s)517 String XmtSymbolType(XmtSymbol s)
518 #else
519 String XmtSymbolType(s)
520 XmtSymbol s;
521 #endif
522 {
523     return XrmQuarkToString((XrmQuark)s->type);
524 }
525 
526 #if NeedFunctionPrototypes
XmtSymbolIsEnumerated(XmtSymbol s)527 Boolean XmtSymbolIsEnumerated(XmtSymbol s)
528 #else
529 Boolean XmtSymbolIsEnumerated(s)
530 XmtSymbol s;
531 #endif
532 {
533     return (s->num_values > 0);
534 }
535