]>
Commit | Line | Data |
---|---|---|
41a6b53e | 1 | /* $Header$ */ |
2 | ||
7ee9b49f | 3 | #include <stdio.h> |
4 | #include <X11/StringDefs.h> | |
5 | #include <X11/IntrinsicP.h> | |
6 | #include <X11/Shell.h> | |
7 | #include <X11/Core.h> | |
8 | #include <X11/CoreP.h> | |
9 | #include <Xm/Xm.h> | |
10 | #include <Xm/BulletinB.h> | |
41a6b53e | 11 | #include <Xm/BulletinBP.h> |
7ee9b49f | 12 | #include <Xm/Label.h> |
13 | #include <Xm/Text.h> | |
41a6b53e | 14 | #include <Xm/TextP.h> |
7ee9b49f | 15 | #include <Xm/PushB.h> |
16 | #include <Xm/PushBG.h> | |
17 | #include <Xm/CascadeB.h> | |
18 | #include <Xm/ToggleB.h> | |
19 | #include <Xm/ToggleBG.h> | |
20 | #include <Xm/RowColumn.h> | |
41a6b53e | 21 | #include <Xm/RowColumnP.h> |
7ee9b49f | 22 | #include <Xm/Separator.h> |
3583baaa | 23 | #include <Xm/Traversal.h> |
7ee9b49f | 24 | #include "mmoira.h" |
25 | ||
892c98b2 | 26 | static char rcsid[] = "$Header$"; |
27 | ||
41a6b53e | 28 | #ifndef MAX |
7ee9b49f | 29 | #define MAX(a,b) ((a > b) ? a : b) |
41a6b53e | 30 | #endif |
31 | #ifndef MIN | |
ecb7d146 | 32 | #define MIN(a,b) ((a < b) ? a : b) |
41a6b53e | 33 | #endif |
7ee9b49f | 34 | |
4fa286c6 | 35 | int hpad = 10; |
36 | int vpad = 5; | |
7ee9b49f | 37 | |
7ee9b49f | 38 | void manage_widget(); |
39 | Widget CreateForm(); | |
40 | Widget CreateMenu(); | |
41 | Widget BuildMenuTree(); | |
ecb7d146 | 42 | Widget MakeRadioField(); |
892c98b2 | 43 | int button_callback(); |
ecb7d146 | 44 | void radio_callback(); |
ecb7d146 | 45 | void string_callback(); |
892c98b2 | 46 | void boolean_callback(); |
7ee9b49f | 47 | void menu_callback(); |
3583baaa | 48 | void newvalue(); |
41a6b53e | 49 | void MoiraFocusOut(); |
3583baaa | 50 | EntryForm *WidgetToForm(); |
7ee9b49f | 51 | |
4fa286c6 | 52 | extern void UpdateForm(); |
892c98b2 | 53 | extern int PopupErrorMessage(); |
54 | extern void PopupHelpWindow(); | |
55 | extern int AppendToLog(); | |
892c98b2 | 56 | extern void MakeWatchCursor(); |
57 | extern void MakeNormalCursor(); | |
58 | extern Widget SetupLogWidget(); | |
7ee9b49f | 59 | |
41a6b53e | 60 | static XtActionsRec myactions[] = { |
61 | { "MoiraFocusOut", MoiraFocusOut }, | |
62 | }; | |
63 | ||
892c98b2 | 64 | |
65 | void | |
66 | manage_widget(w, widget, call_data) | |
67 | Widget w, widget; | |
68 | XmAnyCallbackStruct *call_data; | |
ecb7d146 | 69 | { |
892c98b2 | 70 | XtManageChild(widget); |
71 | } | |
ecb7d146 | 72 | |
892c98b2 | 73 | int |
b2d21e59 | 74 | button_callback(w, client_data, call_data) |
75 | Widget w; | |
76 | EntryForm *client_data; | |
892c98b2 | 77 | XmAnyCallbackStruct *call_data; |
78 | { | |
b2d21e59 | 79 | XtUnmanageChild(client_data->formpointer); |
892c98b2 | 80 | } |
81 | ||
82 | ||
83 | Widget | |
84 | BuildMenuTree(topW, spec) | |
85 | Widget topW; | |
86 | MenuItem *spec; | |
87 | { | |
88 | return (CreateMenu(topW, spec->submenu, XmHORIZONTAL)); | |
ecb7d146 | 89 | } |
90 | ||
7ee9b49f | 91 | /* |
92 | ** Read the specification and put up a menu to match... | |
7ee9b49f | 93 | */ |
94 | ||
95 | Widget | |
96 | CreateMenu(parent, spec, orientation) | |
97 | Widget parent; | |
98 | MenuItem **spec; | |
99 | int orientation; | |
100 | { | |
101 | Widget menuparent; | |
102 | MenuItem *curmenuitem; | |
103 | Widget childbutton, childmenu; | |
104 | Arg wargs[10]; | |
105 | int n; | |
106 | XmString label; /* !@#$%^ compound string required */ | |
7ee9b49f | 107 | |
108 | label = XmStringCreate( "Complete junk", XmSTRING_DEFAULT_CHARSET); | |
109 | ||
110 | n = 0; | |
7ee9b49f | 111 | XtSetArg(wargs[n], XmNlabelString, label); n++; |
7ee9b49f | 112 | |
892c98b2 | 113 | if (orientation == XmHORIZONTAL) { |
114 | XtSetArg(wargs[n], XmNspacing, 5); n++; | |
115 | menuparent = XmCreateMenuBar( parent, "randommenu", | |
116 | wargs, n); | |
117 | XtManageChild(menuparent); | |
118 | } | |
ecb7d146 | 119 | else |
120 | menuparent = XmCreatePulldownMenu(parent, "randommenu", | |
121 | wargs, n); | |
122 | ||
7ee9b49f | 123 | for ( curmenuitem = (*spec); |
124 | curmenuitem; | |
125 | spec++, curmenuitem = (*spec)) { | |
126 | ||
127 | #ifdef DEBUG | |
128 | printf ("Making entry: %s\n", curmenuitem->label); | |
129 | #endif | |
130 | label = XmStringCreate( curmenuitem->label, | |
131 | XmSTRING_DEFAULT_CHARSET); | |
7ee9b49f | 132 | n = 0; |
133 | XtSetArg(wargs[n], XmNlabelString, label); n++; | |
3583baaa | 134 | if (curmenuitem->accel) { |
135 | XtSetArg(wargs[n], XmNmnemonic, *(curmenuitem->accel)); n++; | |
136 | } | |
7ee9b49f | 137 | |
7ee9b49f | 138 | if (curmenuitem->submenu) { |
139 | #ifdef DEBUG | |
140 | printf ("It has a submenu, which I'm recursing on...\n"); | |
141 | #endif | |
ecb7d146 | 142 | childmenu = CreateMenu( menuparent, |
143 | curmenuitem->submenu, | |
144 | XmVERTICAL); | |
7ee9b49f | 145 | XtSetArg(wargs[n], XmNsubMenuId, childmenu); n++; |
146 | ||
147 | childbutton = XtCreateManagedWidget( "child", | |
148 | xmCascadeButtonWidgetClass, | |
149 | menuparent, wargs, n); | |
7ee9b49f | 150 | |
7ee9b49f | 151 | } |
152 | ||
153 | else { | |
ecb7d146 | 154 | childbutton = XtCreateManagedWidget( "child", |
155 | xmPushButtonGadgetClass, | |
156 | menuparent, wargs, n); | |
157 | ||
7ee9b49f | 158 | XtAddCallback( childbutton, |
159 | XmNactivateCallback, | |
160 | menu_callback, curmenuitem); | |
161 | } | |
162 | } | |
7ee9b49f | 163 | |
ecb7d146 | 164 | return (menuparent); |
7ee9b49f | 165 | } |
166 | ||
7ee9b49f | 167 | /* |
168 | ** Read the specification and put up a form to match... | |
169 | */ | |
170 | ||
171 | Widget | |
172 | CreateForm(parent, spec) | |
173 | Widget parent; | |
174 | EntryForm *spec; | |
175 | { | |
ecb7d146 | 176 | Widget bb; |
7ee9b49f | 177 | Arg wargs[10]; |
ecb7d146 | 178 | int n; |
7ee9b49f | 179 | XmString label; /* compound string required */ |
180 | Dimension height_so_far = 0, width_so_far = 0; | |
181 | Dimension height, width; | |
182 | Widget titleW, instructionW; | |
183 | Position x, y; | |
184 | Widget shellparent; | |
185 | ||
ecb7d146 | 186 | if (spec->formpointer) { |
4fa286c6 | 187 | UpdateForm(spec); |
ecb7d146 | 188 | return(spec->formpointer); |
189 | } | |
7ee9b49f | 190 | |
b2d21e59 | 191 | height_so_far = vpad; |
192 | ||
7ee9b49f | 193 | #define GETSIZE(foo) n = 0; \ |
194 | XtSetArg(wargs[n], XtNwidth, &width); n++; \ | |
195 | XtSetArg(wargs[n], XtNheight, &height); n++; \ | |
196 | XtGetValues (foo, wargs, n); \ | |
197 | ||
198 | #define STORESIZE if (width > width_so_far) width_so_far = width;\ | |
4fa286c6 | 199 | height_so_far += height + vpad; |
7ee9b49f | 200 | |
201 | ||
202 | n = 0; | |
4fa286c6 | 203 | XtSetArg(wargs[n], XmNautoUnmanage, False); n++; |
41a6b53e | 204 | bb = XmCreateBulletinBoardDialog(parent, spec->formname, wargs, n); |
3583baaa | 205 | MapWidgetToForm(bb, spec); |
ecb7d146 | 206 | |
ecb7d146 | 207 | spec->formpointer = bb; |
7ee9b49f | 208 | |
4fa286c6 | 209 | #ifdef FORMTITLES |
7ee9b49f | 210 | label = XmStringCreate(spec->formname, XmSTRING_DEFAULT_CHARSET); |
211 | n = 0; | |
212 | XtSetArg(wargs[n], XmNlabelString, label); n++; | |
213 | XtSetArg(wargs[n], XtNx, 0); n++; | |
214 | XtSetArg(wargs[n], XtNy, 0); n++; | |
215 | titleW = XtCreateManagedWidget( "title", | |
216 | xmLabelWidgetClass, | |
217 | bb, wargs, n); | |
218 | GETSIZE(titleW); | |
219 | STORESIZE; | |
4fa286c6 | 220 | #endif |
7ee9b49f | 221 | |
222 | label = XmStringCreate(spec->instructions, XmSTRING_DEFAULT_CHARSET); | |
223 | n = 0; | |
224 | XtSetArg(wargs[n], XmNlabelString, label); n++; | |
225 | XtSetArg(wargs[n], XtNx, 0); n++; | |
226 | XtSetArg(wargs[n], XtNy, height_so_far); n++; | |
b2d21e59 | 227 | instructionW = XtCreateManagedWidget( "instructions", |
7ee9b49f | 228 | xmLabelWidgetClass, |
229 | bb, wargs, n); | |
230 | GETSIZE(instructionW); | |
231 | STORESIZE; | |
232 | ||
233 | height = height_so_far; | |
234 | width = width_so_far; | |
ecb7d146 | 235 | MakeInputLines(bb, &height, &width, spec); |
7ee9b49f | 236 | STORESIZE; |
237 | ||
238 | height = height_so_far; | |
239 | width = width_so_far; | |
ecb7d146 | 240 | MakeButtons(bb, &height, &width, spec); |
7ee9b49f | 241 | STORESIZE; |
242 | ||
243 | /* | |
244 | ** Center the title of the form | |
245 | */ | |
b2d21e59 | 246 | #ifdef FORMTITLES |
7ee9b49f | 247 | n = 0; |
248 | XtSetArg(wargs[n], XtNwidth, &width); n++; | |
249 | XtGetValues (titleW, wargs, n); | |
250 | ||
251 | x = (width_so_far - width) / 2; | |
252 | ||
253 | n = 0; | |
254 | XtSetArg(wargs[n], XtNx, x); n++; | |
255 | XtSetValues (titleW, wargs, n); | |
4fa286c6 | 256 | #endif |
b2d21e59 | 257 | n = 0; |
258 | XtSetArg(wargs[n], XtNwidth, &width); n++; | |
259 | XtGetValues (instructionW, wargs, n); | |
260 | ||
261 | x = (width_so_far - width) / 2; | |
262 | ||
263 | n = 0; | |
264 | XtSetArg(wargs[n], XtNx, x); n++; | |
265 | XtSetValues (instructionW, wargs, n); | |
266 | ||
7ee9b49f | 267 | return((Widget) bb); |
268 | } | |
269 | ||
270 | /* | |
271 | ** Pheight and pwidth start with the values-to-date of the bboard so far. | |
272 | ** Return your height and width in them when you're done. | |
273 | ** | |
274 | ** Positioning the widgets happens in two phases: | |
275 | ** First, we set their y-positions as we create them. | |
276 | ** After they're created, we go back and adjust the x-positions | |
277 | ** according to the widest left side noted. | |
278 | */ | |
279 | ||
ecb7d146 | 280 | MakeInputLines(parent, pheight, pwidth, spec) |
7ee9b49f | 281 | Widget parent; |
282 | Dimension *pheight; | |
283 | Dimension *pwidth; | |
ecb7d146 | 284 | EntryForm *spec; |
7ee9b49f | 285 | { |
286 | UserPrompt *current; | |
287 | XmString label; /* compound string required */ | |
288 | Arg wargs[10]; | |
289 | int i, n; | |
290 | Widget child; | |
291 | Dimension width, height, maxleftwidth = 0, maxrightwidth = 0; | |
292 | Dimension localy, leftheight = 0, rightheight = 0; | |
ecb7d146 | 293 | UserPrompt **myinputlines = spec->inputlines; |
7ee9b49f | 294 | int foo = 30; |
295 | Widget children[20]; | |
41a6b53e | 296 | static XtTranslations trans = NULL; |
297 | #define newtrans "<FocusOut>: focusOut() MoiraFocusOut()" | |
298 | ||
7ee9b49f | 299 | |
300 | for ( current = (*myinputlines), localy = 0, i = 0; | |
301 | current; | |
302 | myinputlines++, current = (*myinputlines), i++) { | |
303 | ||
304 | ||
305 | #ifdef DEBUG | |
306 | printf ("Making entry %d: %s of type %d\n", | |
307 | i, current->prompt, current->type); | |
308 | #endif | |
309 | /* | |
310 | ** First, make the prompt | |
311 | */ | |
3583baaa | 312 | if (current->type == FT_KEYWORD) { |
313 | char *p; | |
314 | ||
315 | p = index(current->prompt, '|'); | |
316 | if (p) { | |
317 | *p++ = 0; | |
318 | current->keyword_name = p; | |
319 | } | |
320 | } | |
321 | ||
7ee9b49f | 322 | label = XmStringCreate( current->prompt, |
323 | XmSTRING_DEFAULT_CHARSET); | |
324 | n = 0; | |
325 | XtSetArg(wargs[n], XmNlabelString, label); n++; | |
326 | XtSetArg(wargs[n], XtNy, localy + *pheight); n++; | |
327 | child = XtCreateManagedWidget( "prompt", | |
328 | xmLabelWidgetClass, | |
329 | parent, wargs, n); | |
330 | ||
331 | GETSIZE(child); | |
332 | leftheight = height; | |
333 | if (width > maxleftwidth) | |
334 | maxleftwidth = width; | |
335 | ||
3583baaa | 336 | if (current->type == FT_KEYWORD && current->keyword_name) { |
337 | label = XmStringCreate("add new value", | |
338 | XmSTRING_DEFAULT_CHARSET); | |
339 | n = 0; | |
340 | XtSetArg(wargs[n], XmNlabelString, label); n++; | |
341 | XtSetArg(wargs[n], XtNy, localy + *pheight + height); n++; | |
342 | XtSetArg(wargs[n], XtNx, height); n++; | |
343 | child = XtCreateManagedWidget("newvalue", | |
344 | xmPushButtonWidgetClass, | |
345 | parent, wargs, n); | |
346 | XtAddCallback(child, XmNactivateCallback, | |
347 | newvalue, current); | |
348 | ||
349 | GETSIZE(child); | |
350 | leftheight += height; | |
351 | if (width + height > maxleftwidth) | |
352 | maxleftwidth = width + height; | |
353 | } | |
7ee9b49f | 354 | /* |
355 | ** Second, make the input widget | |
356 | */ | |
357 | n = 0; | |
358 | XtSetArg(wargs[n], XtNy, localy + *pheight); n++; | |
ecb7d146 | 359 | XtSetArg(wargs[n], XmNtraversalOn, True); n++; |
7ee9b49f | 360 | XtSetArg(wargs[n], XtNsensitive, |
361 | !(current->insensitive)); n++; | |
362 | switch (current->type) { | |
363 | case FT_STRING: | |
b2d21e59 | 364 | children[i] = XtCreateManagedWidget( "textwidget", |
7ee9b49f | 365 | xmTextWidgetClass, |
366 | parent, wargs, n); | |
b2d21e59 | 367 | XtAddCallback( children[i], XmNvalueChangedCallback, |
ecb7d146 | 368 | string_callback, current); |
41a6b53e | 369 | if (trans == NULL) { |
370 | XtAppAddActions(XtWidgetToApplicationContext(children[i]), | |
371 | myactions, XtNumber(myactions)); | |
372 | ||
373 | trans = XtParseTranslationTable(newtrans); | |
374 | } | |
375 | XtOverrideTranslations(children[i], trans); | |
7ee9b49f | 376 | if (current->returnvalue.stringvalue) { |
377 | XmTextSetString (children[i], current->returnvalue.stringvalue); | |
378 | } | |
379 | GETSIZE (children[i]); | |
380 | rightheight = height; | |
381 | if (width > maxrightwidth) | |
382 | maxrightwidth = width; | |
383 | break; | |
384 | ||
385 | case FT_BOOLEAN: | |
b2d21e59 | 386 | XtSetArg(wargs[n], XmNset, |
387 | current->returnvalue.booleanvalue ? True : False); n++; | |
ecb7d146 | 388 | |
389 | if (current->returnvalue.booleanvalue) | |
390 | label = XmStringCreate( "(True)", XmSTRING_DEFAULT_CHARSET); | |
391 | else | |
392 | label = XmStringCreate( "(False)", XmSTRING_DEFAULT_CHARSET); | |
7ee9b49f | 393 | XtSetArg(wargs[n], XmNlabelString, label); n++; |
394 | ||
395 | children[i] = XtCreateManagedWidget( "ignore this", | |
396 | xmToggleButtonWidgetClass, | |
397 | parent, wargs, n); | |
398 | ||
399 | XtAddCallback( children[i], XmNvalueChangedCallback, | |
ecb7d146 | 400 | boolean_callback, current); |
7ee9b49f | 401 | |
402 | GETSIZE (children[i]); | |
403 | rightheight = height; | |
404 | if (width > maxrightwidth) | |
405 | maxrightwidth = width; | |
406 | break; | |
407 | ||
408 | case FT_KEYWORD: | |
ecb7d146 | 409 | children[i] = |
3583baaa | 410 | MakeRadioField(parent, current, |
411 | &rightheight, spec); | |
ecb7d146 | 412 | XtManageChild(children[i]); |
413 | XtSetValues(children[i], wargs, n); | |
7ee9b49f | 414 | GETSIZE (children[i]); |
415 | if (width > maxrightwidth) | |
416 | maxrightwidth = width; | |
417 | break; | |
418 | ||
419 | default: | |
420 | printf ("Sorry, don't recognize that type\n"); | |
421 | break; | |
422 | } | |
ecb7d146 | 423 | XmAddTabGroup(children[i]); |
3583baaa | 424 | MapWidgetToForm(children[i], spec); |
425 | current->parent = (caddr_t) spec; | |
426 | ||
4fa286c6 | 427 | current->mywidget = children[i]; |
7ee9b49f | 428 | |
4fa286c6 | 429 | localy += MAX(rightheight, leftheight) + vpad; |
7ee9b49f | 430 | } |
431 | ||
432 | /* | |
433 | ** Now slide the input widgets right as far as the widest prompt. | |
434 | */ | |
435 | n = 0; | |
4fa286c6 | 436 | XtSetArg(wargs[n], XtNx, maxleftwidth + hpad); n++; |
7ee9b49f | 437 | for (; i; i--) |
438 | XtSetValues (children[i - 1], wargs, n); | |
439 | ||
4fa286c6 | 440 | *pheight = localy - vpad; |
441 | *pwidth = maxleftwidth + maxrightwidth + hpad; | |
7ee9b49f | 442 | } |
443 | ||
444 | /* | |
445 | ** All the junk about keeping track of the sum of the children's heights | |
446 | ** is because the !#$% RowColumn widget doesn't sum them for us, NOR | |
ecb7d146 | 447 | ** does it accept SetValues on its XtNHeight! Thanks, Motif! |
7ee9b49f | 448 | */ |
449 | ||
ecb7d146 | 450 | Widget |
3583baaa | 451 | MakeRadioField(parent, prompt, pheight, spec) |
7ee9b49f | 452 | Widget parent; |
453 | UserPrompt *prompt; | |
454 | Dimension *pheight; | |
3583baaa | 455 | EntryForm *spec; |
7ee9b49f | 456 | { |
41a6b53e | 457 | Widget radioparent, child = NULL; |
7ee9b49f | 458 | char *current; |
459 | Arg wargs[10]; | |
ecb7d146 | 460 | int count, n; |
461 | XmString label; /* accursed compound string required */ | |
7ee9b49f | 462 | Dimension height, width; |
41a6b53e | 463 | char **keywords, *null[2]; |
7ee9b49f | 464 | |
4fa286c6 | 465 | if (!prompt->keywords) { |
7ee9b49f | 466 | fprintf (stderr, "Warning: No list of keywords for widget\n"); |
41a6b53e | 467 | prompt->keywords = null; |
468 | null[0] = NULL; | |
7ee9b49f | 469 | } |
ecb7d146 | 470 | for ( count = 0, keywords = prompt->keywords; |
471 | *keywords; | |
472 | keywords++, count++); | |
473 | ||
474 | /* | |
475 | ** Although the XmNnumColumns resource is documented as actually | |
476 | ** representing the number of _rows_ when XmNorientation is set to XmVERTICAL, | |
477 | ** it doesn't. So I need to count the items myself and manually set the | |
478 | ** number of columns to get a maximum of five rows. There's no XmNnumRows | |
479 | ** resource. Thanks, Motif! | |
480 | */ | |
481 | ||
482 | n = 0; | |
892c98b2 | 483 | XtSetArg(wargs[n], XmNspacing, 0); n++; |
484 | ||
ecb7d146 | 485 | if (count > 5) { |
b2d21e59 | 486 | XtSetArg(wargs[n], XmNnumColumns, 1 + (count-1) / 5); n++; |
ecb7d146 | 487 | XtSetArg(wargs[n], XmNorientation, XmVERTICAL); n++; |
488 | XtSetArg(wargs[n], XmNpacking, XmPACK_COLUMN); n++; | |
489 | } | |
ecb7d146 | 490 | radioparent = XmCreateRadioBox(parent, "radio", wargs, n); |
491 | ||
492 | keywords = prompt->keywords; | |
7ee9b49f | 493 | for (current=(*keywords); current; keywords++, current=(*keywords)) { |
494 | n = 0; | |
495 | label = XmStringCreate(current, XmSTRING_DEFAULT_CHARSET); | |
496 | XtSetArg(wargs[n], XmNlabelString, label); n++; | |
b2d21e59 | 497 | if ((prompt->returnvalue.stringvalue) && |
498 | (!strcmp (current, prompt->returnvalue.stringvalue))) { | |
7ee9b49f | 499 | XtSetArg(wargs[n], XmNset, True); n++; |
500 | } | |
501 | else { | |
502 | XtSetArg(wargs[n], XmNset, False); n++; | |
503 | } | |
504 | child = XtCreateManagedWidget( current, | |
892c98b2 | 505 | xmToggleButtonWidgetClass, |
ecb7d146 | 506 | radioparent, wargs, n); |
3583baaa | 507 | MapWidgetToForm(child, spec); |
7ee9b49f | 508 | |
509 | XtAddCallback( child, XmNvalueChangedCallback, | |
510 | radio_callback, prompt); | |
511 | ||
7ee9b49f | 512 | } |
513 | /* | |
ecb7d146 | 514 | ** Assume all child widgets are the same height. Increase height by |
515 | ** five times this, or the actual number of children, whichever is lesser. | |
516 | */ | |
517 | ||
41a6b53e | 518 | if (child) { |
519 | GETSIZE (child); | |
520 | } else | |
521 | height = 10; | |
b2d21e59 | 522 | *pheight = (height * MIN(5, count)) + vpad; |
ecb7d146 | 523 | |
ecb7d146 | 524 | return(radioparent); |
7ee9b49f | 525 | } |
526 | ||
41a6b53e | 527 | |
528 | /* This is called when the list of keywords changes. The old radio box | |
529 | * will be destroyed and a new one created. | |
530 | */ | |
531 | ||
532 | RemakeRadioField(form, field) | |
533 | EntryForm *form; | |
534 | int field; | |
535 | { | |
536 | Dimension x, y, parent_y, oldheight, newheight; | |
537 | Arg wargs[4]; | |
538 | Widget w; | |
539 | XmBulletinBoardWidget bb; | |
540 | XmRowColumnWidget rc; | |
541 | static XtTranslations trans = NULL; | |
542 | extern char form_override_table[]; | |
543 | int i; | |
544 | ||
545 | XtSetArg(wargs[0], XtNx, &x); | |
546 | XtSetArg(wargs[1], XtNy, &y); | |
547 | XtSetArg(wargs[2], XtNheight, &oldheight); | |
548 | XtGetValues(form->inputlines[field]->mywidget, wargs, 3); | |
549 | XtUnmanageChild(form->inputlines[field]->mywidget); | |
550 | form->inputlines[field]->mywidget = w = | |
551 | MakeRadioField(form->formpointer, form->inputlines[field], | |
552 | &newheight, form); | |
553 | XtSetArg(wargs[0], XtNx, x); | |
554 | XtSetArg(wargs[1], XtNy, y); | |
555 | XtSetValues(w, wargs, 2); | |
556 | MapWidgetToForm(w, form); | |
557 | XmAddTabGroup(w); | |
558 | if (newheight > oldheight) { | |
559 | bb = (XmBulletinBoardWidget) form->formpointer; | |
560 | parent_y = y; | |
561 | for (i = 0; i < bb->composite.num_children; i++) { | |
562 | XtSetArg(wargs[0], XtNy, &y); | |
563 | XtGetValues(bb->composite.children[i], wargs, 1); | |
564 | if (y > parent_y) { | |
565 | y = (y + newheight) - oldheight; | |
566 | XtSetArg(wargs[0], XtNy, y); | |
567 | XtSetValues(bb->composite.children[i], wargs, 1); | |
568 | } | |
569 | } | |
570 | } | |
571 | ||
572 | if (trans == NULL) | |
573 | trans = XtParseTranslationTable(form_override_table); | |
574 | XtOverrideTranslations(w, trans); | |
575 | rc = (XmRowColumnWidget) w; | |
576 | for (i = 0; i < rc->composite.num_children; i++) | |
577 | XtOverrideTranslations(rc->composite.children[i], trans); | |
578 | ||
579 | XtManageChild(w); | |
580 | } | |
581 | ||
582 | ||
ecb7d146 | 583 | MakeButtons(parent, pheight, pwidth, spec) |
7ee9b49f | 584 | Widget parent; |
585 | Dimension *pheight; | |
586 | Dimension *pwidth; | |
ecb7d146 | 587 | EntryForm *spec; |
7ee9b49f | 588 | { |
589 | BottomButton *current; | |
590 | XmString label; /* compound string required */ | |
591 | Arg wargs[10]; | |
592 | int i, n; | |
593 | Dimension newwidth, width = 25; | |
594 | Widget newbutton; | |
ecb7d146 | 595 | BottomButton **buttons = spec->buttons; |
7ee9b49f | 596 | |
4fa286c6 | 597 | *pheight += vpad; |
598 | ||
7ee9b49f | 599 | n = 0; |
600 | XtSetArg(wargs[n], XtNy, *pheight); n++; | |
601 | XtSetArg(wargs[n], XtNx, 0); n++; | |
602 | XtSetArg(wargs[n], XtNwidth, *pwidth); n++; | |
603 | XtCreateManagedWidget( "separator", | |
604 | xmSeparatorWidgetClass, | |
605 | parent, wargs, n); | |
4fa286c6 | 606 | *pheight += vpad; |
7ee9b49f | 607 | |
608 | for ( current=(*buttons); | |
609 | current; | |
610 | buttons++, current=(*buttons)) { | |
611 | ||
612 | #ifdef DEBUG | |
613 | printf ("Making a button labeled %s\n", current->label); | |
614 | #endif | |
615 | label = XmStringCreate( current->label, | |
616 | XmSTRING_DEFAULT_CHARSET); | |
617 | n = 0; | |
618 | XtSetArg(wargs[n], XtNy, (*pheight)); n++; | |
619 | XtSetArg(wargs[n], XtNx, width); n++; | |
620 | XtSetArg(wargs[n], XmNlabelString, label); n++; | |
621 | ||
622 | newbutton = XtCreateManagedWidget( current->label, | |
623 | xmPushButtonWidgetClass, | |
624 | parent, wargs, n); | |
625 | ||
626 | XtAddCallback( newbutton, XmNactivateCallback, | |
ecb7d146 | 627 | current->returnfunction, spec); |
7ee9b49f | 628 | n = 0; |
629 | XtSetArg(wargs[n], XtNwidth, &newwidth); n++; | |
630 | XtGetValues (newbutton, wargs, n); | |
631 | ||
4fa286c6 | 632 | width += (newwidth + hpad); |
7ee9b49f | 633 | } |
634 | ||
635 | (*pheight) += 100; | |
636 | } | |
637 | ||
ecb7d146 | 638 | void |
7ee9b49f | 639 | radio_callback(w, client_data, call_data) |
640 | Widget w; | |
641 | XmAnyCallbackStruct *client_data; | |
642 | XmAnyCallbackStruct *call_data; | |
643 | { | |
644 | Arg wargs[10]; | |
ecb7d146 | 645 | int n; |
646 | Boolean is_set; | |
7ee9b49f | 647 | |
648 | UserPrompt *prompt = (UserPrompt *) client_data; | |
649 | ||
7ee9b49f | 650 | n = 0; |
ecb7d146 | 651 | XtSetArg(wargs[n], XmNset, &is_set); n++; |
7ee9b49f | 652 | XtGetValues (w, wargs, n); |
653 | ||
ecb7d146 | 654 | if (!is_set) |
655 | return; | |
7ee9b49f | 656 | |
657 | /* | |
ecb7d146 | 658 | ** Since Motif insists on using !@#$% Compound Strings as the text for |
659 | ** its label widgets, but doesn't provide a way of getting a char* back | |
660 | ** from a !@#$% Compound String, I can't retrieve the label of the button | |
661 | ** that was hit. | |
662 | ** | |
663 | ** Fortunately, I was smart enough to use the button label as the name | |
664 | ** of the widget, and I can extract it via XtName(). Thanks, Motif! | |
665 | */ | |
b2d21e59 | 666 | if (prompt->returnvalue.stringvalue && |
667 | (strcmp(prompt->returnvalue.stringvalue, XtName(w)))) { | |
892c98b2 | 668 | strcpy(prompt->returnvalue.stringvalue, XtName(w)); |
3583baaa | 669 | if (prompt->valuechanged) |
670 | (*prompt->valuechanged)(WidgetToForm(w), prompt); | |
892c98b2 | 671 | } |
7ee9b49f | 672 | |
ecb7d146 | 673 | } |
674 | ||
675 | void | |
676 | boolean_callback(w, client_data, call_data) | |
677 | Widget w; | |
678 | XmAnyCallbackStruct *client_data; | |
679 | XmAnyCallbackStruct *call_data; | |
680 | { | |
681 | Arg wargs[10]; | |
682 | int n; | |
683 | Boolean is_set; | |
684 | UserPrompt *current = (UserPrompt *)client_data; | |
685 | XmString label; | |
686 | ||
687 | n = 0; | |
688 | XtSetArg(wargs[n], XmNset, &is_set); n++; | |
689 | XtGetValues (w, wargs, n); | |
690 | ||
691 | current->returnvalue.booleanvalue = is_set; | |
7ee9b49f | 692 | |
ecb7d146 | 693 | if (is_set) |
694 | label = XmStringCreate( "(True)", XmSTRING_DEFAULT_CHARSET); | |
695 | else | |
696 | label = XmStringCreate( "(False)", XmSTRING_DEFAULT_CHARSET); | |
697 | n = 0; | |
698 | XtSetArg(wargs[n], XmNlabelString, label); n++; | |
699 | XtSetValues (w, wargs, n); | |
700 | ||
3583baaa | 701 | if (current->valuechanged) |
702 | (*current->valuechanged)(WidgetToForm(w), current); | |
703 | ||
ecb7d146 | 704 | #if DEBUG |
705 | printf ("boolean_callback: button %x is %s\n", | |
706 | w, (is_set ? "True" : "False")); | |
707 | #endif | |
7ee9b49f | 708 | } |
709 | ||
710 | void | |
711 | menu_callback(w, client_data, call_data) | |
712 | Widget w; | |
713 | XmAnyCallbackStruct *client_data; | |
714 | XmAnyCallbackStruct *call_data; | |
715 | { | |
716 | MenuItem *itemhit = (MenuItem *) client_data; | |
717 | ||
b2d21e59 | 718 | /* printf ("menu_callback: item '%s', op %d and string '%s'\n", |
719 | itemhit->label, | |
720 | itemhit->operation, | |
721 | itemhit->form); | |
722 | XtManageChild(entryformwidget); | |
723 | */ | |
7ee9b49f | 724 | MoiraMenuRequest(itemhit); |
ecb7d146 | 725 | } |
7ee9b49f | 726 | |
892c98b2 | 727 | |
ecb7d146 | 728 | void |
729 | string_callback(w, client_data, call_data) | |
730 | Widget w; | |
731 | XmAnyCallbackStruct *client_data; | |
732 | XmAnyCallbackStruct *call_data; | |
733 | { | |
734 | UserPrompt *current = (UserPrompt *)client_data; | |
735 | char *newvalue; | |
736 | ||
737 | newvalue = XmTextGetString(w); | |
738 | ||
892c98b2 | 739 | if (strcmp(current->returnvalue.stringvalue, newvalue)) { |
b2d21e59 | 740 | /* printf ("Replacing old value of selection, '%s', with '%s'\n", |
892c98b2 | 741 | current->returnvalue.stringvalue, |
742 | newvalue); | |
41a6b53e | 743 | strcpy(current->returnvalue.stringvalue, newvalue); |
3583baaa | 744 | if (current->valuechanged) |
745 | (*current->valuechanged)(WidgetToForm(w), current); | |
41a6b53e | 746 | */ } |
ecb7d146 | 747 | XtFree(newvalue); |
7ee9b49f | 748 | } |
3583baaa | 749 | |
750 | ||
41a6b53e | 751 | void MoiraFocusOut(w, event, p, n) |
752 | Widget w; | |
753 | XEvent *event; | |
754 | String *p; | |
755 | Cardinal *n; | |
756 | { | |
757 | char *newvalue; | |
758 | UserPrompt *current = NULL; | |
759 | EntryForm *f; | |
760 | XmTextRec *tr = (XmTextRec *)w; | |
761 | int i; | |
762 | ||
763 | if (tr->core.self != w || tr->core.widget_class != xmTextWidgetClass) | |
764 | return; | |
765 | newvalue = XmTextGetString(w); | |
766 | f = WidgetToForm(w); | |
767 | for (i = 0; f->inputlines[i]; i++) | |
768 | if (f->inputlines[i]->mywidget == w) | |
769 | current = f->inputlines[i]; | |
770 | if (current == NULL) { | |
771 | fprintf(stderr, "Couldn't find prompt structure!\n"); | |
772 | return; | |
773 | } | |
774 | ||
775 | if (strcmp(current->returnvalue.stringvalue, newvalue)) { | |
776 | strcpy(current->returnvalue.stringvalue, newvalue); | |
777 | if (current->valuechanged) | |
778 | (*current->valuechanged)(f, current); | |
779 | } | |
780 | XtFree(newvalue); | |
781 | } | |
782 | ||
783 | ||
3583baaa | 784 | void |
785 | newvalue(w, client_data, call_data) | |
786 | Widget w; | |
787 | XmAnyCallbackStruct *client_data; | |
788 | XmAnyCallbackStruct *call_data; | |
789 | { | |
790 | UserPrompt *current = (UserPrompt *)client_data; | |
791 | EntryForm *form, *f; | |
792 | int i; | |
793 | static MenuItem *mi = NULL; | |
794 | ||
795 | if (current->keyword_name == NULL) { | |
796 | PopupErrorMessage("Sorry, that keyword cannot be changed.", NULL); | |
797 | return; | |
798 | } | |
799 | form = (EntryForm *)current->parent; | |
800 | for (i = 0; form->inputlines[i]; i++) | |
801 | if (form->inputlines[i] == current) | |
802 | break; | |
803 | f = GetAndClearForm("add_new_value"); | |
804 | if (mi == NULL) { | |
805 | mi = (MenuItem *)malloc(sizeof(*mi)); | |
806 | mi->operation = MM_NEW_VALUE; | |
807 | mi->query = "add_alias"; | |
808 | mi->argc = 3; | |
809 | } | |
810 | mi->form = form->formname; | |
811 | mi->accel = (char *) i; | |
812 | f->menu = mi; | |
813 | f->extrastuff = current->keyword_name; | |
814 | DisplayForm(f); | |
815 | } | |
816 | ||
817 | ||
818 | /* WARNING: This routine uses Motif internal undocumented routines. | |
819 | * It was the only way to get carriage return to Do The Right Thing. | |
820 | * If you are in a single-item tab group, this routine will call | |
821 | * MoiraFormComplete() (same as pressing OK on the bottom of the form). | |
822 | * otherwise, it advances the focus the same as pressing TAB. | |
823 | */ | |
824 | ||
825 | void EnterPressed(w, event, argv, count) | |
826 | Widget w; | |
827 | XEvent *event; | |
828 | char **argv; | |
829 | Cardinal *count; | |
830 | { | |
831 | Widget next; | |
832 | EntryForm *form; | |
833 | ||
834 | next = _XmFindNextTabGroup(w); | |
835 | if (next == w) { | |
41a6b53e | 836 | MoiraFocusOut(w, event, argv, count); |
3583baaa | 837 | form = WidgetToForm(w); |
838 | MoiraFormComplete(NULL, form); | |
839 | } else { | |
840 | _XmMgrTraversal(w, XmTRAVERSE_NEXT_TAB_GROUP); | |
841 | } | |
842 | } | |
843 | ||
844 | ||
845 | void CancelForm(w, event, argv, count) | |
846 | Widget w; | |
847 | XEvent *event; | |
848 | char **argv; | |
849 | Cardinal *count; | |
850 | { | |
851 | EntryForm *form; | |
852 | ||
853 | form = WidgetToForm(w); | |
854 | if (form) | |
855 | XtUnmanageChild(form->formpointer); | |
856 | } | |
857 | ||
858 | ||
859 | void ExecuteForm(w, event, argv, count) | |
860 | Widget w; | |
861 | XEvent *event; | |
862 | char **argv; | |
863 | Cardinal *count; | |
864 | { | |
865 | EntryForm *form; | |
866 | ||
867 | form = WidgetToForm(w); | |
41a6b53e | 868 | if (form) { |
869 | MoiraFocusOut(w, event, argv, count); | |
870 | MoiraFormComplete(NULL, form); | |
871 | } | |
3583baaa | 872 | } |
873 | ||
874 | ||
875 | void DoHelp(w, event, argv, count) | |
876 | Widget w; | |
877 | XEvent *event; | |
878 | char **argv; | |
879 | Cardinal *count; | |
880 | { | |
881 | EntryForm *form; | |
882 | ||
883 | form = WidgetToForm(w); | |
884 | if (form) | |
885 | help(form->formname); | |
886 | } | |
887 | ||
888 | ||
889 | extern struct hash *create_hash(); | |
890 | static struct hash *WFmap = NULL; | |
891 | ||
892 | MapWidgetToForm(w, f) | |
893 | Widget *w; | |
894 | EntryForm *f; | |
895 | { | |
896 | if (WFmap == NULL) { | |
897 | WFmap = create_hash(101); | |
898 | } | |
899 | hash_store(WFmap, w, f); | |
900 | } | |
901 | ||
902 | EntryForm *WidgetToForm(w) | |
903 | Widget *w; | |
904 | { | |
905 | return((EntryForm *) hash_lookup(WFmap, w)); | |
906 | } |