]> andersk Git - moira.git/blob - clients/mmoira/formup.c
*** empty log message ***
[moira.git] / clients / mmoira / formup.c
1 #include        <stdio.h>
2 #include        <X11/StringDefs.h>
3 #include        <X11/IntrinsicP.h>
4 #include        <X11/Shell.h>
5 #include        <X11/Core.h>
6 #include        <X11/CoreP.h>
7 #include        <Xm/Xm.h>
8 #include        <Xm/BulletinB.h>
9 #include        <Xm/Label.h>
10 #include        <Xm/Text.h>
11 #include        <Xm/PushB.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>
18 #include        "mmoira.h"
19
20 static char rcsid[] = "$Header$";
21
22 #define MAX(a,b)        ((a > b) ? a : b)
23 #define MIN(a,b)        ((a < b) ? a : b)
24
25 int     hpad = 10;
26 int     vpad = 5;
27
28 void    manage_widget();
29 Widget  CreateForm();
30 Widget  CreateMenu();
31 Widget  BuildMenuTree();
32 Widget  MakeRadioField();
33 int     button_callback();
34 void    radio_callback();
35 void    string_callback();
36 void    boolean_callback();
37 void    menu_callback();
38
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();
46
47
48 void
49 manage_widget(w, widget, call_data)
50 Widget  w, widget;
51 XmAnyCallbackStruct     *call_data;
52 {
53         XtManageChild(widget);  
54 }
55
56 int
57 button_callback(w, client_data, call_data)
58 Widget          w;
59 EntryForm       *client_data;
60 XmAnyCallbackStruct     *call_data;
61 {
62         char    output[100];
63         static int      mode = 0;
64
65 /*      sprintf (output, "Button %x was hit...\n", w);
66         if (mode) {
67                 MakeWatchCursor(toplevel);
68                 MakeWatchCursor(entryformwidget);
69                 mode = 0;
70         }
71         else {
72                 MakeNormalCursor(toplevel);
73                 MakeNormalCursor(entryformwidget);
74                 mode = 1;
75         }
76         AppendToLog(output);
77         PopupErrorMessage("Sorry, no functionality here!\nSecond line", "No further help is available");
78 */
79         XtUnmanageChild(client_data->formpointer);
80
81 }
82
83
84 Widget
85 BuildMenuTree(topW, spec)
86 Widget          topW;
87 MenuItem        *spec;
88 {
89         return (CreateMenu(topW, spec->submenu, XmHORIZONTAL));
90 }
91
92 /*
93 ** Read the specification and put up a menu to match...
94 */
95
96 Widget
97 CreateMenu(parent, spec, orientation)
98 Widget          parent;
99 MenuItem        **spec;
100 int             orientation;
101 {
102         Widget          menuparent;
103         MenuItem        *curmenuitem;
104         Widget          childbutton, childmenu;
105         Arg             wargs[10];
106         int             n;
107         XmString        label;          /* !@#$%^ compound string required */
108
109         label = XmStringCreate( "Complete junk", XmSTRING_DEFAULT_CHARSET);
110
111         n = 0;
112         XtSetArg(wargs[n], XmNlabelString, label);      n++;
113
114         if (orientation == XmHORIZONTAL) {
115                 XtSetArg(wargs[n], XmNspacing, 5);      n++;
116                 menuparent = XmCreateMenuBar(   parent, "randommenu", 
117                                         wargs, n);
118                 XtManageChild(menuparent);
119         }
120         else
121                 menuparent = XmCreatePulldownMenu(parent, "randommenu", 
122                                                 wargs, n);
123
124         for (   curmenuitem = (*spec);
125                 curmenuitem;
126                 spec++, curmenuitem = (*spec)) {
127
128 #ifdef  DEBUG
129                 printf ("Making entry:  %s\n", curmenuitem->label);
130 #endif
131                 label = XmStringCreate( curmenuitem->label,
132                                         XmSTRING_DEFAULT_CHARSET);
133                 n = 0;
134                 XtSetArg(wargs[n], XmNlabelString, label);      n++;
135
136                 if (curmenuitem->submenu) {
137 #ifdef  DEBUG
138                         printf ("It has a submenu, which I'm recursing on...\n");
139 #endif
140                         childmenu = CreateMenu( menuparent, 
141                                                 curmenuitem->submenu,
142                                                 XmVERTICAL);
143                         XtSetArg(wargs[n], XmNsubMenuId, childmenu);    n++;
144
145                         childbutton = XtCreateManagedWidget(    "child",
146                                         xmCascadeButtonWidgetClass,
147                                         menuparent, wargs, n);
148
149                 }
150
151                 else {
152                         childbutton = XtCreateManagedWidget(    "child",
153                                         xmPushButtonGadgetClass,
154                                         menuparent, wargs, n);
155
156                         XtAddCallback(  childbutton, 
157                                         XmNactivateCallback, 
158                                         menu_callback, curmenuitem);
159                 }
160         }
161
162         return (menuparent);
163 }
164
165 /*
166 ** Read the specification and put up a form to match...
167 */
168
169 Widget
170 CreateForm(parent, spec)
171 Widget          parent;
172 EntryForm       *spec;
173 {
174         Widget          bb;
175         Arg             wargs[10];
176         int             n;
177         XmString        label;          /* compound string required */
178         Dimension       height_so_far = 0, width_so_far = 0;
179         Dimension       height, width;
180         Widget          titleW, instructionW;
181         Position        x, y;
182         Widget          shellparent;
183
184         if (spec->formpointer) {
185                 UpdateForm(spec);
186                 return(spec->formpointer);
187         }
188
189         height_so_far = vpad;
190
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); \
195
196 #define STORESIZE       if (width > width_so_far) width_so_far = width;\
197                         height_so_far += height + vpad;
198
199
200         n = 0;
201         XtSetArg(wargs[n], XmNautoUnmanage, False);             n++;
202         bb = XmCreateBulletinBoardDialog(parent, "board", wargs, n);
203
204         spec->formpointer = bb;
205
206 #ifdef FORMTITLES
207         label = XmStringCreate(spec->formname, XmSTRING_DEFAULT_CHARSET);
208         n = 0;
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",
213                                 xmLabelWidgetClass,
214                                 bb, wargs, n);
215         GETSIZE(titleW);
216         STORESIZE;
217 #endif
218
219         label = XmStringCreate(spec->instructions, XmSTRING_DEFAULT_CHARSET);
220         n = 0;
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",
225                                 xmLabelWidgetClass,
226                                 bb, wargs, n);
227         GETSIZE(instructionW);
228         STORESIZE;
229
230         height = height_so_far;
231         width = width_so_far;
232         MakeInputLines(bb, &height, &width, spec);
233         STORESIZE;
234
235         height = height_so_far;
236         width = width_so_far;
237         MakeButtons(bb, &height, &width, spec);
238         STORESIZE;
239
240 /*
241 ** Center the title of the form
242 */
243 #ifdef FORMTITLES
244         n = 0;
245         XtSetArg(wargs[n], XtNwidth, &width);                   n++;
246         XtGetValues (titleW, wargs, n);
247
248         x = (width_so_far - width) / 2;
249
250         n = 0;
251         XtSetArg(wargs[n], XtNx, x);                            n++;
252         XtSetValues (titleW, wargs, n);
253 #endif
254         n = 0;
255         XtSetArg(wargs[n], XtNwidth, &width);                   n++;
256         XtGetValues (instructionW, wargs, n);
257
258         x = (width_so_far - width) / 2;
259
260         n = 0;
261         XtSetArg(wargs[n], XtNx, x);                            n++;
262         XtSetValues (instructionW, wargs, n);
263
264         return((Widget) bb);
265 }
266
267 /*
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.
270 **
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.
275 */
276
277 MakeInputLines(parent, pheight, pwidth, spec)
278 Widget          parent;
279 Dimension       *pheight;
280 Dimension       *pwidth;
281 EntryForm       *spec;
282 {
283         UserPrompt      *current;
284         XmString        label;          /* compound string required */
285         Arg             wargs[10];
286         int             i, n;
287         Widget          child;
288         Dimension       width, height, maxleftwidth = 0, maxrightwidth = 0;
289         Dimension       localy, leftheight = 0, rightheight = 0;
290         UserPrompt      **myinputlines = spec->inputlines;
291         int             foo = 30;
292         Widget          children[20];
293
294         for (   current = (*myinputlines), localy = 0,  i = 0;
295                 current; 
296                 myinputlines++, current = (*myinputlines), i++) {
297
298
299 #ifdef  DEBUG
300                 printf ("Making entry %d: %s of type %d\n", 
301                                 i, current->prompt, current->type);
302 #endif
303 /*
304 ** First, make the prompt
305 */
306                 label = XmStringCreate( current->prompt, 
307                                         XmSTRING_DEFAULT_CHARSET);
308                 n = 0;
309                 XtSetArg(wargs[n], XmNlabelString, label);      n++;
310                 XtSetArg(wargs[n], XtNy, localy + *pheight);    n++;
311                 child = XtCreateManagedWidget(  "prompt",
312                                 xmLabelWidgetClass,
313                                 parent, wargs, n);
314
315                 GETSIZE(child);
316                 leftheight = height;
317                 if (width > maxleftwidth)
318                         maxleftwidth = width;
319
320 /*
321 ** Second, make the input widget
322 */
323                 n = 0;
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) {
329                 case FT_STRING:
330                         children[i] = XtCreateManagedWidget(    "textwidget",
331                                                 xmTextWidgetClass,
332                                                 parent, wargs, n);
333                         XtAddCallback(  children[i], XmNvalueChangedCallback,
334                                 string_callback, current);
335                         if (current->returnvalue.stringvalue) {
336                                 XmTextSetString (children[i], current->returnvalue.stringvalue);
337                         }
338                         GETSIZE (children[i]);
339                         rightheight = height;
340                         if (width > maxrightwidth)
341                                 maxrightwidth = width;
342                         break;
343
344                 case FT_BOOLEAN:
345                         XtSetArg(wargs[n], XmNset,
346                                  current->returnvalue.booleanvalue ? True : False);     n++;
347
348                         if (current->returnvalue.booleanvalue)
349                                 label = XmStringCreate( "(True)", XmSTRING_DEFAULT_CHARSET);
350                         else
351                                 label = XmStringCreate( "(False)", XmSTRING_DEFAULT_CHARSET);
352                         XtSetArg(wargs[n], XmNlabelString, label);      n++;
353
354                         children[i] = XtCreateManagedWidget(    "ignore this",
355                                                 xmToggleButtonWidgetClass,
356                                                 parent, wargs, n);
357
358                         XtAddCallback(  children[i], XmNvalueChangedCallback,
359                                 boolean_callback, current);
360
361                         GETSIZE (children[i]);
362                         rightheight = height;
363                         if (width > maxrightwidth)
364                                 maxrightwidth = width;
365                         break;
366
367                 case FT_KEYWORD:
368                         children[i] = 
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;
375                         break;
376
377                 default:
378                         printf ("Sorry, don't recognize that type\n");
379                         break;
380                 }
381                 XmAddTabGroup(children[i]);
382                 current->mywidget = children[i];
383
384                 localy += MAX(rightheight, leftheight) + vpad;
385         }
386
387 /*
388 ** Now slide the input widgets right as far as the widest prompt.
389 */
390         n = 0;
391         XtSetArg(wargs[n], XtNx, maxleftwidth + hpad);  n++;
392         for (; i; i--)
393                 XtSetValues (children[i - 1], wargs, n);
394
395         *pheight = localy - vpad;
396         *pwidth = maxleftwidth + maxrightwidth + hpad;
397 }
398
399 /*
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!
403 */
404
405 Widget
406 MakeRadioField(parent, prompt, pheight)
407 Widget          parent;
408 UserPrompt      *prompt;
409 Dimension       *pheight;
410 {
411         Widget  radioparent, child;
412         char    *current;
413         Arg     wargs[10];
414         int     count, n;
415         XmString        label;  /* accursed compound string required */
416         Dimension       height, width;
417         char    **keywords;
418
419
420         if (!prompt->keywords) {
421                 fprintf (stderr, "Warning:  No list of keywords for widget\n");
422                 return;
423         }
424         for (   count = 0, keywords = prompt->keywords;
425                 *keywords; 
426                 keywords++, count++);
427
428 /*
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!
434 */
435
436         n = 0;
437         XtSetArg(wargs[n], XmNspacing, 0);      n++;
438
439         if (count > 5) {
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++;
443         }
444
445         radioparent = XmCreateRadioBox(parent, "radio", wargs, n);
446
447         keywords = prompt->keywords;
448         for (current=(*keywords); current; keywords++, current=(*keywords)) {
449                 n = 0;
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++;
455                 }
456                 else {
457                         XtSetArg(wargs[n], XmNset, False);      n++;
458                 }
459                 child = XtCreateManagedWidget(  current,
460                                                 xmToggleButtonWidgetClass,
461                                                 radioparent, wargs, n);
462
463                 XtAddCallback(  child, XmNvalueChangedCallback,
464                                 radio_callback, prompt);
465
466         }
467 /*
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.
470 */
471
472         GETSIZE (child);
473         *pheight = (height * MIN(5, count)) + vpad; 
474
475         return(radioparent);
476 }
477
478 MakeButtons(parent, pheight, pwidth, spec)
479 Widget          parent;
480 Dimension       *pheight;
481 Dimension       *pwidth;
482 EntryForm       *spec;
483 {
484         BottomButton    *current;
485         XmString        label;          /* compound string required */
486         Arg             wargs[10];
487         int             i, n;
488         Dimension       newwidth, width = 25;
489         Widget          newbutton;
490         BottomButton    **buttons = spec->buttons;
491
492         *pheight += vpad;
493
494         n = 0;
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,
500                                 parent, wargs, n);
501         *pheight += vpad;
502
503         for (   current=(*buttons); 
504                 current; 
505                 buttons++, current=(*buttons)) {
506
507 #ifdef  DEBUG
508                 printf ("Making a button labeled %s\n", current->label);
509 #endif
510                 label = XmStringCreate( current->label, 
511                                         XmSTRING_DEFAULT_CHARSET);
512                 n = 0;
513                 XtSetArg(wargs[n], XtNy, (*pheight));                   n++;
514                 XtSetArg(wargs[n], XtNx, width);                        n++;
515                 XtSetArg(wargs[n], XmNlabelString, label);              n++;
516
517                 newbutton = XtCreateManagedWidget(      current->label,
518                                                 xmPushButtonWidgetClass,
519                                                 parent, wargs, n);
520
521                 XtAddCallback(  newbutton, XmNactivateCallback,
522                                 current->returnfunction, spec);
523                 n = 0;
524                 XtSetArg(wargs[n], XtNwidth, &newwidth);                n++;
525                 XtGetValues (newbutton, wargs, n);
526
527                 width += (newwidth + hpad);
528         }
529
530         (*pheight) += 100;
531 }
532
533 void
534 radio_callback(w, client_data, call_data)
535 Widget  w;
536 XmAnyCallbackStruct     *client_data;
537 XmAnyCallbackStruct     *call_data;
538 {
539         Arg             wargs[10];
540         int             n;
541         Boolean         is_set;
542
543         UserPrompt      *prompt = (UserPrompt *) client_data;
544
545         n = 0;
546         XtSetArg(wargs[n], XmNset, &is_set);    n++;
547         XtGetValues (w, wargs, n);
548
549         if (!is_set)
550                 return;
551
552 /*
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 
556 ** that was hit. 
557 **
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!
560 */
561         if (prompt->returnvalue.stringvalue &&
562                         (strcmp(prompt->returnvalue.stringvalue, XtName(w)))) {
563                 strcpy(prompt->returnvalue.stringvalue, XtName(w));
564         }
565
566 }
567
568 void
569 boolean_callback(w, client_data, call_data)
570 Widget  w;
571 XmAnyCallbackStruct     *client_data;
572 XmAnyCallbackStruct     *call_data;
573 {
574         Arg             wargs[10];
575         int             n;
576         Boolean         is_set;
577         UserPrompt      *current = (UserPrompt *)client_data;
578         XmString        label;
579
580         n = 0;
581         XtSetArg(wargs[n], XmNset, &is_set);                    n++;
582         XtGetValues (w, wargs, n);
583
584         current->returnvalue.booleanvalue = is_set;
585
586         if (is_set)
587                 label = XmStringCreate( "(True)", XmSTRING_DEFAULT_CHARSET);
588         else
589                 label = XmStringCreate( "(False)", XmSTRING_DEFAULT_CHARSET);
590         n = 0;
591         XtSetArg(wargs[n], XmNlabelString, label);              n++;
592         XtSetValues (w, wargs, n);
593
594 #if DEBUG
595         printf ("boolean_callback:  button %x is %s\n", 
596                         w, (is_set ? "True" : "False"));
597 #endif
598 }
599
600 void
601 menu_callback(w, client_data, call_data)
602 Widget  w;
603 XmAnyCallbackStruct     *client_data;
604 XmAnyCallbackStruct     *call_data;
605 {
606         MenuItem        *itemhit = (MenuItem *) client_data;
607
608 /*      printf  ("menu_callback: item '%s', op %d and string '%s'\n", 
609                         itemhit->label, 
610                         itemhit->operation, 
611                         itemhit->form);
612         XtManageChild(entryformwidget); 
613 */
614         MoiraMenuRequest(itemhit);
615 }
616
617
618 void
619 string_callback(w, client_data, call_data)
620 Widget  w;
621 XmAnyCallbackStruct     *client_data;
622 XmAnyCallbackStruct     *call_data;
623 {
624         UserPrompt      *current = (UserPrompt *)client_data;
625         char            *newvalue;
626
627         newvalue = XmTextGetString(w);
628
629         if (strcmp(current->returnvalue.stringvalue, newvalue)) {
630 /*              printf ("Replacing old value of selection, '%s', with '%s'\n",
631                                 current->returnvalue.stringvalue,
632                                 newvalue);
633 */              strcpy(current->returnvalue.stringvalue, newvalue);
634         }
635         XtFree(newvalue);
636 }
This page took 0.088859 seconds and 5 git commands to generate.