1 /*
2 * Motif Tools Library, Version 3.1
3 * $Id: NameToWidget.c,v 1.3 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: NameToWidget.c,v $
12 * Revision 1.3 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.2 2001/04/15 15:29:36 grmcdorman
32 * * XmtCallCallback has two new arguments types: XmtRCallbackUserData, which
33 * is the XmNuserData value, and XmtRCallbackImmediate, which is a value
34 * embedded in the list.
35 *
36 * * Two new functions, XmtCreateQueryListChildren and XmtCreateQueryListChild,
37 * are provided. They are like the XmtCreate* functions except that they
38 * return a list of the widgets created (quark and pointer to the widget).
39 *
40 * * Major enhancements to XmtInputField:
41 * - The input field now has a cancel() action. This reverts the field's
42 * value to that prior to the start of editing (i.e. the last commit).
43 * No default translation is bound to this action, however.
44 * - There is a callback for the cancel action (XmtNcancelCallback).
45 * - The input field can be set to cancel, commit, or do nothing on focus
46 * out. (Previously, it always did a commit). The default is commit.
47 * (XmtNfocusOutAction)
48 *
49 * * XmtLayout:
50 * - It now has a losingFocusCallback (XmNloosingFocusCallback).
51 * - It, and the layout widgets (XmtLayoutBox/XmtLayoutString), now
52 * support background pixmaps.
53 * - It now supports XmNresizePolicy.
54 * - Strings in the layout parser are converted to XmStrings by
55 * XtConvertAndStore, so any custom XmString conversion is used
56 * (as, for example, the Xmt convert, which supports the @[]
57 * embedded items)
58 *
59 * * Other:
60 * - Pixmaps are convered using XtConvertAndStore, again to allow
61 * custom converters.
62 *
63 * Bug Fixes: (for Solaris 2.5.1/Motif 1.2/Sparc system)
64 * * XmtInputField did not work properly if the widget had traversalOn
65 * false.
66 * * XmtLayout's child geometry manager was called by Xt when
67 * a shell child was added to the layout; it did not handle
68 * this case.
69 * * XmtLayout had an XmtWarningMsg call with a missing argument (line 2029).
70 * * Widgets automatically created by XmtLayout parsing have been given
71 * non-blank names. [You may wish to tweak this by adding, for example,
72 * a leading underscore.]
73 * * Under some circumstances, XmtNameToWidget could be called during
74 * widget creation, with 'w->core.num_popups' uninitialized. The
75 * workaround applied is to ignore the popup list if the 'num_popups'
76 * value is more than 50 or negative.
77 *
78 * Revision 1.1.1.1 2001/02/10 13:50:08 motiftools
79 * Initial import of Xmt310 to CVS
80 *
81 *
82 */
83
84 /*
85 * Portions of this file are derived from the Xt source code.
86 * See the file COPYRIGHT for the MIT and Digital copyrights.
87 */
88
89 #include <Xmt/XmtP.h>
90 #include <Xmt/Util.h>
91 #include <Xmt/AppRes.h>
92 #include <X11/IntrinsicP.h>
93
94 static XrmQuark selfq = NULLQUARK;
95 static XrmQuark questionq = NULLQUARK;
96
97 #if NeedFunctionPrototypes
GetParent(Widget w)98 static Widget GetParent(Widget w)
99 #else
100 static Widget GetParent(w)
101 Widget w;
102 #endif
103 {
104 if (w == NULL) return NULL;
105 if (XtParent(w) != NULL) return XtParent(w);
106 else return w;
107 }
108
109 #if NeedFunctionPrototypes
GetNamedAncestor(Widget ref,char * name)110 static Widget GetNamedAncestor(Widget ref, char *name)
111 #else
112 static Widget GetNamedAncestor(ref, name)
113 Widget ref;
114 char *name;
115 #endif
116 {
117 Widget w;
118 WidgetClass c;
119 XrmQuark q = XrmStringToQuark(name);
120
121 if (ref == NULL) return NULL;
122
123 /* see if the supplied name matches any ancestor's names */
124 for(w = XtParent(ref); w != NULL; w = XtParent(w))
125 if (w->core.xrm_name == q) return w;
126
127 /*
128 * if not, start checking classes. Check the class name, and
129 * all the superclass names of each ancestor widget.
130 * This is done with WidgetClass, but should work for objects too.
131 */
132 for(w = XtParent(ref); w != NULL; w = XtParent(w))
133 for(c = XtClass(w); c != NULL; c = c->core_class.superclass)
134 if (c->core_class.xrm_class == q) return w;
135
136 /* if no name or class matches, return NULL */
137 return NULL;
138 }
139
140 #if NeedFunctionPrototypes
GetChild(Widget w,XrmName q)141 static Widget GetChild(Widget w, XrmName q)
142 #else
143 static Widget GetChild(w, q)
144 Widget w;
145 XrmName q;
146 #endif
147 {
148 CompositeWidget parent = (CompositeWidget) w;
149 int i;
150
151 /*
152 * Check the names of all normal children.
153 * Check the names of all popup children.
154 * Check the class names of all normal children.
155 * Check the class names of all popup children.
156 * Note that we don't check superclass names.
157 */
158
159 if (w == NULL) return NULL;
160
161 /* normal children names */
162 if (XtIsComposite(w)) {
163 for(i = 0; i < parent->composite.num_children; i++)
164 if (parent->composite.children[i]->core.xrm_name == q)
165 return parent->composite.children[i];
166 }
167
168 /* popup children names */
169 /* try to handle unintialized 'num_popups' */
170 if (w->core.num_popups < 50 && w->core.num_popups > 0)
171 for(i = 0; i < w->core.num_popups; i++)
172 if (w->core.popup_list[i]->core.xrm_name == q)
173 return w->core.popup_list[i];
174
175 /* normal children classes */
176 if (XtIsComposite(w)) {
177 for(i = 0; i < parent->composite.num_children; i++)
178 if (XtClass(parent->composite.children[i])->core_class.xrm_class
179 == q)
180 return parent->composite.children[i];
181 }
182
183 /* popup children classes */
184 /* try to handle unintialized 'num_popups' */
185 if (w->core.num_popups < 50 && w->core.num_popups > 0)
186 for(i = 0; i < w->core.num_popups; i++)
187 if (XtClass(w->core.popup_list[i])->core_class.xrm_class == q)
188 return w->core.popup_list[i];
189
190 /* no child matches */
191 return NULL;
192 }
193
194
195 #if NeedFunctionPrototypes
ParseWidgetModifiers(Widget w,StringConst * name)196 static Widget ParseWidgetModifiers(Widget w, StringConst *name)
197 #else
198 static Widget ParseWidgetModifiers(w, name)
199 Widget w;
200 StringConst *name;
201 #endif
202 {
203 if (*name == NULL || **name == '\0')
204 return w; /* no recursion */
205 else if (**name == '.') {
206 /*
207 * ignore '.' if there are following modifiers, or
208 * return w if no modifiers follow it.
209 */
210 *name += 1;
211 return ParseWidgetModifiers(w, name);
212 }
213 else if (**name == '~') {
214 *name += 1;
215 return XmtGetShell(ParseWidgetModifiers(w, name));
216 }
217 else if (**name == '^') {
218 if (*(*name+1) != '{') {
219 *name += 1;
220 return GetParent(ParseWidgetModifiers(w, name));
221 }
222 else {
223 char ancestor[100];
224 int i = 0;
225 *name += 2;
226 while (**name && **name != '}') {
227 ancestor[i++] = **name;
228 *name += 1;
229 }
230 ancestor[i] = '\0';
231 if (**name == '}') *name += 1;
232 return GetNamedAncestor(ParseWidgetModifiers(w, name),
233 ancestor);
234 }
235 }
236 else /* there are no more modifiers, so don't recurse */
237 return w;
238 }
239
240
241 /*
242 * The following 5 procedures are code modified from the internals
243 * of the function XtNameToWidget. This code appears in the file
244 * Intrinsic.c in the MIT Xt distribution, with the following RCS info:
245 * $XConsortium: Intrinsic.c,v 1.171 91/07/16 18:30:20 converse Exp $
246 */
247 #if NeedFunctionPrototypes
248 static Widget NameListToWidget(register Widget root,
249 XrmNameList names, XrmBindingList bindings,
250 int num_quarks, int in_depth, int *out_depth,
251 int *found_depth);
252 #else
253 static Widget NameListToWidget();
254 #endif
255
256 typedef Widget (*NameMatchProc)();
257
258 #if NeedFunctionPrototypes
MatchExactChildren(XrmNameList names,XrmBindingList bindings,int num_quarks,register WidgetList children,register int num,int in_depth,int * out_depth,int * found_depth)259 static Widget MatchExactChildren(XrmNameList names, XrmBindingList bindings,
260 int num_quarks, register WidgetList children,
261 register int num, int in_depth,
262 int *out_depth, int *found_depth)
263 #else
264 static Widget MatchExactChildren(names, bindings, num_quarks, children, num,
265 in_depth, out_depth, found_depth)
266 XrmNameList names;
267 XrmBindingList bindings;
268 int num_quarks;
269 register WidgetList children;
270 register int num;
271 int in_depth;
272 int *out_depth;
273 int *found_depth;
274 #endif
275 {
276 register Cardinal i;
277 register XrmName name = *names;
278 Widget w, result = NULL;
279 int d, min = 10000;
280
281 /* check the names of children. '?' always matches -- djf */
282 for (i = 0; i < num; i++) {
283 if ((name == children[i]->core.xrm_name) ||
284 (name == questionq)) /* djf */ {
285 w = NameListToWidget(children[i], &names[1], &bindings[1],
286 num_quarks-1,
287 in_depth+1, &d, found_depth);
288 if (w != NULL && d < min) {result = w; min = d;}
289 }
290 }
291
292 *out_depth = min;
293 return result;
294 }
295
296 #if NeedFunctionPrototypes
MatchExactClass(XrmNameList names,XrmBindingList bindings,int num_quarks,register WidgetList children,register int num,int in_depth,int * out_depth,int * found_depth)297 static Widget MatchExactClass(XrmNameList names, XrmBindingList bindings,
298 int num_quarks, register WidgetList children,
299 register int num, int in_depth, int *out_depth,
300 int *found_depth)
301 #else
302 static Widget MatchExactClass(names, bindings, num_quarks, children, num,
303 in_depth, out_depth, found_depth)
304 XrmNameList names;
305 XrmBindingList bindings;
306 int num_quarks;
307 register WidgetList children;
308 register int num;
309 int in_depth;
310 int *out_depth;
311 int *found_depth;
312 #endif
313 {
314 register Cardinal i;
315 register XrmName name = *names;
316 Widget w, result = NULL;
317 int d, min = 10000;
318
319 /* like the above, but check classes -- djf */
320 for (i = 0; i < num; i++) {
321 if (name == XtClass(children[i])->core_class.xrm_class) {
322 w = NameListToWidget(children[i], &names[1], &bindings[1],
323 num_quarks-1,
324 in_depth+1, &d, found_depth);
325 if (w != NULL && d < min) {result = w; min = d;}
326 }
327 }
328
329 *out_depth = min;
330 return result;
331 }
332
333
334 #if NeedFunctionPrototypes
MatchWildChildren(XrmNameList names,XrmBindingList bindings,int num_quarks,register WidgetList children,register int num,int in_depth,int * out_depth,int * found_depth)335 static Widget MatchWildChildren(XrmNameList names, XrmBindingList bindings,
336 int num_quarks, register WidgetList children,
337 register int num, int in_depth,
338 int *out_depth, int *found_depth)
339 #else
340 static Widget MatchWildChildren(names, bindings, num_quarks, children, num,
341 in_depth, out_depth, found_depth)
342 XrmNameList names;
343 XrmBindingList bindings;
344 int num_quarks;
345 register WidgetList children;
346 register int num;
347 int in_depth;
348 int *out_depth;
349 int *found_depth;
350 #endif
351 {
352 register Cardinal i;
353 Widget w, result = NULL;
354 int d, min = 10000;
355
356 for (i = 0; i < num; i++) {
357 w = NameListToWidget(children[i], names, bindings, num_quarks,
358 in_depth+1, &d, found_depth);
359 if (w != NULL && d < min) {result = w; min = d;}
360 }
361 *out_depth = min;
362 return result;
363 }
364
365 #if NeedFunctionPrototypes
SearchChildren(Widget root,XrmNameList names,XrmBindingList bindings,int num_quarks,NameMatchProc matchproc,int in_depth,int * out_depth,int * found_depth)366 static Widget SearchChildren(Widget root,
367 XrmNameList names, XrmBindingList bindings,
368 int num_quarks, NameMatchProc matchproc,
369 int in_depth, int *out_depth, int *found_depth)
370 #else
371 static Widget SearchChildren(root, names, bindings, num_quarks, matchproc,
372 in_depth, out_depth, found_depth)
373 Widget root;
374 XrmNameList names;
375 XrmBindingList bindings;
376 int num_quarks;
377 NameMatchProc matchproc;
378 int in_depth;
379 int *out_depth;
380 int *found_depth;
381 #endif
382 {
383 Widget w1, w2;
384 int d1, d2;
385
386 if (XtIsComposite(root)) {
387 w1 = (*matchproc)(names, bindings, num_quarks,
388 ((CompositeWidget) root)->composite.children,
389 ((CompositeWidget) root)->composite.num_children,
390 in_depth, &d1, found_depth);
391 }
392 else {
393 d1 = 10000;
394 w1 = NULL;
395 }
396 w2 = (*matchproc)(names, bindings, num_quarks, root->core.popup_list,
397 root->core.num_popups < 50 && root->core.num_popups > 0 ? root->core.num_popups : 0,
398 in_depth, &d2, found_depth);
399 *out_depth = (d1 < d2 ? d1 : d2);
400 return (d1 < d2 ? w1 : w2);
401 }
402
403 #if NeedFunctionPrototypes
NameListToWidget(register Widget root,XrmNameList names,XrmBindingList bindings,int num_quarks,int in_depth,int * out_depth,int * found_depth)404 static Widget NameListToWidget(register Widget root,
405 XrmNameList names, XrmBindingList bindings,
406 int num_quarks, int in_depth,
407 int *out_depth, int *found_depth)
408 #else
409 static Widget NameListToWidget(root, names, bindings, num_quarks, in_depth,
410 out_depth, found_depth)
411 register Widget root;
412 XrmNameList names;
413 XrmBindingList bindings;
414 int num_quarks;
415 int in_depth;
416 int *out_depth;
417 int *found_depth;
418 #endif
419 {
420 Widget w1, w2;
421 int d1, d2;
422
423 if (in_depth >= *found_depth) {
424 *out_depth = 10000;
425 return NULL;
426 }
427
428 if (num_quarks == 0) {
429 *out_depth = *found_depth = in_depth;
430 return root;
431 }
432
433 if (! XtIsWidget(root)) {
434 *out_depth = 10000;
435 return NULL;
436 }
437
438 if (*bindings == XrmBindTightly) {
439 w1 = SearchChildren(root, names, bindings, num_quarks,
440 MatchExactChildren,
441 in_depth, out_depth, found_depth);
442 /* if no names match, look for a class name that matches -- djf */
443 if (w1 == NULL) {
444 w1 = SearchChildren(root, names, bindings, num_quarks,
445 MatchExactClass,
446 in_depth, out_depth, found_depth);
447 }
448
449 if (w1 != NULL)
450 return w1;
451 }
452 else { /* XrmBindLoosely */
453 w1 = SearchChildren(root, names, bindings, num_quarks,
454 MatchExactChildren,
455 in_depth, &d1, found_depth);
456 if (w1 == NULL) { /* if no names match exactly, check classes -- djf */
457 w1 = SearchChildren(root, names, bindings, num_quarks,
458 MatchExactClass,
459 in_depth, &d1, found_depth);
460 }
461 w2 = SearchChildren(root, names, bindings, num_quarks,
462 MatchWildChildren,
463 in_depth, &d2, found_depth);
464 *out_depth = (d1 < d2 ? d1 : d2);
465 return (d1 < d2 ? w1 : w2);
466 }
467 /* NOTREACHED */
468 return NULL; /* but return something anyway to keep gcc -Wall quiet */
469 } /* NameListToWidget */
470
471
472 /* modified X Consortium code ends here. */
473
474 #if NeedFunctionPrototypes
XmtNameToWidget(Widget ref,StringConst name)475 Widget XmtNameToWidget(Widget ref, StringConst name)
476 #else
477 Widget XmtNameToWidget(ref, name)
478 Widget ref;
479 StringConst name;
480 #endif
481 {
482 StringConst newname;
483 Boolean modifiers = False;
484 XrmQuark quark_array[50];
485 XrmBinding binding_array[50];
486 XrmQuarkList quarks;
487 XrmBindingList bindings;
488 int numquarks;
489 Widget w;
490 int depth = 0;
491 int found = 10000;
492
493 /* initialize quarks used by lots of functions */
494 if (selfq == NULLQUARK) selfq = XrmStringToQuark("self");
495 if (questionq == NULLQUARK) questionq = XrmStringToQuark("?");
496
497 newname = name;
498 /* if the name begins with a modifier, go parse them */
499 if ((name[0] == '.') || (name[0] == '^') || (name[0] == '~')) {
500 modifiers = True;
501 ref = ParseWidgetModifiers(ref, &newname);
502 }
503
504 /*
505 * if no name, or nothing following the modifiers,
506 * then just return the reference widget. This is
507 * so names like "^^" work.
508 */
509 if (!newname || !*newname) return ref;
510
511 /* quarkify the name and count the quarks */
512 quarks = quark_array;
513 bindings = binding_array;
514 XrmStringToBindingQuarkList(newname, bindings, quarks);
515 for(numquarks = 0; quarks[numquarks] != NULLQUARK; numquarks++);
516
517 if (!modifiers) {
518 /* if the name begins with '*', it is relative to the root. */
519 if (name[0]== '*')
520 ref = XmtGetApplicationShell(ref);
521 else {
522 /*
523 * if first quark is 'self', skip it.
524 * if first quark is a sibling of ref, ref = parent
525 * otherwise if first quark doesn't name a child, maybe it
526 * names a root widget. If it doesn't name any known root,
527 * it is an error.
528 */
529 if (quarks[0] == selfq) {
530 quarks++;
531 bindings++;
532 numquarks--;
533 }
534 else if (GetChild(XtParent(ref), quarks[0]))
535 ref = XtParent(ref);
536 else if (!GetChild(ref, quarks[0])) {
537 ref = XmtLookupApplicationShell(quarks[0]);
538 if (!ref) return NULL;
539 quarks++;
540 bindings++;
541 numquarks--;
542 }
543 }
544 }
545
546 w = NameListToWidget(ref, quarks, bindings, numquarks,
547 0, &depth, &found);
548 return w;
549 }
550
551