2 #include <X11/StringDefs.h>
3 #include <X11/IntrinsicP.h>
8 #include <Xm/BulletinB.h>
12 #include <Xm/PushBG.h>
13 #include <Xm/CascadeB.h>
14 #include <Xm/ToggleB.h>
15 #include <Xm/ToggleBG.h>
16 #include <Xm/RowColumn.h>
17 #include <Xm/Separator.h>
20 static char rcsid[] = "$Header$";
22 #define MAX(a,b) ((a > b) ? a : b)
23 #define MIN(a,b) ((a < b) ? a : b)
31 Widget BuildMenuTree();
32 Widget MakeRadioField();
33 int button_callback();
34 void radio_callback();
35 void string_callback();
36 void boolean_callback();
39 extern void UpdateForm();
40 extern int PopupErrorMessage();
41 extern void PopupHelpWindow();
42 extern int AppendToLog();
43 extern void MakeWatchCursor();
44 extern void MakeNormalCursor();
45 extern Widget SetupLogWidget();
49 manage_widget(w, widget, call_data)
51 XmAnyCallbackStruct *call_data;
53 XtManageChild(widget);
57 button_callback(w, client_data, call_data)
59 EntryForm *client_data;
60 XmAnyCallbackStruct *call_data;
65 /* sprintf (output, "Button %x was hit...\n", w);
67 MakeWatchCursor(toplevel);
68 MakeWatchCursor(entryformwidget);
72 MakeNormalCursor(toplevel);
73 MakeNormalCursor(entryformwidget);
77 PopupErrorMessage("Sorry, no functionality here!\nSecond line", "No further help is available");
79 XtUnmanageChild(client_data->formpointer);
85 BuildMenuTree(topW, spec)
89 return (CreateMenu(topW, spec->submenu, XmHORIZONTAL));
93 ** Read the specification and put up a menu to match...
97 CreateMenu(parent, spec, orientation)
103 MenuItem *curmenuitem;
104 Widget childbutton, childmenu;
107 XmString label; /* !@#$%^ compound string required */
109 label = XmStringCreate( "Complete junk", XmSTRING_DEFAULT_CHARSET);
112 XtSetArg(wargs[n], XmNlabelString, label); n++;
114 if (orientation == XmHORIZONTAL) {
115 XtSetArg(wargs[n], XmNspacing, 5); n++;
116 menuparent = XmCreateMenuBar( parent, "randommenu",
118 XtManageChild(menuparent);
121 menuparent = XmCreatePulldownMenu(parent, "randommenu",
124 for ( curmenuitem = (*spec);
126 spec++, curmenuitem = (*spec)) {
129 printf ("Making entry: %s\n", curmenuitem->label);
131 label = XmStringCreate( curmenuitem->label,
132 XmSTRING_DEFAULT_CHARSET);
134 XtSetArg(wargs[n], XmNlabelString, label); n++;
136 if (curmenuitem->submenu) {
138 printf ("It has a submenu, which I'm recursing on...\n");
140 childmenu = CreateMenu( menuparent,
141 curmenuitem->submenu,
143 XtSetArg(wargs[n], XmNsubMenuId, childmenu); n++;
145 childbutton = XtCreateManagedWidget( "child",
146 xmCascadeButtonWidgetClass,
147 menuparent, wargs, n);
152 childbutton = XtCreateManagedWidget( "child",
153 xmPushButtonGadgetClass,
154 menuparent, wargs, n);
156 XtAddCallback( childbutton,
158 menu_callback, curmenuitem);
166 ** Read the specification and put up a form to match...
170 CreateForm(parent, spec)
177 XmString label; /* compound string required */
178 Dimension height_so_far = 0, width_so_far = 0;
179 Dimension height, width;
180 Widget titleW, instructionW;
184 if (spec->formpointer) {
186 return(spec->formpointer);
189 height_so_far = vpad;
191 #define GETSIZE(foo) n = 0; \
192 XtSetArg(wargs[n], XtNwidth, &width); n++; \
193 XtSetArg(wargs[n], XtNheight, &height); n++; \
194 XtGetValues (foo, wargs, n); \
196 #define STORESIZE if (width > width_so_far) width_so_far = width;\
197 height_so_far += height + vpad;
201 XtSetArg(wargs[n], XmNautoUnmanage, False); n++;
202 bb = XmCreateBulletinBoardDialog(parent, "board", wargs, n);
204 spec->formpointer = bb;
207 label = XmStringCreate(spec->formname, XmSTRING_DEFAULT_CHARSET);
209 XtSetArg(wargs[n], XmNlabelString, label); n++;
210 XtSetArg(wargs[n], XtNx, 0); n++;
211 XtSetArg(wargs[n], XtNy, 0); n++;
212 titleW = XtCreateManagedWidget( "title",
219 label = XmStringCreate(spec->instructions, XmSTRING_DEFAULT_CHARSET);
221 XtSetArg(wargs[n], XmNlabelString, label); n++;
222 XtSetArg(wargs[n], XtNx, 0); n++;
223 XtSetArg(wargs[n], XtNy, height_so_far); n++;
224 instructionW = XtCreateManagedWidget( "instructions",
227 GETSIZE(instructionW);
230 height = height_so_far;
231 width = width_so_far;
232 MakeInputLines(bb, &height, &width, spec);
235 height = height_so_far;
236 width = width_so_far;
237 MakeButtons(bb, &height, &width, spec);
241 ** Center the title of the form
245 XtSetArg(wargs[n], XtNwidth, &width); n++;
246 XtGetValues (titleW, wargs, n);
248 x = (width_so_far - width) / 2;
251 XtSetArg(wargs[n], XtNx, x); n++;
252 XtSetValues (titleW, wargs, n);
255 XtSetArg(wargs[n], XtNwidth, &width); n++;
256 XtGetValues (instructionW, wargs, n);
258 x = (width_so_far - width) / 2;
261 XtSetArg(wargs[n], XtNx, x); n++;
262 XtSetValues (instructionW, wargs, n);
268 ** Pheight and pwidth start with the values-to-date of the bboard so far.
269 ** Return your height and width in them when you're done.
271 ** Positioning the widgets happens in two phases:
272 ** First, we set their y-positions as we create them.
273 ** After they're created, we go back and adjust the x-positions
274 ** according to the widest left side noted.
277 MakeInputLines(parent, pheight, pwidth, spec)
284 XmString label; /* compound string required */
288 Dimension width, height, maxleftwidth = 0, maxrightwidth = 0;
289 Dimension localy, leftheight = 0, rightheight = 0;
290 UserPrompt **myinputlines = spec->inputlines;
294 for ( current = (*myinputlines), localy = 0, i = 0;
296 myinputlines++, current = (*myinputlines), i++) {
300 printf ("Making entry %d: %s of type %d\n",
301 i, current->prompt, current->type);
304 ** First, make the prompt
306 label = XmStringCreate( current->prompt,
307 XmSTRING_DEFAULT_CHARSET);
309 XtSetArg(wargs[n], XmNlabelString, label); n++;
310 XtSetArg(wargs[n], XtNy, localy + *pheight); n++;
311 child = XtCreateManagedWidget( "prompt",
317 if (width > maxleftwidth)
318 maxleftwidth = width;
321 ** Second, make the input widget
324 XtSetArg(wargs[n], XtNy, localy + *pheight); n++;
325 XtSetArg(wargs[n], XmNtraversalOn, True); n++;
326 XtSetArg(wargs[n], XtNsensitive,
327 !(current->insensitive)); n++;
328 switch (current->type) {
330 children[i] = XtCreateManagedWidget( "textwidget",
333 XtAddCallback( children[i], XmNvalueChangedCallback,
334 string_callback, current);
335 if (current->returnvalue.stringvalue) {
336 XmTextSetString (children[i], current->returnvalue.stringvalue);
338 GETSIZE (children[i]);
339 rightheight = height;
340 if (width > maxrightwidth)
341 maxrightwidth = width;
345 XtSetArg(wargs[n], XmNset,
346 current->returnvalue.booleanvalue ? True : False); n++;
348 if (current->returnvalue.booleanvalue)
349 label = XmStringCreate( "(True)", XmSTRING_DEFAULT_CHARSET);
351 label = XmStringCreate( "(False)", XmSTRING_DEFAULT_CHARSET);
352 XtSetArg(wargs[n], XmNlabelString, label); n++;
354 children[i] = XtCreateManagedWidget( "ignore this",
355 xmToggleButtonWidgetClass,
358 XtAddCallback( children[i], XmNvalueChangedCallback,
359 boolean_callback, current);
361 GETSIZE (children[i]);
362 rightheight = height;
363 if (width > maxrightwidth)
364 maxrightwidth = width;
369 MakeRadioField(parent, current, &rightheight);
370 XtManageChild(children[i]);
371 XtSetValues(children[i], wargs, n);
372 GETSIZE (children[i]);
373 if (width > maxrightwidth)
374 maxrightwidth = width;
378 printf ("Sorry, don't recognize that type\n");
381 XmAddTabGroup(children[i]);
382 current->mywidget = children[i];
384 localy += MAX(rightheight, leftheight) + vpad;
388 ** Now slide the input widgets right as far as the widest prompt.
391 XtSetArg(wargs[n], XtNx, maxleftwidth + hpad); n++;
393 XtSetValues (children[i - 1], wargs, n);
395 *pheight = localy - vpad;
396 *pwidth = maxleftwidth + maxrightwidth + hpad;
400 ** All the junk about keeping track of the sum of the children's heights
401 ** is because the !#$% RowColumn widget doesn't sum them for us, NOR
402 ** does it accept SetValues on its XtNHeight! Thanks, Motif!
406 MakeRadioField(parent, prompt, pheight)
411 Widget radioparent, child;
415 XmString label; /* accursed compound string required */
416 Dimension height, width;
420 if (!prompt->keywords) {
421 fprintf (stderr, "Warning: No list of keywords for widget\n");
424 for ( count = 0, keywords = prompt->keywords;
426 keywords++, count++);
429 ** Although the XmNnumColumns resource is documented as actually
430 ** representing the number of _rows_ when XmNorientation is set to XmVERTICAL,
431 ** it doesn't. So I need to count the items myself and manually set the
432 ** number of columns to get a maximum of five rows. There's no XmNnumRows
433 ** resource. Thanks, Motif!
437 XtSetArg(wargs[n], XmNspacing, 0); n++;
440 XtSetArg(wargs[n], XmNnumColumns, 1 + (count-1) / 5); n++;
441 XtSetArg(wargs[n], XmNorientation, XmVERTICAL); n++;
442 XtSetArg(wargs[n], XmNpacking, XmPACK_COLUMN); n++;
445 radioparent = XmCreateRadioBox(parent, "radio", wargs, n);
447 keywords = prompt->keywords;
448 for (current=(*keywords); current; keywords++, current=(*keywords)) {
450 label = XmStringCreate(current, XmSTRING_DEFAULT_CHARSET);
451 XtSetArg(wargs[n], XmNlabelString, label); n++;
452 if ((prompt->returnvalue.stringvalue) &&
453 (!strcmp (current, prompt->returnvalue.stringvalue))) {
454 XtSetArg(wargs[n], XmNset, True); n++;
457 XtSetArg(wargs[n], XmNset, False); n++;
459 child = XtCreateManagedWidget( current,
460 xmToggleButtonWidgetClass,
461 radioparent, wargs, n);
463 XtAddCallback( child, XmNvalueChangedCallback,
464 radio_callback, prompt);
468 ** Assume all child widgets are the same height. Increase height by
469 ** five times this, or the actual number of children, whichever is lesser.
473 *pheight = (height * MIN(5, count)) + vpad;
478 MakeButtons(parent, pheight, pwidth, spec)
484 BottomButton *current;
485 XmString label; /* compound string required */
488 Dimension newwidth, width = 25;
490 BottomButton **buttons = spec->buttons;
495 XtSetArg(wargs[n], XtNy, *pheight); n++;
496 XtSetArg(wargs[n], XtNx, 0); n++;
497 XtSetArg(wargs[n], XtNwidth, *pwidth); n++;
498 XtCreateManagedWidget( "separator",
499 xmSeparatorWidgetClass,
503 for ( current=(*buttons);
505 buttons++, current=(*buttons)) {
508 printf ("Making a button labeled %s\n", current->label);
510 label = XmStringCreate( current->label,
511 XmSTRING_DEFAULT_CHARSET);
513 XtSetArg(wargs[n], XtNy, (*pheight)); n++;
514 XtSetArg(wargs[n], XtNx, width); n++;
515 XtSetArg(wargs[n], XmNlabelString, label); n++;
517 newbutton = XtCreateManagedWidget( current->label,
518 xmPushButtonWidgetClass,
521 XtAddCallback( newbutton, XmNactivateCallback,
522 current->returnfunction, spec);
524 XtSetArg(wargs[n], XtNwidth, &newwidth); n++;
525 XtGetValues (newbutton, wargs, n);
527 width += (newwidth + hpad);
534 radio_callback(w, client_data, call_data)
536 XmAnyCallbackStruct *client_data;
537 XmAnyCallbackStruct *call_data;
543 UserPrompt *prompt = (UserPrompt *) client_data;
546 XtSetArg(wargs[n], XmNset, &is_set); n++;
547 XtGetValues (w, wargs, n);
553 ** Since Motif insists on using !@#$% Compound Strings as the text for
554 ** its label widgets, but doesn't provide a way of getting a char* back
555 ** from a !@#$% Compound String, I can't retrieve the label of the button
558 ** Fortunately, I was smart enough to use the button label as the name
559 ** of the widget, and I can extract it via XtName(). Thanks, Motif!
561 if (prompt->returnvalue.stringvalue &&
562 (strcmp(prompt->returnvalue.stringvalue, XtName(w)))) {
563 strcpy(prompt->returnvalue.stringvalue, XtName(w));
569 boolean_callback(w, client_data, call_data)
571 XmAnyCallbackStruct *client_data;
572 XmAnyCallbackStruct *call_data;
577 UserPrompt *current = (UserPrompt *)client_data;
581 XtSetArg(wargs[n], XmNset, &is_set); n++;
582 XtGetValues (w, wargs, n);
584 current->returnvalue.booleanvalue = is_set;
587 label = XmStringCreate( "(True)", XmSTRING_DEFAULT_CHARSET);
589 label = XmStringCreate( "(False)", XmSTRING_DEFAULT_CHARSET);
591 XtSetArg(wargs[n], XmNlabelString, label); n++;
592 XtSetValues (w, wargs, n);
595 printf ("boolean_callback: button %x is %s\n",
596 w, (is_set ? "True" : "False"));
601 menu_callback(w, client_data, call_data)
603 XmAnyCallbackStruct *client_data;
604 XmAnyCallbackStruct *call_data;
606 MenuItem *itemhit = (MenuItem *) client_data;
608 /* printf ("menu_callback: item '%s', op %d and string '%s'\n",
612 XtManageChild(entryformwidget);
614 MoiraMenuRequest(itemhit);
619 string_callback(w, client_data, call_data)
621 XmAnyCallbackStruct *client_data;
622 XmAnyCallbackStruct *call_data;
624 UserPrompt *current = (UserPrompt *)client_data;
627 newvalue = XmTextGetString(w);
629 if (strcmp(current->returnvalue.stringvalue, newvalue)) {
630 /* printf ("Replacing old value of selection, '%s', with '%s'\n",
631 current->returnvalue.stringvalue,
633 */ strcpy(current->returnvalue.stringvalue, newvalue);