#include <Xm/Separator.h>
#include "mmoira.h"
-#define HPADDING 8
-#define WPADDING 20
+static char rcsid[] = "$Header$";
+
#define MAX(a,b) ((a > b) ? a : b)
+#define MIN(a,b) ((a < b) ? a : b)
-extern Widget toplevel;
+int hpad = 10;
+int vpad = 5;
-void map_menu_widget();
void manage_widget();
Widget CreateForm();
Widget CreateMenu();
Widget BuildMenuTree();
+Widget MakeRadioField();
int button_callback();
-int radio_callback();
+void radio_callback();
+void string_callback();
+void boolean_callback();
void menu_callback();
-void post_menu_handler();
+extern void UpdateForm();
+extern int PopupErrorMessage();
+extern void PopupHelpWindow();
+extern int AppendToLog();
+extern void MakeWatchCursor();
+extern void MakeNormalCursor();
+extern Widget SetupLogWidget();
+
+
+void
+manage_widget(w, widget, call_data)
+Widget w, widget;
+XmAnyCallbackStruct *call_data;
+{
+ XtManageChild(widget);
+}
+
+int
+button_callback(w, client_data, call_data)
+Widget w;
+EntryForm *client_data;
+XmAnyCallbackStruct *call_data;
+{
+ char output[100];
+ static int mode = 0;
+
+/* sprintf (output, "Button %x was hit...\n", w);
+ if (mode) {
+ MakeWatchCursor(toplevel);
+ MakeWatchCursor(entryformwidget);
+ mode = 0;
+ }
+ else {
+ MakeNormalCursor(toplevel);
+ MakeNormalCursor(entryformwidget);
+ mode = 1;
+ }
+ AppendToLog(output);
+ PopupErrorMessage("Sorry, no functionality here!\nSecond line", "No further help is available");
+*/
+ XtUnmanageChild(client_data->formpointer);
+
+}
+
+
+Widget
+BuildMenuTree(topW, spec)
+Widget topW;
+MenuItem *spec;
+{
+ return (CreateMenu(topW, spec->submenu, XmHORIZONTAL));
+}
/*
** Read the specification and put up a menu to match...
-**
-** Something in here is making a bad button grab...It either gets the
-** error,
-** "BadAccess (attempt to access private resource denied)
-** Major opcode of failed request: 28 (X_GrabButton)
-**
-** or puts up the menu and permanently grabs the pointer!
-**
-** All Motif pulldown menus are replaced with homebrews until I get an
-** updated widget set to try out.
*/
Widget
Arg wargs[10];
int n;
XmString label; /* !@#$%^ compound string required */
- Widget shellparent;
label = XmStringCreate( "Complete junk", XmSTRING_DEFAULT_CHARSET);
n = 0;
-
-/* MOTIF menus are broken.
XtSetArg(wargs[n], XmNlabelString, label); n++;
- menuparent = XmCreatePopupMenu(parent, "randommenu", wargs, n);
-*/
- XtSetArg(wargs[n], XtNmappedWhenManaged, False); n++;
- shellparent = XtCreateApplicationShell( "shellparent",
- transientShellWidgetClass,
+ if (orientation == XmHORIZONTAL) {
+ XtSetArg(wargs[n], XmNspacing, 5); n++;
+ menuparent = XmCreateMenuBar( parent, "randommenu",
+ wargs, n);
+ XtManageChild(menuparent);
+ }
+ else
+ menuparent = XmCreatePulldownMenu(parent, "randommenu",
wargs, n);
- n = 0;
- if (orientation)
- XtSetArg(wargs[n], XtNorientation, orientation); n++;
- menuparent = XtCreateManagedWidget ( "row",
- xmRowColumnWidgetClass,
- shellparent, wargs, n);
-
-
-/*
- XtAddEventHandler ( parent, ButtonPressMask, FALSE,
- post_menu_handler, menuparent);
-*/
for ( curmenuitem = (*spec);
curmenuitem;
spec++, curmenuitem = (*spec)) {
#endif
label = XmStringCreate( curmenuitem->label,
XmSTRING_DEFAULT_CHARSET);
- if (curmenuitem->submenu) {
- label = XmStringConcat(label,
- XmStringCreate( "...",
- XmSTRING_DEFAULT_CHARSET));
- }
n = 0;
XtSetArg(wargs[n], XmNlabelString, label); n++;
- childbutton = XtCreateManagedWidget( "child",
- xmPushButtonGadgetClass,
- menuparent, wargs, n);
-
if (curmenuitem->submenu) {
#ifdef DEBUG
printf ("It has a submenu, which I'm recursing on...\n");
#endif
-/* MOTIF menus don't work...
- childmenu = XmCreatePulldownMenu(menuparent,
- curmenuitem->label,
- NULL, 0);
-
- n = 0;
+ childmenu = CreateMenu( menuparent,
+ curmenuitem->submenu,
+ XmVERTICAL);
XtSetArg(wargs[n], XmNsubMenuId, childmenu); n++;
childbutton = XtCreateManagedWidget( "child",
xmCascadeButtonWidgetClass,
menuparent, wargs, n);
-*/
-
- childmenu = CreateMenu( childbutton,
- curmenuitem->submenu,
- XmVERTICAL);
- XtAddCallback( childbutton, XmNactivateCallback,
- map_menu_widget, childmenu);
}
else {
+ childbutton = XtCreateManagedWidget( "child",
+ xmPushButtonGadgetClass,
+ menuparent, wargs, n);
+
XtAddCallback( childbutton,
XmNactivateCallback,
menu_callback, curmenuitem);
}
}
- XtRealizeWidget(shellparent);
- return (shellparent);
+ return (menuparent);
}
-/* We don't need this, since I'm using callbacks rather than
-** event handlers.
-
-void
-post_menu_handler(w, menu, event)
-Widget w;
-Widget menu;
-XEvent *event;
-{
- Arg wargs[10];
- int n;
- Widget button;
-
- n = 0;
- XtSetArg(wargs[n], XmNwhichButton, &button); n++;
- XtGetValues(menu, wargs, n);
-
- if ((Widget) (event->xbutton.button) == button) {
- XmMenuPosition (menu, event);
- XtManageChild(menu);
- }
-
- else {
- printf ("Ignoring hit from 'wrong' button\n");
- }
-}
-*/
-
-
-DisplayForm(spec)
-EntryForm *spec;
-{
- Widget w;
-
- w = CreateForm(toplevel, spec);
- XtManageChild(w);
-}
-
-
/*
** Read the specification and put up a form to match...
*/
Widget parent;
EntryForm *spec;
{
- XmBulletinBoardWidget bb;
+ Widget bb;
Arg wargs[10];
- int i, n;
+ int n;
XmString label; /* compound string required */
Dimension height_so_far = 0, width_so_far = 0;
Dimension height, width;
Position x, y;
Widget shellparent;
-/*
- n = 0;
- XtSetArg(wargs[n], XtNmappedWhenManaged, False); n++;
- shellparent = XtCreateApplicationShell( "shellparent",
- topLevelShellWidgetClass,
- wargs, n);
-*/
+ if (spec->formpointer) {
+ UpdateForm(spec);
+ return(spec->formpointer);
+ }
+
+ height_so_far = vpad;
#define GETSIZE(foo) n = 0; \
XtSetArg(wargs[n], XtNwidth, &width); n++; \
XtGetValues (foo, wargs, n); \
#define STORESIZE if (width > width_so_far) width_so_far = width;\
- height_so_far += height + HPADDING;
+ height_so_far += height + vpad;
n = 0;
- XtSetArg(wargs[n], XmNautoUnmanage, FALSE); n++;
- bb = (XmBulletinBoardWidget)
- XmCreateBulletinBoardDialog(parent, "board", wargs, n);
+ XtSetArg(wargs[n], XmNautoUnmanage, False); n++;
+ bb = XmCreateBulletinBoardDialog(parent, "board", wargs, n);
+
+ spec->formpointer = bb;
+#ifdef FORMTITLES
label = XmStringCreate(spec->formname, XmSTRING_DEFAULT_CHARSET);
n = 0;
XtSetArg(wargs[n], XmNlabelString, label); n++;
bb, wargs, n);
GETSIZE(titleW);
STORESIZE;
+#endif
label = XmStringCreate(spec->instructions, XmSTRING_DEFAULT_CHARSET);
n = 0;
XtSetArg(wargs[n], XmNlabelString, label); n++;
XtSetArg(wargs[n], XtNx, 0); n++;
XtSetArg(wargs[n], XtNy, height_so_far); n++;
- instructionW = XtCreateManagedWidget( "title",
+ instructionW = XtCreateManagedWidget( "instructions",
xmLabelWidgetClass,
bb, wargs, n);
GETSIZE(instructionW);
height = height_so_far;
width = width_so_far;
- MakeInputLines((Widget) bb, &height, &width, spec->inputlines);
+ MakeInputLines(bb, &height, &width, spec);
STORESIZE;
height = height_so_far;
width = width_so_far;
- MakeButtons((Widget) bb, &height, &width, spec->buttons, (char *)spec);
+ MakeButtons(bb, &height, &width, spec);
STORESIZE;
/*
** Center the title of the form
*/
+#ifdef FORMTITLES
n = 0;
XtSetArg(wargs[n], XtNwidth, &width); n++;
XtGetValues (titleW, wargs, n);
n = 0;
XtSetArg(wargs[n], XtNx, x); n++;
XtSetValues (titleW, wargs, n);
+#endif
+ n = 0;
+ XtSetArg(wargs[n], XtNwidth, &width); n++;
+ XtGetValues (instructionW, wargs, n);
+
+ x = (width_so_far - width) / 2;
- spec->formpointer = (Widget) bb;
+ n = 0;
+ XtSetArg(wargs[n], XtNx, x); n++;
+ XtSetValues (instructionW, wargs, n);
return((Widget) bb);
}
** according to the widest left side noted.
*/
-MakeInputLines(parent, pheight, pwidth, inputlines)
+MakeInputLines(parent, pheight, pwidth, spec)
Widget parent;
Dimension *pheight;
Dimension *pwidth;
-UserPrompt **inputlines;
+EntryForm *spec;
{
UserPrompt *current;
XmString label; /* compound string required */
Widget child;
Dimension width, height, maxleftwidth = 0, maxrightwidth = 0;
Dimension localy, leftheight = 0, rightheight = 0;
- UserPrompt **myinputlines = inputlines;
+ UserPrompt **myinputlines = spec->inputlines;
int foo = 30;
Widget children[20];
*/
n = 0;
XtSetArg(wargs[n], XtNy, localy + *pheight); n++;
+ XtSetArg(wargs[n], XmNtraversalOn, True); n++;
XtSetArg(wargs[n], XtNsensitive,
!(current->insensitive)); n++;
switch (current->type) {
case FT_STRING:
- children[i] = XtCreateManagedWidget( "child",
+ children[i] = XtCreateManagedWidget( "textwidget",
xmTextWidgetClass,
parent, wargs, n);
+ XtAddCallback( children[i], XmNvalueChangedCallback,
+ string_callback, current);
if (current->returnvalue.stringvalue) {
XmTextSetString (children[i], current->returnvalue.stringvalue);
}
break;
case FT_BOOLEAN:
- XtSetArg(wargs[n], XmNset, current->returnvalue.booleanvalue); n++;
-/*
-** EEEuch! Not only to I have to use a blank (not NULL!) string to
-** override the ToggleButton's insistance on labelling itself, it has
-** to be a _compound_ blank string!
-*/
- label = XmStringCreate( " ", XmSTRING_DEFAULT_CHARSET);
+ XtSetArg(wargs[n], XmNset,
+ current->returnvalue.booleanvalue ? True : False); n++;
+
+ if (current->returnvalue.booleanvalue)
+ label = XmStringCreate( "(True)", XmSTRING_DEFAULT_CHARSET);
+ else
+ label = XmStringCreate( "(False)", XmSTRING_DEFAULT_CHARSET);
XtSetArg(wargs[n], XmNlabelString, label); n++;
children[i] = XtCreateManagedWidget( "ignore this",
parent, wargs, n);
XtAddCallback( children[i], XmNvalueChangedCallback,
- radio_callback, NULL);
+ boolean_callback, current);
GETSIZE (children[i]);
rightheight = height;
break;
case FT_KEYWORD:
- children[i] = XmCreateRadioBox(parent, "radio", wargs, n);
- XtManageChild(children[i]);
- AddRadioButtons( children[i],
- current,
- &rightheight);
+ children[i] =
+ MakeRadioField(parent, current, &rightheight);
+ XtManageChild(children[i]);
+ XtSetValues(children[i], wargs, n);
GETSIZE (children[i]);
if (width > maxrightwidth)
maxrightwidth = width;
printf ("Sorry, don't recognize that type\n");
break;
}
+ XmAddTabGroup(children[i]);
+ current->mywidget = children[i];
- localy += MAX(rightheight, leftheight) + HPADDING;
+ localy += MAX(rightheight, leftheight) + vpad;
}
/*
** Now slide the input widgets right as far as the widest prompt.
*/
n = 0;
- XtSetArg(wargs[n], XtNx, maxleftwidth + WPADDING); n++;
+ XtSetArg(wargs[n], XtNx, maxleftwidth + hpad); n++;
for (; i; i--)
XtSetValues (children[i - 1], wargs, n);
- *pheight = localy - HPADDING;
- *pwidth = maxleftwidth + maxrightwidth + WPADDING;
+ *pheight = localy - vpad;
+ *pwidth = maxleftwidth + maxrightwidth + hpad;
}
/*
** All the junk about keeping track of the sum of the children's heights
** is because the !#$% RowColumn widget doesn't sum them for us, NOR
-** does it accept SetValues on its XtNHeight!
+** does it accept SetValues on its XtNHeight! Thanks, Motif!
*/
-AddRadioButtons(parent, prompt, pheight)
+Widget
+MakeRadioField(parent, prompt, pheight)
Widget parent;
UserPrompt *prompt;
Dimension *pheight;
{
- Widget child;
+ Widget radioparent, child;
char *current;
Arg wargs[10];
- int i, n;
- XmString label; /* compound string required */
+ int count, n;
+ XmString label; /* accursed compound string required */
Dimension height, width;
- Dimension height_so_far = 0;
- char **keywords = prompt->keywords;
- char *defvalue = prompt->returnvalue.stringvalue;
+ char **keywords;
+
- if (!keywords) {
+ if (!prompt->keywords) {
fprintf (stderr, "Warning: No list of keywords for widget\n");
return;
}
+ for ( count = 0, keywords = prompt->keywords;
+ *keywords;
+ keywords++, count++);
+
+/*
+** Although the XmNnumColumns resource is documented as actually
+** representing the number of _rows_ when XmNorientation is set to XmVERTICAL,
+** it doesn't. So I need to count the items myself and manually set the
+** number of columns to get a maximum of five rows. There's no XmNnumRows
+** resource. Thanks, Motif!
+*/
+
+ n = 0;
+ XtSetArg(wargs[n], XmNspacing, 0); n++;
+
+ if (count > 5) {
+ XtSetArg(wargs[n], XmNnumColumns, 1 + (count-1) / 5); n++;
+ XtSetArg(wargs[n], XmNorientation, XmVERTICAL); n++;
+ XtSetArg(wargs[n], XmNpacking, XmPACK_COLUMN); n++;
+ }
+
+ radioparent = XmCreateRadioBox(parent, "radio", wargs, n);
+
+ keywords = prompt->keywords;
for (current=(*keywords); current; keywords++, current=(*keywords)) {
n = 0;
label = XmStringCreate(current, XmSTRING_DEFAULT_CHARSET);
XtSetArg(wargs[n], XmNlabelString, label); n++;
- if (!strcmp (current, defvalue)) {
+ if ((prompt->returnvalue.stringvalue) &&
+ (!strcmp (current, prompt->returnvalue.stringvalue))) {
XtSetArg(wargs[n], XmNset, True); n++;
}
else {
XtSetArg(wargs[n], XmNset, False); n++;
}
child = XtCreateManagedWidget( current,
- xmToggleButtonGadgetClass,
- parent, wargs, n);
+ xmToggleButtonWidgetClass,
+ radioparent, wargs, n);
XtAddCallback( child, XmNvalueChangedCallback,
radio_callback, prompt);
- GETSIZE (child);
- height_so_far += height;
}
/*
- GETSIZE (parent);
- printf ("height of radio parent was %d\n", height);
- n = 0;
- XtSetArg(wargs[n], XtNheight, height_so_far); n++;
- XtSetValues (parent, wargs, n);
- GETSIZE (parent);
- printf ("height of radio parent is now %d\n", height);
+** Assume all child widgets are the same height. Increase height by
+** five times this, or the actual number of children, whichever is lesser.
*/
- *pheight = height_so_far;
+
+ GETSIZE (child);
+ *pheight = (height * MIN(5, count)) + vpad;
+
+ return(radioparent);
}
-MakeButtons(parent, pheight, pwidth, buttons, data)
+MakeButtons(parent, pheight, pwidth, spec)
Widget parent;
Dimension *pheight;
Dimension *pwidth;
-BottomButton **buttons;
-caddr_t data;
+EntryForm *spec;
{
BottomButton *current;
XmString label; /* compound string required */
int i, n;
Dimension newwidth, width = 25;
Widget newbutton;
+ BottomButton **buttons = spec->buttons;
+
+ *pheight += vpad;
n = 0;
XtSetArg(wargs[n], XtNy, *pheight); n++;
XtCreateManagedWidget( "separator",
xmSeparatorWidgetClass,
parent, wargs, n);
- *pheight += HPADDING;
+ *pheight += vpad;
for ( current=(*buttons);
current;
parent, wargs, n);
XtAddCallback( newbutton, XmNactivateCallback,
- current->returnfunction, data);
+ current->returnfunction, spec);
n = 0;
XtSetArg(wargs[n], XtNwidth, &newwidth); n++;
XtGetValues (newbutton, wargs, n);
- width += (newwidth + WPADDING);
+ width += (newwidth + hpad);
}
(*pheight) += 100;
}
void
-map_menu_widget(w, widget, call_data)
-Widget w, widget;
+radio_callback(w, client_data, call_data)
+Widget w;
+XmAnyCallbackStruct *client_data;
XmAnyCallbackStruct *call_data;
{
Arg wargs[10];
int n;
- Position x, y;
- Widget foo;
+ Boolean is_set;
-
- for ( x = 0, y = 0, foo = w->core.parent;
- foo;
- foo = foo->core.parent) {
+ UserPrompt *prompt = (UserPrompt *) client_data;
- x += foo->core.x;
- y += foo->core.y;
- }
+ n = 0;
+ XtSetArg(wargs[n], XmNset, &is_set); n++;
+ XtGetValues (w, wargs, n);
+
+ if (!is_set)
+ return;
/*
- if (w->core.parent)
- x += w->core.parent->core.width;
+** Since Motif insists on using !@#$% Compound Strings as the text for
+** its label widgets, but doesn't provide a way of getting a char* back
+** from a !@#$% Compound String, I can't retrieve the label of the button
+** that was hit.
+**
+** Fortunately, I was smart enough to use the button label as the name
+** of the widget, and I can extract it via XtName(). Thanks, Motif!
*/
- x += w->core.width;
- y += w->core.y;
-
- n = 0;
- XtSetArg(wargs[n], XtNx, x); n++;
- XtSetArg(wargs[n], XtNy, y); n++;
- XtSetValues(widget, wargs, n);
+ if (prompt->returnvalue.stringvalue &&
+ (strcmp(prompt->returnvalue.stringvalue, XtName(w)))) {
+ strcpy(prompt->returnvalue.stringvalue, XtName(w));
+ }
- XtMapWidget(widget);
}
void
-manage_widget(w, widget, call_data)
-Widget w, widget;
-XmAnyCallbackStruct *call_data;
-{
- XtManageChild(widget);
-}
-
-int
-button_callback(w, client_data, call_data)
-Widget w;
-EntryForm *client_data;
-XmAnyCallbackStruct *call_data;
-{
- XtUnmanageChild(client_data->formpointer);
-}
-
-int
-radio_callback(w, client_data, call_data)
+boolean_callback(w, client_data, call_data)
Widget w;
XmAnyCallbackStruct *client_data;
XmAnyCallbackStruct *call_data;
{
Arg wargs[10];
- int i, n;
- XmString label; /* !@#$ compound string required! */
- char *text_value;
-
- UserPrompt *prompt = (UserPrompt *) client_data;
-
- printf ("radio_callback: button %x, data %x\n", w, client_data);
-
-/*
-** It should be _easy_ to find the value of a label, right? _WRONG!_
-** Have to disassemble the !@#$ compound text to get a char*, and
-** Motif doesn't provide any functions to do so. So I stash the label
-** value as the name of the widget.
+ int n;
+ Boolean is_set;
+ UserPrompt *current = (UserPrompt *)client_data;
+ XmString label;
n = 0;
- XtSetArg(wargs[n], XmNlabelString, label); n++;
+ XtSetArg(wargs[n], XmNset, &is_set); n++;
XtGetValues (w, wargs, n);
- XmStringGetLtoR (label,
- XmSTRING_DEFAULT_CHARSET, &text_value);
-*/
+ current->returnvalue.booleanvalue = is_set;
+ if (is_set)
+ label = XmStringCreate( "(True)", XmSTRING_DEFAULT_CHARSET);
+ else
+ label = XmStringCreate( "(False)", XmSTRING_DEFAULT_CHARSET);
+ n = 0;
+ XtSetArg(wargs[n], XmNlabelString, label); n++;
+ XtSetValues (w, wargs, n);
-/*
-** Unfortunately, Xt caches w->core.name into something besides a char*,
-** so I can't use it. And XtName is, somehow, unavailable.
-
- if (!prompt) {
- printf ("Oops! radio_callback called from '%s' with no data\n",
- w->core.name);
- return(0);
- }
-
- printf ("Replacing old value of selection, '%s', with '%s'\n",
- prompt->returnvalue.stringvalue,
- w->core.name);
-
- strcpy(prompt->returnvalue.stringvalue, w->core.name);
-*/
-
+#if DEBUG
+ printf ("boolean_callback: button %x is %s\n",
+ w, (is_set ? "True" : "False"));
+#endif
}
void
{
MenuItem *itemhit = (MenuItem *) client_data;
-#ifdef DEBUG
- printf ("menu_callback: item '%s', op %d and string '%s'\n",
+/* printf ("menu_callback: item '%s', op %d and string '%s'\n",
itemhit->label,
itemhit->operation,
itemhit->form);
-#endif
- MoiraMenuRequest(itemhit);
-/*
-** Unmap the shell of this button. (UGLY HACK until Motif menus work)
+ XtManageChild(entryformwidget);
*/
+ MoiraMenuRequest(itemhit);
+}
+
- XtUnmapWidget(XtParent(XtParent(w)));
+void
+string_callback(w, client_data, call_data)
+Widget w;
+XmAnyCallbackStruct *client_data;
+XmAnyCallbackStruct *call_data;
+{
+ UserPrompt *current = (UserPrompt *)client_data;
+ char *newvalue;
+
+ newvalue = XmTextGetString(w);
+
+ if (strcmp(current->returnvalue.stringvalue, newvalue)) {
+/* printf ("Replacing old value of selection, '%s', with '%s'\n",
+ current->returnvalue.stringvalue,
+ newvalue);
+*/ strcpy(current->returnvalue.stringvalue, newvalue);
+ }
+ XtFree(newvalue);
}