1 /*
2  * Motif Tools Library, Version 3.1
3  * $Id: Create.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: Create.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:42:08  motiftools
79  * Initial import of Xmt310 to CVS
80  *
81  *
82  */
83 
84 #include <Xmt/XmtP.h>
85 #include <Xmt/Create.h>
86 #include <Xmt/WidgetType.h>
87 #include <Xmt/Include.h>
88 #include <Xmt/Template.h>
89 #include <Xmt/DialogP.h>
90 #include <Xmt/Lexer.h>
91 #include <Xmt/ConvertersP.h>
92 #include <Xmt/AppResP.h>
93 #include <Xm/DialogS.h>
94 #include <X11/IntrinsicP.h>
95 #include <X11/CompositeP.h>
96 
97 #include <unistd.h>
98 
99 
100 #if NeedFunctionPrototypes
ConvertCallbackList(Widget w,StringConst s,XtCallbackList * list_return,XtCacheRef * ref_return)101 static void ConvertCallbackList(Widget w, StringConst s,
102 				XtCallbackList *list_return,
103 				XtCacheRef *ref_return)
104 #else
105 static void ConvertCallbackList(w, s, list_return, ref_return)
106 Widget w;
107 StringConst s;
108 XtCallbackList *list_return;
109 XtCacheRef *ref_return;
110 #endif
111 {
112     XrmValue from, to;
113 
114     if (_XmtCallbackConverter == NULL) {
115 	XmtWarningMsg("CreateWidget", "noConverter",
116 		      "no String to XtCallbackList converter registered.\n\tCall XmtRegisterCallbackConverter().");
117 	return;
118     }
119 
120     from.addr = (XPointer) s;
121     from.size = strlen(s)+1;
122     to.addr = (XPointer) list_return;
123     to.size = sizeof(XtCallbackList);
124     XtCallConverter(XtDisplayOfObject(w), _XmtCallbackConverter, NULL, 0,
125 		    &from, &to, ref_return);
126 }
127 
128 #if NeedFunctionPrototypes
FreeCallbackList(Widget w,XtCacheRef ref)129 static void FreeCallbackList(Widget w, XtCacheRef ref)
130 #else
131 static void FreeCallbackList(w, ref)
132 Widget w;
133 XtCacheRef ref;
134 #endif
135 {
136     XtCacheRef refs[2];
137 
138     if (ref == NULL) return;
139     refs[0] = ref;
140     refs[1] = NULL;
141     XtAppReleaseCacheRefs(XtWidgetToApplicationContext(w), refs);
142 }
143 
144 #if NeedFunctionPrototypes
CallCallbackList(Widget w,XtCallbackList list)145 static void CallCallbackList(Widget w, XtCallbackList list)
146 #else
147 static void CallCallbackList(w, list)
148 Widget w;
149 XtCallbackList list;
150 #endif
151 {
152     for(; list->callback; list++)
153 	(*list->callback)(w, list->closure, NULL);
154 }
155 
156 typedef XmtWidgetList WidgetName;
157 
158 /* forward declaration */
159 #if NeedFunctionPrototypes
160 static void CreateChildren(Widget, XmtDialogInfo *, WidgetName *, Cardinal);
161 static Widget _XmtCreateChild(Widget, StringConst, XmtDialogInfo *,
162 			      WidgetName *, Cardinal);
163 #else
164 static void CreateChildren();
165 static Widget _XmtCreateChild();
166 #endif
167 
168 typedef struct {
169     String create;
170     String children;
171     String managed;
172 } CallbackStringsType;
173 
174 static XtResource callback_resources[] = {
175 {XmtNxmtCreationCallback, XmtCXmtCreationCallback, XtRString,
176      sizeof(String), XtOffsetOf(CallbackStringsType, create),
177      XtRString, (XtPointer) NULL},
178 {XmtNxmtChildrenCreationCallback, XmtCXmtChildrenCreationCallback, XtRString,
179      sizeof(String), XtOffsetOf(CallbackStringsType, children),
180      XtRString, (XtPointer) NULL},
181 {XmtNxmtManagedCreationCallback, XmtCXmtManagedCreationCallback, XtRString,
182      sizeof(String), XtOffsetOf(CallbackStringsType, managed),
183      XtRString, (XtPointer) NULL},
184 };
185 
186 static XtResource requires_resource[] = {
187 {XmtNxmtRequires, XmtCXmtRequires, XtRString,
188      sizeof(String), 0, XtRString, NULL}
189 };
190 
191 #if NeedFunctionPrototypes
CreateChild(Widget parent,StringConst name,XmtWidgetType * type,String template,Boolean managed,String * styles,Cardinal num_styles,Boolean load,XmtDialogInfo * dialog_info,WidgetName * names,Cardinal num_names)192 static Widget CreateChild(Widget parent, StringConst name, XmtWidgetType *type,
193                           String template, Boolean managed,
194                           String *styles, Cardinal num_styles, Boolean load,
195                           XmtDialogInfo *dialog_info,
196                           WidgetName *names, Cardinal num_names)
197 #else
198 static Widget CreateChild(parent, name, type, template, managed,
199                           styles, num_styles, load, dialog_info,
200                           names, num_names)
201 Widget parent;
202 StringConst name;
203 XmtWidgetType *type;
204 String template;
205 Boolean managed;
206 String *styles;
207 Cardinal num_styles;
208 Boolean load;
209 XmtDialogInfo *dialog_info;
210 WidgetName *names;
211 Cardinal num_names;
212 #endif
213 {
214     Widget w = NULL;
215     String requires_string;
216     CallbackStringsType callback_strings;
217     XrmQuark nameq;
218     XtCallbackList create_callback_list = NULL;
219     XtCallbackList children_callback_list = NULL;
220     XtCallbackList managed_callback_list = NULL;
221     XtCacheRef create_callback_ref;
222     XtCacheRef children_callback_ref;
223     XtCacheRef managed_callback_ref;
224     int i;
225 
226     /* first, load any required files, unless already loaded */
227     if (load) {
228 	XtGetSubresources(parent, (XtPointer)&requires_string,
229 			  (String)name, (String)name,
230 			  requires_resource, (Cardinal)1,
231 			  NULL, (Cardinal) 0);
232 	if (requires_string) XmtLoadResourceFileList(parent, requires_string);
233     }
234 
235     /* apply any styles that were specified */
236     if (num_styles)
237 	for(i=0; i < num_styles; i++)
238 	    XmtTemplateInstantiate(parent, name, styles[i], NULL, 0);
239 
240     /* now create the widget */
241     if (type)
242 	w = XmtCreateWidgetType(name, type, parent, NULL, 0);
243     else if (template) {
244 	/*
245 	 * if the widget is a template type, instantiate the template,
246 	 * and then start the creation process over to read the xmtType
247 	 * resource.  Note that we recurse and then return immediately.
248 	 * If we don't return the callbacks will be called twice and
249 	 * the children created twice.
250 	 */
251 	XmtTemplateInstantiate(parent, name, template, NULL, 0);
252 	w = _XmtCreateChild(parent, name, dialog_info, names, num_names);
253 	return w;
254     }
255 
256     /*
257      * if we don't have a widget now, something went wrong.
258      * Assume that someone else printed a warning message, and return.
259      */
260     if (w == NULL) return NULL;
261 
262     /*
263      * see if the widget matches any in the names list, and if so,
264      * store the widget pointer at the given address
265      */
266     nameq = XrmStringToQuark(name);
267     for(i=0; i < num_names; i++) {
268 	if (nameq == names[i].nameq) {
269 	    *names[i].widgetp = w;
270 	    break;
271 	}
272     }
273 
274     /*
275      * A widget has just been created.  Next we:
276      * (0) fetch and convert the creation callback resources
277      * (1) invoke the xmtCreationCallback list
278      * (2) call CreateChildren to create the widget's children (reg. or popup)
279      * (2a) invoke the xmtChildrenCreationCallback list
280      * (3) manage it, unless a shell or unmanaged
281      * (3a) invoke the xmtManagedCreationCallback list
282      * (4) free any creation callbacks.
283      */
284 
285     /* (0) fetch and convert the creation callback resources */
286     XtGetApplicationResources(w, (XtPointer)&callback_strings,
287 			      callback_resources, XtNumber(callback_resources),
288 			      NULL, (Cardinal)0);
289     if (callback_strings.create)
290 	ConvertCallbackList(w, callback_strings.create,
291 			    &create_callback_list, &create_callback_ref);
292     if (callback_strings.children)
293 	ConvertCallbackList(w, callback_strings.children,
294 			    &children_callback_list, &children_callback_ref);
295     if (callback_strings.managed)
296 	ConvertCallbackList(w, callback_strings.managed,
297 			    &managed_callback_list, &managed_callback_ref);
298 
299     /* (1) invoke the xmtCreationCallback list */
300     if (create_callback_list) CallCallbackList(w, create_callback_list);
301 
302     /* (2) call CreateChildren, to create regular or popup children */
303     CreateChildren(w, dialog_info, names, num_names);
304 
305     /* (2a) invoke the xmtChildrenCreationCallback list */
306     if (children_callback_list) CallCallbackList(w,children_callback_list);
307 
308     /* (3) manage it, unless a shell or unmanaged */
309     if (managed && !XtIsShell(w)) {
310 	XtManageChild(w);
311 	/* (3a) invoke the xmtManagedCreationCallback list */
312 	if (managed_callback_list) CallCallbackList(w, managed_callback_list);
313     }
314 
315     /* (4) free any creation callbacks. */
316     if (create_callback_list) FreeCallbackList(w, create_callback_ref);
317     if (children_callback_list) FreeCallbackList(w, children_callback_ref);
318     if (managed_callback_list) FreeCallbackList(w, managed_callback_ref);
319 
320     return w;
321 }
322 
323 static String keywords[] = {
324     "managed",
325     "unmanaged",
326 };
327 
328 #define MANAGED   0
329 #define UNMANAGED 1
330 
331 #define MAX_TEMPLATE_ARGS 10
332 
333 #if NeedFunctionPrototypes
ParseType(Widget w,StringConst name,XmtLexer l,XmtWidgetType ** type,String * template,Boolean * managed,String ** styles,Cardinal * num_styles)334 static Boolean ParseType(Widget w, StringConst name, XmtLexer l,
335 			 XmtWidgetType **type, String *template,
336 			 Boolean *managed,
337 			 String **styles, Cardinal *num_styles)
338 #else
339 static Boolean ParseType(w, name, l, type, template, managed,
340 			 styles, num_styles)
341 Widget w;
342 StringConst name;
343 XmtLexer l;
344 XmtWidgetType **type;
345 String *template;
346 Boolean *managed;
347 String **styles;
348 Cardinal *num_styles;
349 #endif
350 {
351     XmtLexerToken tok;
352     int max_styles = 0;
353     String style;
354     String args[MAX_TEMPLATE_ARGS];
355     Cardinal num_args;
356     Cardinal expected_args;
357     String template_name;
358     int i;
359 
360     /* set defaults and parse any modifiers or styles */
361     *managed = True;
362     *num_styles = 0;
363     *styles = NULL;
364     while (1) {
365 	tok = XmtLexerGetToken(l);
366 	if (tok == XmtLexerKeyword) {
367 	    switch(XmtLexerKeyValue(l)) {
368 	    case MANAGED:
369 		*managed = True;
370 		break;
371 	    case UNMANAGED:
372 		*managed = False;
373 		break;
374 	    }
375 	    XmtLexerConsumeToken(l);
376 	}
377 	else if ((tok == XmtLexerIdent) &&
378 		 ((style = XmtLookupStyle(w, XmtLexerStrValue(l))) != NULL)) {
379 	    if (*num_styles == max_styles) {
380 		max_styles += 4;
381 		*styles = (String *)XtRealloc((char *)*styles,
382 					      max_styles * sizeof(String));
383 	    }
384 	    template_name = XmtLexerStrValue(l);
385 	    XmtLexerConsumeToken(l);
386 	    XmtLexerGetArgList(l, args, MAX_TEMPLATE_ARGS, &num_args);
387 	    style = XmtTemplateSubstituteArgs(style, args, num_args,
388 					      &expected_args);
389 	    *styles[*num_styles] = style;
390 	    *num_styles += 1;
391 	    if (num_args > expected_args)
392 		XmtWarningMsg("XmtParseWidgetType", "styleArgs",
393 			      "widget '%s':\n\tstyle '%s' expects up to %d args; %d passed.",
394 			      name, template_name, expected_args, num_args);
395 	    for(i=0; i < num_args; i++) XtFree(args[i]);
396 	    XtFree(template_name);
397 	}
398 	else
399 	    break;
400     }
401 
402     /* now we expect a widget type or template */
403     *type = NULL;
404     *template = NULL;
405     if (XmtLexerGetToken(l) != XmtLexerIdent) {
406 	XmtWarningMsg("XmtParseWidgetType", "syntax",
407 		      "syntax error in xmtChildren or xmtType resource\n\tof widget '%s'.",
408 		      name);
409 	return False;
410     }
411     *type = XmtLookupWidgetType(XmtLexerStrValue(l));
412     if (!*type) {
413 	*template = XmtLookupTemplate(w, XmtLexerStrValue(l));
414 	if (*template) {
415 	    template_name = XmtLexerStrValue(l);
416 	    XmtLexerConsumeToken(l);
417 	    XmtLexerGetArgList(l, args, MAX_TEMPLATE_ARGS, &num_args);
418 	    *template = XmtTemplateSubstituteArgs(*template, args, num_args,
419 						  &expected_args);
420 	    if (num_args > expected_args)
421 		XmtWarningMsg("XmtParseWidgetType", "templateArgs",
422 			      "widget '%s':\n\ttemplate '%s' expects up to %d args; %d passed.",
423 			      name, template_name, expected_args, num_args);
424 	    for(i=0; i < num_args; i++) XtFree(args[i]);
425 	    XtFree(template_name);
426 	}
427     }
428 
429     if (!*type && !*template)
430 	XmtWarningMsg("XmtParseWidgetType", "type",
431 		      "unknown widget type %s\n\tin xmtChildren or xmtType resource of widget %s.",
432 		      XmtLexerStrValue(l), name);
433     if (!*template) {
434 	XtFree(XmtLexerStrValue(l));
435 	XmtLexerConsumeToken(l);
436     }
437 
438     if (*type || *template) return True;
439     else {
440 	if (*num_styles) {
441 	    for(i=0; i < *num_styles; i++) XtFree(*styles[i]);
442 	    XtFree((char *)*styles);
443 	    *styles = NULL;
444 	    *num_styles = 0;
445 	}
446 	return False;
447     }
448 }
449 
450 #if NeedFunctionPrototypes
SetDialogInfo(XmtDialogInfo * info,String resource,Widget w,XmtWidgetType * type)451 static void SetDialogInfo(XmtDialogInfo *info, String resource,
452 			  Widget w, XmtWidgetType *type)
453 #else
454 static void SetDialogInfo(info, resource, w, type)
455 XmtDialogInfo *info;
456 String resource;
457 Widget w;
458 XmtWidgetType *type;
459 #endif
460 {
461     int i;
462     XrmQuark resourceq = XrmStringToQuark(resource);
463 
464     if ((type->get_value_proc == NULL) && (type->set_value_proc == NULL)) {
465 	XmtWarningMsg("XmtCreateChildren", "notype",
466 		      "Can't associate resource '%s' with child '%s';\n\twidget class '%s' has no get value nor set value procedure.",
467 		      resource, XtName(w), type->name);
468 	return;
469     }
470 
471     for(i = 0; i < info->num_resources; i++)
472 	if (info->resources[i].resource_name == (String)resourceq) break;
473 
474     if (i < info->num_resources) {
475 	info->widgets[i] = w;
476 	info->types[i] = type;
477     }
478     else
479 	XmtWarningMsg("XmtCreateChildren", "noname",
480 		      "Child '%s': resource name '%s' not found.",
481 		      XtName(w), resource);
482 }
483 
484 #if NeedFunctionPrototypes
CreateWidgetList(Widget parent,XmtLexer l,XmtDialogInfo * dialog_info,WidgetName * names,Cardinal num_names)485 static void CreateWidgetList(Widget parent, XmtLexer l,
486 			     XmtDialogInfo *dialog_info,
487 			     WidgetName *names, Cardinal num_names)
488 #else
489 static void CreateWidgetList(parent, l, dialog_info, names, num_names)
490 Widget parent;
491 XmtLexer l;
492 XmtDialogInfo *dialog_info;
493 WidgetName *names;
494 Cardinal num_names;
495 #endif
496 {
497     Boolean managed;
498     XmtWidgetType *type;
499     String template;
500     String *styles;
501     Cardinal num_styles;
502     XmtLexerToken tok;
503     Widget child;
504     int i;
505 
506     if (ParseType(parent, XtName(parent), l, &type, &template,
507 		  &managed, &styles, &num_styles) == False)
508 	goto error;
509 
510     /* now read a list of names, and create them */
511     /* grammar:  id [= name] (',' id[= name])* ';' */
512     while (1) {
513 	if (XmtLexerGetToken(l) != XmtLexerIdent) goto syntax;
514 	child = CreateChild(parent, XmtLexerStrValue(l), type, template,
515 			    managed, styles, num_styles, True, dialog_info,
516 			    names, num_names);
517 	XtFree(XmtLexerStrValue(l));
518 	tok = XmtLexerNextToken(l);
519 	if (tok == XmtLexerEqual) {
520 	    tok = XmtLexerNextToken(l);
521 	    if (tok != XmtLexerIdent) goto syntax;
522 	    if (!type) {
523 		XmtWarningMsg("XmtCreateChildren", "resource",
524 			      "child '%s' cannot have a resource name '%s':\n\tchild's type is a template, not a registered widget type.",
525 			      XtName(child), XmtLexerStrValue(l));
526 	    }
527 	    else if (dialog_info)
528 		SetDialogInfo(dialog_info, XmtLexerStrValue(l), child, type);
529 	    else
530 		XmtWarningMsg("XmtCreateChildren", "resource",
531 			      "child '%s' cannot have a resource name '%s':\n\tthere is no resource list associated with this widget tree.",
532 			      XtName(child), XmtLexerStrValue(l));
533 
534 	    XtFree(XmtLexerStrValue(l));
535 	    tok = XmtLexerNextToken(l);
536 	}
537 	if (tok == XmtLexerSemicolon) break;
538 	else if (tok != XmtLexerComma) goto syntax;
539 	XmtLexerConsumeToken(l);
540     }
541     XmtLexerConsumeToken(l); /* skip the semicolon */
542 
543     if (template) XtFree(template);
544     if (num_styles) {
545 	for(i=0; i < num_styles; i++) XtFree(styles[i]);
546 	XtFree((char *)styles);
547     }
548 
549     /* eat the final semicolon, and we're done */
550     XmtLexerConsumeToken(l);
551     return;
552 
553  syntax:
554     XmtWarningMsg("XmtCreateChildren", "syntax",
555 		  "syntax error in xmtChildren resource\n\t of widget %s",
556 		  XtName(parent));
557  error: /* read till semicolon */
558     while(((tok = XmtLexerNextToken(l)) != XmtLexerSemicolon) &&
559 	  (tok != XmtLexerEndOfString));
560     XmtLexerConsumeToken(l);
561 }
562 
563 
564 static XtResource children_resource[] = {
565 {XmtNxmtChildren, XmtCXmtChildren, XtRString,
566      sizeof(String), 0, XtRString, NULL}
567 };
568 
569 #if NeedFunctionPrototypes
CreateChildren(Widget parent,XmtDialogInfo * dialog_info,WidgetName * names,Cardinal num_names)570 static void CreateChildren(Widget parent, XmtDialogInfo *dialog_info,
571                            WidgetName *names, Cardinal num_names)
572 #else
573 static void CreateChildren(parent, dialog_info, names, num_names)
574 Widget parent;
575 XmtDialogInfo *dialog_info;
576 WidgetName *names;
577 Cardinal num_names;
578 #endif
579 {
580     String children_string;
581     XmtLexer lexer;
582 
583     /* fetch the value of the xmtChildren resource */
584     XtGetApplicationResources(parent, (XtPointer)&children_string,
585 			      children_resource, (Cardinal) 1,
586 			      NULL, (Cardinal)0);
587 
588     /* XXX should we issue a warning here? */
589     if (children_string == NULL) return;
590 
591     /*
592      * get ready to parse the string.
593      * we copy the string because the process of parsing it can cause
594      * new resource files to be loaded, which could cause it to be freed
595      * from underneath us.
596      */
597 
598     children_string = XtNewString(children_string);
599     lexer = XmtLexerCreate(keywords, XtNumber(keywords));
600     XmtLexerInit(lexer, children_string);
601 
602     while(XmtLexerGetToken(lexer) != XmtLexerEndOfString)
603 	CreateWidgetList(parent, lexer, dialog_info, names, num_names);
604 
605     XmtLexerDestroy(lexer);
606     XtFree(children_string);
607 }
608 
609 
610 #if NeedFunctionPrototypes
_XmtCreateChildren(Widget parent,WidgetName * names,Cardinal num_names)611 static void _XmtCreateChildren(Widget parent,
612 			       WidgetName *names, Cardinal num_names)
613 #else
614 static void _XmtCreateChildren(parent, names, num_names)
615 Widget parent;
616 WidgetName *names;
617 Cardinal num_names;
618 #endif
619 {
620     XmtDialogInfo *dialog_info;
621     String requires_string;
622 
623     /* see if there is a resource list associated with this parent */
624     dialog_info = _XmtDialogLookupDialogInfo(parent);
625 
626     /* first, load any required files */
627     XtGetApplicationResources(parent, (XtPointer)&requires_string,
628 			      requires_resource, (Cardinal)1,
629 			      NULL, (Cardinal) 0);
630     if (requires_string) XmtLoadResourceFileList(parent, requires_string);
631 
632     /* do the rest */
633     CreateChildren(parent, dialog_info, names, num_names);
634 }
635 
636 #if NeedFunctionPrototypes
XmtCreateChildren(Widget parent)637 void XmtCreateChildren(Widget parent)
638 #else
639 void XmtCreateChildren(parent)
640 Widget parent;
641 #endif
642 {
643     _XmtCreateChildren(parent, NULL, 0);
644 }
645 
646 #if NeedFunctionPrototypes
GetWidgetNames(va_list var,WidgetName ** names_return,Cardinal * num_return)647 static void GetWidgetNames(va_list var,
648 			   WidgetName **names_return, Cardinal *num_return)
649 #else
650 static void GetWidgetNames(var, names_return, num_return)
651 va_list var;
652 WidgetName **names_return;
653 Cardinal *num_return;
654 #endif
655 {
656     WidgetName *names;
657     String name;
658     Cardinal num, max;
659 
660     num = max = 0;
661     names = NULL;
662     while((name = va_arg(var, String)) != NULL) {
663 	if (num == max) {
664 	    max += 10;
665 	    names = (WidgetName *)XtRealloc((char *)names,
666 					    max * sizeof(WidgetName));
667 	}
668 	names[num].nameq = XrmStringToQuark(name);
669 	names[num].widgetp = va_arg(var, Widget *);
670 	/* initialize *widgetp to NULL in case it is not found */
671 	*names[num].widgetp = NULL;
672 	num++;
673     }
674 
675     *names_return = names;
676     *num_return = num;
677 }
678 
679 #if NeedVarargsPrototypes
XmtCreateQueryChildren(Widget parent,...)680 void XmtCreateQueryChildren(Widget parent, ...)
681 #else
682 void XmtCreateQueryChildren(parent, va_alist)
683 Widget parent;
684 va_dcl
685 #endif
686 {
687     va_list var;
688     WidgetName *names;
689     Cardinal num_names;
690 
691     Va_start(var, parent);
692     GetWidgetNames(var, &names, &num_names);
693     va_end(var);
694     _XmtCreateChildren(parent, names, num_names);
695     XtFree((char *)names);
696 }
697 
698 #if NeedFunctionPrototypes
XmtCreateQueryListChildren(Widget parent,XmtWidgetList * names,Cardinal num_names)699 void XmtCreateQueryListChildren(Widget parent, XmtWidgetList * names,
700 				Cardinal num_names)
701 #else
702 void XmtCreateQueryListChildren(parent, names, num_names)
703 Widget parent;
704 XmtWidgetList * names;
705 Cardinal num_names;
706 #endif
707 {
708     /*
709      * initialize widgets to NULL
710      */
711     int i;
712     for (i = 0; i < num_names; i++) {
713         *names[i].widgetp = NULL;
714     }
715 
716     _XmtCreateChildren(parent, names, num_names);
717 }
718 
719 static XtResource type_resource[] = {
720 {XmtNxmtType, XmtCXmtType, XtRString,
721      sizeof(String), 0, XtRString, NULL}
722 };
723 
724 
725 #if NeedFunctionPrototypes
_XmtCreateChild(Widget parent,StringConst name,XmtDialogInfo * dialog_info,WidgetName * names,Cardinal num_names)726 static Widget _XmtCreateChild(Widget parent, StringConst name,
727                               XmtDialogInfo *dialog_info,
728                               WidgetName *names, Cardinal num_names)
729 #else
730 static Widget _XmtCreateChild(parent, name, dialog_info, names, num_names)
731 Widget parent;
732 StringConst name;
733 XmtDialogInfo *dialog_info;
734 WidgetName *names;
735 Cardinal num_names;
736 #endif
737 {
738     String requires_string, type_string;
739     XmtLexer lexer;
740     XmtWidgetType *type;
741     String template;
742     Boolean managed;
743     String *styles;
744     Cardinal num_styles;
745     Widget w;
746     int i;
747 
748     /* first, load any required files XXX ?*/
749     XtGetSubresources(parent, (XtPointer)&requires_string,
750 		      (String)name, (String)name,
751 		      requires_resource, (Cardinal)1,
752 		      NULL, (Cardinal) 0);
753     if (requires_string) XmtLoadResourceFileList(parent, requires_string);
754 
755     /* fetch the value of the xmtType resource */
756     XtGetSubresources(parent, (XtPointer)&type_string,
757 		      (String)name, (String)name,
758 		      type_resource, (Cardinal) 1,
759 		      NULL, (Cardinal)0);
760 
761     if (type_string == NULL) {
762 	XmtWarningMsg("XmtCreateChild", "noType",
763 		      "widget '%s' has no xmtType resource.",
764 		      name);
765 	return NULL;
766     }
767 
768     /* get ready to parse the string */
769     lexer = XmtLexerCreate(keywords, XtNumber(keywords));
770     XmtLexerInit(lexer, type_string);
771 
772     /*
773      * if we parse it sucessfully, create the child.
774      * Note that CreateChild won't re-load the required files.
775      */
776     if (ParseType(parent, name, lexer, &type, &template,
777 		  &managed, &styles, &num_styles)) {
778 	w = CreateChild(parent, name, type, template,
779 			managed, styles, num_styles, False,
780 			dialog_info, names, num_names);
781 	if (template) XtFree(template);
782 	if (num_styles) {
783 	    for(i=0; i < num_styles; i++) XtFree(styles[i]);
784 	    XtFree((char *)styles);
785 	}
786     }
787     else
788 	w = NULL;
789 
790     XmtLexerDestroy(lexer);
791     return w;
792 }
793 
794 #if NeedFunctionPrototypes
XmtCreateChild(Widget parent,StringConst name)795 Widget XmtCreateChild(Widget parent, StringConst name)
796 #else
797 Widget XmtCreateChild(parent, name)
798 Widget parent;
799 StringConst name;
800 #endif
801 {
802     return _XmtCreateChild(parent, name, NULL, NULL, 0);
803 }
804 
805 #if NeedVarargsPrototypes
XmtCreateQueryChild(Widget parent,StringConst name,...)806 Widget XmtCreateQueryChild(Widget parent, StringConst name, ...)
807 #else
808 Widget XmtCreateQueryChild(parent, name, va_alist)
809 Widget parent;
810 StringConst name;
811 va_dcl
812 #endif
813 {
814     va_list var;
815     WidgetName *names;
816     Cardinal num_names;
817     Widget child;
818 
819     Va_start(var, name);
820     GetWidgetNames(var, &names, &num_names);
821     va_end(var);
822     child = _XmtCreateChild(parent, name, NULL, names, num_names);
823     XtFree((char *)names);
824     return child;
825 }
826 
827 #if NeedFunctionPrototypes
XmtCreateQueryListChild(Widget parent,StringConst name,XmtWidgetList * names,Cardinal num_names)828 Widget XmtCreateQueryListChild(Widget parent, StringConst name,
829 			       XmtWidgetList * names, Cardinal num_names)
830 #else
831 Widget XmtCreateQueryListChild(parent, name, names, num_names)
832 Widget parent;
833 StringConst name;
834 XmtWidgetList * names;
835 Cardinal num_names;
836 #endif
837 {
838     /*
839      * initialize widgets to NULL
840      */
841     int i;
842     for (i = 0; i < num_names; i++) {
843         *names[i].widgetp = NULL;
844     }
845     return _XmtCreateChild(parent, name, NULL, names, num_names);
846 }
847 
848 #if NeedFunctionPrototypes
_XmtBuildDialog(Widget parent,StringConst dialog_name,XtResourceList resources,Cardinal num_resources,WidgetName * names,Cardinal num_names)849 static Widget _XmtBuildDialog(Widget parent, StringConst dialog_name,
850 			      XtResourceList resources, Cardinal num_resources,
851 			      WidgetName *names, Cardinal num_names)
852 #else
853 static Widget _XmtBuildDialog(parent, dialog_name, resources, num_resources,
854 			      names, num_names)
855 Widget parent;
856 StringConst dialog_name;
857 XtResourceList resources;
858 Cardinal num_resources;
859 WidgetName *names;
860 Cardinal num_names;
861 #endif
862 {
863     Widget shell;
864     Arg arg;
865 
866     /* create the dialog shell */
867     /* XXX do I need/want allowShellResize?  What happens without? */
868     XtSetArg(arg, XmNallowShellResize, True);
869     shell = XmCreateDialogShell(parent, (String)dialog_name, &arg, 1);
870 
871     /* associate the resources with the shell */
872     XmtDialogBindResourceList(shell, resources, num_resources);
873 
874     /* create the dialog child and its children */
875     _XmtCreateChildren(shell, names, num_names);
876 
877     /* return the dialog child, if any, or warn and return NULL */
878     if (((CompositeWidget)shell)->composite.num_children)
879 	return ((CompositeWidget)shell)->composite.children[0];
880     else
881 	XmtWarningMsg("XmtBuildDialog", "nochild",
882 		      "No xmtChildren resource for shell widget '%s'",
883 		      dialog_name);
884     return NULL;
885 }
886 
887 #if NeedFunctionPrototypes
XmtBuildDialog(Widget parent,StringConst dialog_name,XtResourceList resources,Cardinal num_resources)888 Widget XmtBuildDialog(Widget parent, StringConst dialog_name,
889 		      XtResourceList resources, Cardinal num_resources)
890 #else
891 Widget XmtBuildDialog(parent, dialog_name, resources, num_resources)
892 Widget parent;
893 StringConst dialog_name;
894 XtResourceList resources;
895 Cardinal num_resources;
896 #endif
897 {
898     return _XmtBuildDialog(parent, dialog_name,
899 			   resources, num_resources,
900 			   NULL, 0);
901 }
902 
903 
904 #if NeedVarargsPrototypes
XmtBuildQueryDialog(Widget parent,StringConst dialog_name,XtResourceList resources,Cardinal num_resources,...)905 Widget XmtBuildQueryDialog(Widget parent, StringConst dialog_name,
906 			   XtResourceList resources, Cardinal num_resources,
907 			   ...)
908 #else
909 Widget XmtBuildQueryDialog(parent, dialog_name,
910 			   resources, num_resources, va_alist)
911 Widget parent;
912 StringConst dialog_name;
913 XtResourceList resources;
914 Cardinal num_resources;
915 va_dcl
916 #endif
917 {
918     va_list var;
919     WidgetName *names;
920     Cardinal num_names;
921     Widget dialog;
922 
923     Va_start(var, num_resources);
924     GetWidgetNames(var, &names, &num_names);
925     va_end(var);
926     dialog = _XmtBuildDialog(parent, dialog_name,
927 			     resources, num_resources,
928 			     names, num_names);
929     XtFree((char *)names);
930     return dialog;
931 }
932 
933 #if NeedVarargsPrototypes
XmtBuildQueryToplevel(Widget parent,StringConst name,...)934 Widget XmtBuildQueryToplevel(Widget parent, StringConst name,  ...)
935 #else
936 Widget XmtBuildQueryToplevel(parent, name, va_alist)
937 Widget parent;
938 StringConst name;
939 va_dcl
940 #endif
941 {
942     va_list var;
943     WidgetName *names;
944     Cardinal num_names;
945     Widget shell;
946 
947     shell = XtCreatePopupShell((String)name, topLevelShellWidgetClass,
948 			       parent, NULL, 0);
949 
950     Va_start(var, name);
951     GetWidgetNames(var, &names, &num_names);
952     va_end(var);
953     _XmtCreateChildren(shell, names, num_names);
954     XtFree((char *)names);
955     if (!((CompositeWidget)shell)->composite.num_children)
956 	XmtWarningMsg("XmtBuildToplevel", "nochild",
957 		      "No xmtChildren resource for shell widget '%s'",
958 		      name);
959     return shell;
960 }
961 
962 #if NeedFunctionPrototypes
XmtBuildToplevel(Widget parent,StringConst name)963 Widget XmtBuildToplevel(Widget parent, StringConst name)
964 #else
965 Widget XmtBuildToplevel(parent, name)
966 Widget parent;
967 StringConst name;
968 #endif
969 {
970     return XmtBuildQueryToplevel(parent, name, NULL);
971 }
972 
973 #if NeedVarargsPrototypes
XmtBuildQueryApplication(StringConst appname,StringConst appclass,Display * display,ArgList args,Cardinal num_args,...)974 Widget XmtBuildQueryApplication(StringConst appname, StringConst appclass,
975 				Display *display,
976 				ArgList args, Cardinal num_args, ...)
977 #else
978 Widget XmtBuildQueryApplication(appname, appclass, display, args, num_args,
979 				va_alist)
980 StringConst appname, appclass;
981 Display *display;
982 ArgList args;
983 Cardinal num_args;
984 va_dcl
985 #endif
986 {
987     va_list var;
988     WidgetName *names;
989     Cardinal num_names;
990     Widget rootshell;
991 
992     rootshell = XtAppCreateShell((String)appname, (String)appclass,
993 				 applicationShellWidgetClass,
994 				 display, args, num_args);
995     Va_start(var, num_args);
996     GetWidgetNames(var, &names, &num_names);
997     va_end(var);
998     _XmtCreateChildren(rootshell, names, num_names);
999     XtFree((char *)names);
1000 
1001     if (!((CompositeWidget)rootshell)->composite.num_children)
1002 	XmtWarningMsg("XmtBuildApplication", "nochild",
1003 		      "No xmtChildren resource for root shell widget '%s'",
1004 		      appname);
1005 
1006     XmtInitializeApplicationShell(rootshell, args, num_args);
1007     return rootshell;
1008 }
1009 
1010 #if NeedFunctionPrototypes
XmtBuildApplication(StringConst appname,StringConst appclass,Display * display,ArgList args,Cardinal num_args)1011 Widget XmtBuildApplication(StringConst appname, StringConst appclass,
1012 			   Display *display,
1013 			   ArgList args, Cardinal num_args)
1014 #else
1015 Widget XmtBuildApplication(appname, appclass, display, args, num_args)
1016 StringConst appname, appclass;
1017 Display *display;
1018 ArgList args;
1019 Cardinal num_args;
1020 #endif
1021 {
1022     return XmtBuildQueryApplication(appname, appclass, display,
1023 				    args, num_args, NULL);
1024 }
1025