]> andersk Git - moira.git/blame - clients/mmoira/formup.c
better sanity checking in MoiraFocusOut()
[moira.git] / clients / mmoira / formup.c
CommitLineData
41a6b53e 1/* $Header$ */
2
7ee9b49f 3#include <stdio.h>
5bcb5e58 4#include <strings.h>
7ee9b49f 5#include <X11/StringDefs.h>
6#include <X11/IntrinsicP.h>
7#include <X11/Shell.h>
8#include <X11/Core.h>
9#include <X11/CoreP.h>
b80b4770 10#include <X11/CompositeP.h>
7ee9b49f 11#include <Xm/Xm.h>
12#include <Xm/BulletinB.h>
13#include <Xm/Label.h>
14#include <Xm/Text.h>
41a6b53e 15#include <Xm/TextP.h>
7ee9b49f 16#include <Xm/PushB.h>
17#include <Xm/PushBG.h>
18#include <Xm/CascadeB.h>
19#include <Xm/ToggleB.h>
20#include <Xm/ToggleBG.h>
21#include <Xm/RowColumn.h>
22#include <Xm/Separator.h>
3583baaa 23#include <Xm/Traversal.h>
7ee9b49f 24#include "mmoira.h"
25
892c98b2 26static 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 35int hpad = 10;
36int vpad = 5;
7ee9b49f 37
7ee9b49f 38void manage_widget();
39Widget CreateForm();
40Widget CreateMenu();
41Widget BuildMenuTree();
ecb7d146 42Widget MakeRadioField();
892c98b2 43int button_callback();
ecb7d146 44void radio_callback();
ecb7d146 45void string_callback();
892c98b2 46void boolean_callback();
7ee9b49f 47void menu_callback();
3583baaa 48void newvalue();
41a6b53e 49void MoiraFocusOut();
3583baaa 50EntryForm *WidgetToForm();
7ee9b49f 51
4fa286c6 52extern void UpdateForm();
892c98b2 53extern int PopupErrorMessage();
54extern void PopupHelpWindow();
55extern int AppendToLog();
892c98b2 56extern void MakeWatchCursor();
57extern void MakeNormalCursor();
58extern Widget SetupLogWidget();
7ee9b49f 59
41a6b53e 60static XtActionsRec myactions[] = {
61 { "MoiraFocusOut", MoiraFocusOut },
62};
63
892c98b2 64
65void
66manage_widget(w, widget, call_data)
67Widget w, widget;
68XmAnyCallbackStruct *call_data;
ecb7d146 69{
892c98b2 70 XtManageChild(widget);
71}
ecb7d146 72
892c98b2 73int
b2d21e59 74button_callback(w, client_data, call_data)
75Widget w;
76EntryForm *client_data;
892c98b2 77XmAnyCallbackStruct *call_data;
78{
b2d21e59 79 XtUnmanageChild(client_data->formpointer);
892c98b2 80}
81
82
83Widget
84BuildMenuTree(topW, spec)
85Widget topW;
86MenuItem *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
95Widget
96CreateMenu(parent, spec, orientation)
97Widget parent;
98MenuItem **spec;
99int 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
171Widget
172CreateForm(parent, spec)
173Widget parent;
174EntryForm *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 280MakeInputLines(parent, pheight, pwidth, spec)
7ee9b49f 281Widget parent;
282Dimension *pheight;
283Dimension *pwidth;
ecb7d146 284EntryForm *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;
7ee9b49f 297
298 for ( current = (*myinputlines), localy = 0, i = 0;
299 current;
300 myinputlines++, current = (*myinputlines), i++) {
301
302
303#ifdef DEBUG
304 printf ("Making entry %d: %s of type %d\n",
305 i, current->prompt, current->type);
306#endif
307/*
308** First, make the prompt
309*/
3583baaa 310 if (current->type == FT_KEYWORD) {
311 char *p;
312
313 p = index(current->prompt, '|');
314 if (p) {
315 *p++ = 0;
316 current->keyword_name = p;
317 }
318 }
319
7ee9b49f 320 label = XmStringCreate( current->prompt,
321 XmSTRING_DEFAULT_CHARSET);
322 n = 0;
323 XtSetArg(wargs[n], XmNlabelString, label); n++;
324 XtSetArg(wargs[n], XtNy, localy + *pheight); n++;
325 child = XtCreateManagedWidget( "prompt",
326 xmLabelWidgetClass,
327 parent, wargs, n);
328
329 GETSIZE(child);
330 leftheight = height;
331 if (width > maxleftwidth)
332 maxleftwidth = width;
333
3583baaa 334 if (current->type == FT_KEYWORD && current->keyword_name) {
335 label = XmStringCreate("add new value",
336 XmSTRING_DEFAULT_CHARSET);
337 n = 0;
338 XtSetArg(wargs[n], XmNlabelString, label); n++;
339 XtSetArg(wargs[n], XtNy, localy + *pheight + height); n++;
340 XtSetArg(wargs[n], XtNx, height); n++;
341 child = XtCreateManagedWidget("newvalue",
342 xmPushButtonWidgetClass,
343 parent, wargs, n);
344 XtAddCallback(child, XmNactivateCallback,
345 newvalue, current);
346
347 GETSIZE(child);
348 leftheight += height;
349 if (width + height > maxleftwidth)
350 maxleftwidth = width + height;
351 }
7ee9b49f 352/*
353** Second, make the input widget
354*/
355 n = 0;
356 XtSetArg(wargs[n], XtNy, localy + *pheight); n++;
ecb7d146 357 XtSetArg(wargs[n], XmNtraversalOn, True); n++;
7ee9b49f 358 XtSetArg(wargs[n], XtNsensitive,
359 !(current->insensitive)); n++;
360 switch (current->type) {
361 case FT_STRING:
b2d21e59 362 children[i] = XtCreateManagedWidget( "textwidget",
7ee9b49f 363 xmTextWidgetClass,
364 parent, wargs, n);
b2d21e59 365 XtAddCallback( children[i], XmNvalueChangedCallback,
ecb7d146 366 string_callback, current);
41a6b53e 367 if (trans == NULL) {
368 XtAppAddActions(XtWidgetToApplicationContext(children[i]),
369 myactions, XtNumber(myactions));
370
111b5809 371 trans = XtParseTranslationTable(resources.text_trans);
41a6b53e 372 }
373 XtOverrideTranslations(children[i], trans);
7ee9b49f 374 if (current->returnvalue.stringvalue) {
375 XmTextSetString (children[i], current->returnvalue.stringvalue);
376 }
377 GETSIZE (children[i]);
378 rightheight = height;
379 if (width > maxrightwidth)
380 maxrightwidth = width;
381 break;
382
383 case FT_BOOLEAN:
b2d21e59 384 XtSetArg(wargs[n], XmNset,
385 current->returnvalue.booleanvalue ? True : False); n++;
ecb7d146 386
387 if (current->returnvalue.booleanvalue)
388 label = XmStringCreate( "(True)", XmSTRING_DEFAULT_CHARSET);
389 else
390 label = XmStringCreate( "(False)", XmSTRING_DEFAULT_CHARSET);
7ee9b49f 391 XtSetArg(wargs[n], XmNlabelString, label); n++;
392
393 children[i] = XtCreateManagedWidget( "ignore this",
394 xmToggleButtonWidgetClass,
395 parent, wargs, n);
396
397 XtAddCallback( children[i], XmNvalueChangedCallback,
ecb7d146 398 boolean_callback, current);
7ee9b49f 399
400 GETSIZE (children[i]);
401 rightheight = height;
402 if (width > maxrightwidth)
403 maxrightwidth = width;
404 break;
405
406 case FT_KEYWORD:
ecb7d146 407 children[i] =
3583baaa 408 MakeRadioField(parent, current,
409 &rightheight, spec);
ecb7d146 410 XtManageChild(children[i]);
411 XtSetValues(children[i], wargs, n);
7ee9b49f 412 GETSIZE (children[i]);
413 if (width > maxrightwidth)
414 maxrightwidth = width;
415 break;
416
417 default:
418 printf ("Sorry, don't recognize that type\n");
419 break;
420 }
ecb7d146 421 XmAddTabGroup(children[i]);
3583baaa 422 MapWidgetToForm(children[i], spec);
423 current->parent = (caddr_t) spec;
424
4fa286c6 425 current->mywidget = children[i];
7ee9b49f 426
4fa286c6 427 localy += MAX(rightheight, leftheight) + vpad;
7ee9b49f 428 }
429
430/*
431** Now slide the input widgets right as far as the widest prompt.
432*/
433 n = 0;
4fa286c6 434 XtSetArg(wargs[n], XtNx, maxleftwidth + hpad); n++;
7ee9b49f 435 for (; i; i--)
436 XtSetValues (children[i - 1], wargs, n);
437
4fa286c6 438 *pheight = localy - vpad;
439 *pwidth = maxleftwidth + maxrightwidth + hpad;
7ee9b49f 440}
441
442/*
443** All the junk about keeping track of the sum of the children's heights
444** is because the !#$% RowColumn widget doesn't sum them for us, NOR
ecb7d146 445** does it accept SetValues on its XtNHeight! Thanks, Motif!
7ee9b49f 446*/
447
ecb7d146 448Widget
3583baaa 449MakeRadioField(parent, prompt, pheight, spec)
7ee9b49f 450Widget parent;
451UserPrompt *prompt;
452Dimension *pheight;
3583baaa 453EntryForm *spec;
7ee9b49f 454{
41a6b53e 455 Widget radioparent, child = NULL;
7ee9b49f 456 char *current;
457 Arg wargs[10];
ecb7d146 458 int count, n;
459 XmString label; /* accursed compound string required */
7ee9b49f 460 Dimension height, width;
41a6b53e 461 char **keywords, *null[2];
7ee9b49f 462
4fa286c6 463 if (!prompt->keywords) {
7ee9b49f 464 fprintf (stderr, "Warning: No list of keywords for widget\n");
41a6b53e 465 prompt->keywords = null;
466 null[0] = NULL;
7ee9b49f 467 }
ecb7d146 468 for ( count = 0, keywords = prompt->keywords;
469 *keywords;
470 keywords++, count++);
471
472/*
473** Although the XmNnumColumns resource is documented as actually
474** representing the number of _rows_ when XmNorientation is set to XmVERTICAL,
475** it doesn't. So I need to count the items myself and manually set the
476** number of columns to get a maximum of five rows. There's no XmNnumRows
477** resource. Thanks, Motif!
478*/
479
480 n = 0;
892c98b2 481 XtSetArg(wargs[n], XmNspacing, 0); n++;
482
ecb7d146 483 if (count > 5) {
b2d21e59 484 XtSetArg(wargs[n], XmNnumColumns, 1 + (count-1) / 5); n++;
ecb7d146 485 XtSetArg(wargs[n], XmNorientation, XmVERTICAL); n++;
486 XtSetArg(wargs[n], XmNpacking, XmPACK_COLUMN); n++;
487 }
ecb7d146 488 radioparent = XmCreateRadioBox(parent, "radio", wargs, n);
489
490 keywords = prompt->keywords;
7ee9b49f 491 for (current=(*keywords); current; keywords++, current=(*keywords)) {
492 n = 0;
493 label = XmStringCreate(current, XmSTRING_DEFAULT_CHARSET);
494 XtSetArg(wargs[n], XmNlabelString, label); n++;
b2d21e59 495 if ((prompt->returnvalue.stringvalue) &&
496 (!strcmp (current, prompt->returnvalue.stringvalue))) {
7ee9b49f 497 XtSetArg(wargs[n], XmNset, True); n++;
498 }
499 else {
500 XtSetArg(wargs[n], XmNset, False); n++;
501 }
502 child = XtCreateManagedWidget( current,
892c98b2 503 xmToggleButtonWidgetClass,
ecb7d146 504 radioparent, wargs, n);
3583baaa 505 MapWidgetToForm(child, spec);
7ee9b49f 506
507 XtAddCallback( child, XmNvalueChangedCallback,
508 radio_callback, prompt);
509
7ee9b49f 510 }
511/*
ecb7d146 512** Assume all child widgets are the same height. Increase height by
513** five times this, or the actual number of children, whichever is lesser.
514*/
515
41a6b53e 516 if (child) {
517 GETSIZE (child);
518 } else
519 height = 10;
b2d21e59 520 *pheight = (height * MIN(5, count)) + vpad;
ecb7d146 521
ecb7d146 522 return(radioparent);
7ee9b49f 523}
524
41a6b53e 525
526/* This is called when the list of keywords changes. The old radio box
527 * will be destroyed and a new one created.
528 */
529
530RemakeRadioField(form, field)
531EntryForm *form;
532int field;
533{
534 Dimension x, y, parent_y, oldheight, newheight;
535 Arg wargs[4];
536 Widget w;
41a6b53e 537 static XtTranslations trans = NULL;
538 extern char form_override_table[];
539 int i;
540
541 XtSetArg(wargs[0], XtNx, &x);
542 XtSetArg(wargs[1], XtNy, &y);
543 XtSetArg(wargs[2], XtNheight, &oldheight);
544 XtGetValues(form->inputlines[field]->mywidget, wargs, 3);
545 XtUnmanageChild(form->inputlines[field]->mywidget);
546 form->inputlines[field]->mywidget = w =
547 MakeRadioField(form->formpointer, form->inputlines[field],
548 &newheight, form);
549 XtSetArg(wargs[0], XtNx, x);
550 XtSetArg(wargs[1], XtNy, y);
551 XtSetValues(w, wargs, 2);
552 MapWidgetToForm(w, form);
553 XmAddTabGroup(w);
554 if (newheight > oldheight) {
41a6b53e 555 parent_y = y;
b80b4770 556 for (i = 0; i < NumChildren(form->formpointer); i++) {
41a6b53e 557 XtSetArg(wargs[0], XtNy, &y);
b80b4770 558 XtGetValues(NthChild(form->formpointer, i), wargs, 1);
41a6b53e 559 if (y > parent_y) {
560 y = (y + newheight) - oldheight;
561 XtSetArg(wargs[0], XtNy, y);
b80b4770 562 XtSetValues(NthChild(form->formpointer, i), wargs, 1);
41a6b53e 563 }
564 }
565 }
566
567 if (trans == NULL)
111b5809 568 trans = XtParseTranslationTable(resources.form_trans);
41a6b53e 569 XtOverrideTranslations(w, trans);
b80b4770 570 for (i = 0; i < NumChildren(w); i++)
571 XtOverrideTranslations(NthChild(w, i), trans);
41a6b53e 572
573 XtManageChild(w);
574}
575
576
ecb7d146 577MakeButtons(parent, pheight, pwidth, spec)
7ee9b49f 578Widget parent;
579Dimension *pheight;
580Dimension *pwidth;
ecb7d146 581EntryForm *spec;
7ee9b49f 582{
583 BottomButton *current;
584 XmString label; /* compound string required */
585 Arg wargs[10];
586 int i, n;
587 Dimension newwidth, width = 25;
588 Widget newbutton;
ecb7d146 589 BottomButton **buttons = spec->buttons;
7ee9b49f 590
4fa286c6 591 *pheight += vpad;
592
7ee9b49f 593 n = 0;
594 XtSetArg(wargs[n], XtNy, *pheight); n++;
595 XtSetArg(wargs[n], XtNx, 0); n++;
596 XtSetArg(wargs[n], XtNwidth, *pwidth); n++;
597 XtCreateManagedWidget( "separator",
598 xmSeparatorWidgetClass,
599 parent, wargs, n);
4fa286c6 600 *pheight += vpad;
7ee9b49f 601
602 for ( current=(*buttons);
603 current;
604 buttons++, current=(*buttons)) {
605
606#ifdef DEBUG
607 printf ("Making a button labeled %s\n", current->label);
608#endif
609 label = XmStringCreate( current->label,
610 XmSTRING_DEFAULT_CHARSET);
611 n = 0;
612 XtSetArg(wargs[n], XtNy, (*pheight)); n++;
613 XtSetArg(wargs[n], XtNx, width); n++;
614 XtSetArg(wargs[n], XmNlabelString, label); n++;
615
616 newbutton = XtCreateManagedWidget( current->label,
617 xmPushButtonWidgetClass,
618 parent, wargs, n);
619
5bcb5e58 620 XtAddCallback(newbutton, XmNactivateCallback,
621 (XtCallbackProc) current->returnfunction,
622 spec);
7ee9b49f 623 n = 0;
624 XtSetArg(wargs[n], XtNwidth, &newwidth); n++;
625 XtGetValues (newbutton, wargs, n);
626
4fa286c6 627 width += (newwidth + hpad);
7ee9b49f 628 }
629
630 (*pheight) += 100;
631}
632
ecb7d146 633void
7ee9b49f 634radio_callback(w, client_data, call_data)
635Widget w;
636XmAnyCallbackStruct *client_data;
637XmAnyCallbackStruct *call_data;
638{
639 Arg wargs[10];
ecb7d146 640 int n;
641 Boolean is_set;
7ee9b49f 642
643 UserPrompt *prompt = (UserPrompt *) client_data;
644
7ee9b49f 645 n = 0;
ecb7d146 646 XtSetArg(wargs[n], XmNset, &is_set); n++;
7ee9b49f 647 XtGetValues (w, wargs, n);
648
ecb7d146 649 if (!is_set)
650 return;
7ee9b49f 651
652/*
ecb7d146 653** Since Motif insists on using !@#$% Compound Strings as the text for
654** its label widgets, but doesn't provide a way of getting a char* back
655** from a !@#$% Compound String, I can't retrieve the label of the button
656** that was hit.
657**
658** Fortunately, I was smart enough to use the button label as the name
659** of the widget, and I can extract it via XtName(). Thanks, Motif!
660*/
b2d21e59 661 if (prompt->returnvalue.stringvalue &&
662 (strcmp(prompt->returnvalue.stringvalue, XtName(w)))) {
892c98b2 663 strcpy(prompt->returnvalue.stringvalue, XtName(w));
3583baaa 664 if (prompt->valuechanged)
665 (*prompt->valuechanged)(WidgetToForm(w), prompt);
892c98b2 666 }
7ee9b49f 667
ecb7d146 668}
669
670void
671boolean_callback(w, client_data, call_data)
672Widget w;
673XmAnyCallbackStruct *client_data;
674XmAnyCallbackStruct *call_data;
675{
676 Arg wargs[10];
677 int n;
678 Boolean is_set;
679 UserPrompt *current = (UserPrompt *)client_data;
680 XmString label;
681
682 n = 0;
683 XtSetArg(wargs[n], XmNset, &is_set); n++;
684 XtGetValues (w, wargs, n);
685
686 current->returnvalue.booleanvalue = is_set;
7ee9b49f 687
ecb7d146 688 if (is_set)
689 label = XmStringCreate( "(True)", XmSTRING_DEFAULT_CHARSET);
690 else
691 label = XmStringCreate( "(False)", XmSTRING_DEFAULT_CHARSET);
692 n = 0;
693 XtSetArg(wargs[n], XmNlabelString, label); n++;
694 XtSetValues (w, wargs, n);
695
3583baaa 696 if (current->valuechanged)
697 (*current->valuechanged)(WidgetToForm(w), current);
698
ecb7d146 699#if DEBUG
700 printf ("boolean_callback: button %x is %s\n",
701 w, (is_set ? "True" : "False"));
702#endif
7ee9b49f 703}
704
705void
706menu_callback(w, client_data, call_data)
707Widget w;
708XmAnyCallbackStruct *client_data;
709XmAnyCallbackStruct *call_data;
710{
711 MenuItem *itemhit = (MenuItem *) client_data;
712
b2d21e59 713/* printf ("menu_callback: item '%s', op %d and string '%s'\n",
714 itemhit->label,
715 itemhit->operation,
716 itemhit->form);
717 XtManageChild(entryformwidget);
718*/
7ee9b49f 719 MoiraMenuRequest(itemhit);
ecb7d146 720}
7ee9b49f 721
892c98b2 722
ecb7d146 723void
724string_callback(w, client_data, call_data)
725Widget w;
726XmAnyCallbackStruct *client_data;
727XmAnyCallbackStruct *call_data;
728{
729 UserPrompt *current = (UserPrompt *)client_data;
730 char *newvalue;
731
732 newvalue = XmTextGetString(w);
733
892c98b2 734 if (strcmp(current->returnvalue.stringvalue, newvalue)) {
b2d21e59 735/* printf ("Replacing old value of selection, '%s', with '%s'\n",
892c98b2 736 current->returnvalue.stringvalue,
737 newvalue);
41a6b53e 738 strcpy(current->returnvalue.stringvalue, newvalue);
3583baaa 739 if (current->valuechanged)
740 (*current->valuechanged)(WidgetToForm(w), current);
41a6b53e 741*/ }
ecb7d146 742 XtFree(newvalue);
7ee9b49f 743}
3583baaa 744
745
41a6b53e 746void MoiraFocusOut(w, event, p, n)
747Widget w;
748XEvent *event;
749String *p;
750Cardinal *n;
751{
752 char *newvalue;
753 UserPrompt *current = NULL;
754 EntryForm *f;
755 XmTextRec *tr = (XmTextRec *)w;
756 int i;
757
2528015e 758 if (!tr || tr->core.self != w || tr->core.widget_class != xmTextWidgetClass)
41a6b53e 759 return;
760 newvalue = XmTextGetString(w);
761 f = WidgetToForm(w);
762 for (i = 0; f->inputlines[i]; i++)
763 if (f->inputlines[i]->mywidget == w)
764 current = f->inputlines[i];
765 if (current == NULL) {
766 fprintf(stderr, "Couldn't find prompt structure!\n");
767 return;
768 }
769
770 if (strcmp(current->returnvalue.stringvalue, newvalue)) {
771 strcpy(current->returnvalue.stringvalue, newvalue);
772 if (current->valuechanged)
773 (*current->valuechanged)(f, current);
774 }
775 XtFree(newvalue);
776}
777
778
3583baaa 779void
780newvalue(w, client_data, call_data)
781Widget w;
782XmAnyCallbackStruct *client_data;
783XmAnyCallbackStruct *call_data;
784{
785 UserPrompt *current = (UserPrompt *)client_data;
786 EntryForm *form, *f;
787 int i;
f9c6085e 788 static MenuItem mi;
3583baaa 789
790 if (current->keyword_name == NULL) {
791 PopupErrorMessage("Sorry, that keyword cannot be changed.", NULL);
792 return;
793 }
794 form = (EntryForm *)current->parent;
795 for (i = 0; form->inputlines[i]; i++)
796 if (form->inputlines[i] == current)
797 break;
798 f = GetAndClearForm("add_new_value");
f9c6085e 799 mi.operation = MM_NEW_VALUE;
800 mi.query = "add_alias";
801 mi.argc = 3;
802 mi.form = form->formname;
803 mi.accel = (char *) i;
804 f->menu = &mi;
3583baaa 805 f->extrastuff = current->keyword_name;
806 DisplayForm(f);
807}
808
809
810/* WARNING: This routine uses Motif internal undocumented routines.
811 * It was the only way to get carriage return to Do The Right Thing.
812 * If you are in a single-item tab group, this routine will call
813 * MoiraFormComplete() (same as pressing OK on the bottom of the form).
814 * otherwise, it advances the focus the same as pressing TAB.
815 */
816
817void EnterPressed(w, event, argv, count)
818Widget w;
819XEvent *event;
820char **argv;
821Cardinal *count;
822{
823 Widget next;
824 EntryForm *form;
825
826 next = _XmFindNextTabGroup(w);
827 if (next == w) {
41a6b53e 828 MoiraFocusOut(w, event, argv, count);
3583baaa 829 form = WidgetToForm(w);
830 MoiraFormComplete(NULL, form);
831 } else {
832 _XmMgrTraversal(w, XmTRAVERSE_NEXT_TAB_GROUP);
833 }
834}
835
836
837void CancelForm(w, event, argv, count)
838Widget w;
839XEvent *event;
840char **argv;
841Cardinal *count;
842{
843 EntryForm *form;
844
845 form = WidgetToForm(w);
846 if (form)
847 XtUnmanageChild(form->formpointer);
848}
849
850
851void ExecuteForm(w, event, argv, count)
852Widget w;
853XEvent *event;
854char **argv;
855Cardinal *count;
856{
857 EntryForm *form;
858
859 form = WidgetToForm(w);
41a6b53e 860 if (form) {
861 MoiraFocusOut(w, event, argv, count);
862 MoiraFormComplete(NULL, form);
863 }
3583baaa 864}
865
866
867void DoHelp(w, event, argv, count)
868Widget w;
869XEvent *event;
870char **argv;
871Cardinal *count;
872{
873 EntryForm *form;
874
875 form = WidgetToForm(w);
876 if (form)
877 help(form->formname);
878}
879
880
881extern struct hash *create_hash();
882static struct hash *WFmap = NULL;
883
884MapWidgetToForm(w, f)
885Widget *w;
886EntryForm *f;
887{
888 if (WFmap == NULL) {
889 WFmap = create_hash(101);
890 }
891 hash_store(WFmap, w, f);
892}
893
894EntryForm *WidgetToForm(w)
895Widget *w;
896{
897 return((EntryForm *) hash_lookup(WFmap, w));
898}
b80b4770 899
900
901/* Routines to deal with children of composite widgets */
902
903Widget NthChild(w, n)
904CompositeRec *w;
905int n;
906{
907 return(w->composite.children[n]);
908}
909
910int NumChildren(w)
911CompositeRec *w;
912{
913 return(w->composite.num_children);
914}
This page took 0.204775 seconds and 5 git commands to generate.