SetMinimumDimensions -> WidgetSetMinWidth
[grace.git] / src / motif.c
blob6a0c5a259633e134995eb037094026e05f473415
1 /*
2 * Grace - GRaphing, Advanced Computation and Exploration of data
4 * Home page: http://plasma-gate.weizmann.ac.il/Grace/
6 * Copyright (c) 2012 Grace Development Team
8 * Maintained by Evgeny Stambulchik
11 * All Rights Reserved
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 /* Motif widgets */
30 #include "widgets.h"
32 #include "events.h"
34 #include <ctype.h>
35 #include <stdarg.h>
36 #include <Xm/Xm.h>
37 #include <Xm/CascadeBG.h>
38 #include <Xm/DialogS.h>
39 #include <Xm/Form.h>
40 #include <Xm/Label.h>
41 #include <Xm/PushB.h>
42 #include <Xm/RowColumn.h>
43 #include <Xm/Text.h>
44 #include <Xm/ToggleB.h>
45 #include "Tab.h"
46 #include "ListTree.h"
48 #include "globals.h"
50 /* Widgets */
51 void WidgetManage(Widget w)
53 XtManageChild(w);
56 void WidgetUnmanage(Widget w)
58 XtUnmanageChild(w);
61 int WidgetIsManaged(Widget w)
63 return (XtIsManaged(w) == True) ? TRUE:FALSE;
66 void *WidgetGetUserData(Widget w)
68 void *udata = NULL;
69 XtVaGetValues(w, XmNuserData, &udata, NULL);
71 return udata;
74 void WidgetSetUserData(Widget w, void *udata)
76 XtVaSetValues(w, XmNuserData, udata, NULL);
79 void WidgetSetSensitive(Widget w, int onoff)
81 XtSetSensitive(w, onoff ? True : False);
84 void WidgetSetHeight(Widget w, unsigned int height)
86 XtVaSetValues(w, XmNheight, (Dimension) height, NULL);
89 void WidgetSetSize(Widget w, unsigned int width, unsigned int height)
91 XtVaSetValues(w,
92 XmNwidth, (Dimension) width,
93 XmNheight, (Dimension) height,
94 NULL);
97 void WidgetGetSize(Widget w, unsigned int *width, unsigned int *height)
99 Dimension ww, wh;
101 XtVaGetValues(w,
102 XmNwidth, &ww,
103 XmNheight, &wh,
104 NULL);
106 *width = (unsigned int) ww;
107 *height = (unsigned int) wh;
110 void WidgetSetMinWidth(Widget w, unsigned int width, unsigned int height)
112 XtVaSetValues(w, XmNpaneMinimum, width, NULL);
115 static int toolkit_modifiers_to_grace_modifiers(void *event)
117 XKeyEvent *xke;
118 int modifiers = NO_MODIFIER;
120 xke = (XKeyEvent *) event;
122 if (xke->state & ControlMask) {
123 modifiers = modifiers ^ CONTROL_MODIFIER;
126 if (xke->state & ShiftMask) {
127 modifiers = modifiers ^ SHIFT_MODIFIER;
130 return modifiers;
133 static int toolkit_key_to_grace_key(void *event)
135 XKeyEvent *xke;
136 KeySym keybuf;
138 xke = (XKeyEvent *) event;
139 keybuf = XLookupKeysym(xke, 0);
141 switch (keybuf) {
142 case XK_e: /* e */
143 return KEY_E;
144 case XK_Up: /* Up */
145 return KEY_UP;
146 case XK_Down: /* Down */
147 return KEY_DOWN;
148 default:
149 return KEY_NONE;
153 static void action(Widget w, XEvent *event, String *par, Cardinal *npar)
157 static void keyHook(Widget w, XtPointer client_data, String action_name,
158 XEvent *event, String *params, Cardinal *num_params)
160 Key_CBData *cbdata = (Key_CBData *) client_data;
162 if (strcmp(action_name, "action")) return;
164 /* In case if we have the same widget */
165 if (cbdata->key != toolkit_key_to_grace_key(event)) return;
166 if (cbdata->modifiers != toolkit_modifiers_to_grace_modifiers(event)) return;
168 if (w != cbdata->w) return;
170 cbdata->cbproc(cbdata->anydata);
173 extern XtAppContext app_con;
175 void AddWidgetKeyPressCB(Widget w, int key, Key_CBProc cbproc, void *anydata)
177 AddWidgetKeyPressCB2(w, NO_MODIFIER, key, cbproc, anydata);
180 void AddWidgetKeyPressCB2(Widget w, int modifiers, int key, Key_CBProc cbproc, void *anydata)
182 char *table = NULL;
183 XtActionsRec actions[1];
184 Key_CBData *cbdata;
186 cbdata = (Key_CBData *) xmalloc(sizeof(Key_CBData));
187 cbdata->w = w;
188 cbdata->modifiers = modifiers;
189 cbdata->key = key;
190 cbdata->cbproc = cbproc;
191 cbdata->anydata = anydata;
193 modifiers = modifiers ^ NO_MODIFIER;
195 if (modifiers & CONTROL_MODIFIER) {
196 table = copy_string(table, "Ctrl");
199 switch (key) {
200 case KEY_E:
201 table = concat_strings(table, "<Key>E: action()");
202 break;
203 case KEY_UP:
204 table = concat_strings(table, "<Key>osfUp: action()");
205 break;
206 case KEY_DOWN:
207 table = concat_strings(table, "<Key>osfDown: action()");
208 break;
209 default:
210 return;
213 actions[0].string = "action";
214 actions[0].proc = action;
216 XtOverrideTranslations(w, XtParseTranslationTable(table));
217 XtAppAddActions(app_con, actions, XtNumber(actions));
218 XtAppAddActionHook(app_con, keyHook, cbdata);
220 xfree(table);
223 static void widgetCB(Widget w, XtPointer client_data, XtPointer call_data)
225 Widget_CBData *cbdata = (Widget_CBData *) client_data;
227 cbdata->calldata = call_data;
229 cbdata->cbproc(cbdata);
232 void AddWidgetCB(Widget w, const char *callback, Widget_CBProc cbproc, void *anydata)
234 Widget_CBData *cbdata;
236 cbdata = (Widget_CBData *) xmalloc(sizeof(Widget_CBData));
237 cbdata->w = w;
238 cbdata->cbproc = cbproc;
239 cbdata->anydata = anydata;
241 if (!strcmp(callback, "valueChanged"))
242 XtAddCallback(w, XmNvalueChangedCallback, widgetCB, (XtPointer) cbdata);
244 if (!strcmp(callback, "activate"))
245 XtAddCallback(w, XmNactivateCallback, widgetCB, (XtPointer) cbdata);
247 if (!strcmp(callback, "modifyVerify"))
248 XtAddCallback(w, XmNmodifyVerifyCallback, widgetCB, (XtPointer) cbdata);
251 static char *label_to_resname(const char *s, const char *suffix)
253 char *retval, *rs;
254 int capitalize = FALSE;
256 retval = copy_string(NULL, s);
257 rs = retval;
258 while (*s) {
259 if (isalnum(*s)) {
260 if (capitalize == TRUE) {
261 *rs = toupper(*s);
262 capitalize = FALSE;
263 } else {
264 *rs = tolower(*s);
266 rs++;
267 } else {
268 capitalize = TRUE;
270 s++;
272 *rs = '\0';
273 if (suffix != NULL) {
274 retval = concat_strings(retval, suffix);
276 return retval;
279 /* Dialog */
280 Widget CreateDialog(Widget parent, const char *s)
282 Widget dialog, w;
283 char *bufp;
285 bufp = label_to_resname(s, "Dialog");
286 dialog = XmCreateDialogShell(parent, bufp, NULL, 0);
287 xfree(bufp);
289 handle_close(dialog);
291 bufp = copy_string(NULL, "Grace: ");
292 bufp = concat_strings(bufp, s);
293 XtVaSetValues(dialog,
294 XmNtitle, bufp,
295 NULL);
296 xfree(bufp);
298 w = CreateForm(dialog);
300 return w;
303 void DialogRaise(Widget form)
305 Widget w = XtParent(form);
307 WidgetManage(w);
308 XMapRaised(XtDisplay(w), XtWindow(w));
311 void DialogClose(Widget form)
313 WidgetUnmanage(XtParent(form));
316 void DialogSetResizable(Widget form, int onoff)
318 XtVaSetValues(form,
319 XmNresizePolicy, onoff ? XmRESIZE_ANY:XmRESIZE_NONE,
320 NULL);
321 XtVaSetValues(XtParent(form),
322 XmNallowShellResize, onoff ? True:False,
323 NULL);
326 /* File selection dialog */
327 static XmStringCharSet charset = XmFONTLIST_DEFAULT_TAG;
329 static char *GetStringSimple(XmString xms)
331 char *s;
333 if (XmStringGetLtoR(xms, charset, &s)) {
334 return s;
335 } else {
336 return NULL;
340 static void destroy_dialog(Widget w, XtPointer client_data, XtPointer call_data)
342 WidgetUnmanage((Widget) client_data);
345 static void fsb_setcwd_cb(Widget but, void *data)
347 char *bufp;
348 XmString directory;
349 Widget fsb = (Widget) data;
351 XtVaGetValues(fsb, XmNdirectory, &directory, NULL);
352 bufp = GetStringSimple(directory);
353 XmStringFree(directory);
354 if (bufp != NULL) {
355 set_workingdir(gapp, bufp);
356 XtFree(bufp);
360 #define FSB_CWD 0
361 #define FSB_HOME 1
362 #define FSB_ROOT 2
363 #define FSB_CYGDRV 3
365 static void fsb_cd_cb(OptionStructure *opt, int value, void *data)
367 char *bufp;
368 XmString dir, pattern, dirmask;
369 Widget FSB = (Widget) data;
371 switch (value) {
372 case FSB_CWD:
373 bufp = get_workingdir(gapp);
374 break;
375 case FSB_HOME:
376 bufp = grace_get_userhome(gapp->grace);
377 break;
378 case FSB_ROOT:
379 bufp = "/";
380 break;
381 case FSB_CYGDRV:
382 bufp = "/cygdrive/";
383 break;
384 default:
385 return;
388 XtVaGetValues(FSB, XmNpattern, &pattern, NULL);
390 dir = XmStringCreateLocalized(bufp);
391 dirmask = XmStringConcatAndFree(dir, pattern);
393 XmFileSelectionDoSearch(FSB, dirmask);
394 XmStringFree(dirmask);
397 static OptionItem fsb_items[] = {
398 {FSB_CWD, "Cwd"},
399 {FSB_HOME, "Home"},
400 {FSB_ROOT, "/"}
401 #ifdef __CYGWIN__
402 ,{FSB_CYGDRV, "My Computer"}
403 #endif
406 #define FSB_ITEMS_NUM sizeof(fsb_items)/sizeof(OptionItem)
408 #if XmVersion >= 2000
409 static void show_hidden_cb(Widget but, int onoff, void *data)
411 FSBStructure *fsb = (FSBStructure *) data;
412 XtVaSetValues(fsb->FSB, XmNfileFilterStyle,
413 onoff ? XmFILTER_NONE:XmFILTER_HIDDEN_FILES, NULL);
415 #endif
418 FSBStructure *CreateFileSelectionBox(Widget parent, char *s)
420 FSBStructure *retval;
421 OptionStructure *opt;
422 Widget fr, form, button;
423 XmString xmstr;
424 char *bufp, *resname;
426 retval = xmalloc(sizeof(FSBStructure));
427 resname = label_to_resname(s, "FSB");
428 retval->FSB = XmCreateFileSelectionDialog(parent, resname, NULL, 0);
429 xfree(resname);
430 retval->dialog = XtParent(retval->FSB);
431 handle_close(retval->dialog);
432 bufp = copy_string(NULL, "Grace: ");
433 bufp = concat_strings(bufp, s);
434 XtVaSetValues(retval->dialog, XmNtitle, bufp, NULL);
435 xfree(bufp);
437 xmstr = XmStringCreateLocalized(get_workingdir(gapp));
438 XtVaSetValues(retval->FSB, XmNdirectory, xmstr, NULL);
439 XmStringFree(xmstr);
441 XtAddCallback(retval->FSB,
442 XmNcancelCallback, destroy_dialog, retval->dialog);
443 AddHelpCB(retval->FSB, "doc/UsersGuide.html#FS-dialog");
445 retval->rc = XmCreateRowColumn(retval->FSB, "rc", NULL, 0);
446 #if XmVersion >= 2000
447 button = CreateToggleButton(retval->rc, "Show hidden files");
448 AddToggleButtonCB(button, show_hidden_cb, retval);
449 XtVaSetValues(retval->FSB, XmNfileFilterStyle, XmFILTER_HIDDEN_FILES, NULL);
450 #endif
451 fr = CreateFrame(retval->rc, NULL);
452 form = XtVaCreateWidget("form", xmFormWidgetClass, fr, NULL);
453 opt = CreateOptionChoice(form, "Chdir to:", 1, FSB_ITEMS_NUM, fsb_items);
454 AddOptionChoiceCB(opt, fsb_cd_cb, (void *) retval->FSB);
455 button = CreateButton(form, "Set as cwd");
456 AddButtonCB(button, fsb_setcwd_cb, (void *) retval->FSB);
458 XtVaSetValues(opt->menu,
459 XmNleftAttachment, XmATTACH_FORM,
460 XmNtopAttachment, XmATTACH_FORM,
461 XmNbottomAttachment, XmATTACH_FORM,
462 XmNrightAttachment, XmATTACH_NONE,
463 NULL);
464 XtVaSetValues(button,
465 XmNleftAttachment, XmATTACH_NONE,
466 XmNtopAttachment, XmATTACH_FORM,
467 XmNbottomAttachment, XmATTACH_FORM,
468 XmNrightAttachment, XmATTACH_FORM,
469 NULL);
470 WidgetManage(form);
472 WidgetManage(retval->rc);
474 AddMouseWheelSupport(XmFileSelectionBoxGetChild(retval->FSB,
475 XmDIALOG_LIST));
476 AddMouseWheelSupport(XmFileSelectionBoxGetChild(retval->FSB,
477 XmDIALOG_DIR_LIST));
479 return retval;
482 typedef struct {
483 FSBStructure *fsb;
484 FSB_CBProc cbproc;
485 void *anydata;
486 } FSB_CBdata;
488 static void fsb_int_cb_proc(Widget w, XtPointer client_data, XtPointer call_data)
490 char *s;
491 int ok;
493 FSB_CBdata *cbdata = (FSB_CBdata *) client_data;
494 XmFileSelectionBoxCallbackStruct *cbs =
495 (XmFileSelectionBoxCallbackStruct *) call_data;
497 s = GetStringSimple(cbs->value);
498 if (s == NULL) {
499 errmsg("Error converting XmString to char string");
500 return;
503 set_wait_cursor();
505 ok = cbdata->cbproc(cbdata->fsb, s, cbdata->anydata);
506 XtFree(s);
507 if (ok) {
508 WidgetUnmanage(cbdata->fsb->dialog);
510 unset_wait_cursor();
513 void AddFileSelectionBoxCB(FSBStructure *fsb, FSB_CBProc cbproc, void *anydata)
515 FSB_CBdata *cbdata;
517 cbdata = xmalloc(sizeof(FSB_CBdata));
518 cbdata->fsb = fsb;
519 cbdata->cbproc = (FSB_CBProc) cbproc;
520 cbdata->anydata = anydata;
521 XtAddCallback(fsb->FSB,
522 XmNokCallback, fsb_int_cb_proc, (XtPointer) cbdata);
525 void SetFileSelectionBoxPattern(FSBStructure *fsb, char *pattern)
527 XmString xmstr;
529 if (pattern != NULL) {
530 xmstr = XmStringCreateLocalized(pattern);
531 XtVaSetValues(fsb->FSB, XmNpattern, xmstr, NULL);
532 XmStringFree(xmstr);
536 /* Containers */
537 Widget CreateVContainer(Widget parent)
539 Widget rc;
541 rc = XmCreateRowColumn(parent, "VContainer", NULL, 0);
542 WidgetManage(rc);
544 return rc;
547 Widget CreateHContainer(Widget parent)
549 Widget rc;
551 rc = XmCreateRowColumn(parent, "HContainer", NULL, 0);
552 XtVaSetValues(rc, XmNorientation, XmHORIZONTAL, NULL);
553 WidgetManage(rc);
555 return rc;
558 /* Form */
559 Widget CreateForm(Widget parent)
561 Widget w;
563 w = XmCreateForm(parent, "form", NULL, 0);
565 return w;
568 void FormAddHChild(Widget form, Widget child)
570 Widget last_widget;
572 last_widget = WidgetGetUserData(form);
573 if (last_widget) {
574 XtVaSetValues(child,
575 XmNleftAttachment, XmATTACH_WIDGET,
576 XmNleftWidget, last_widget,
577 NULL);
578 XtVaSetValues(last_widget,
579 XmNrightAttachment, XmATTACH_NONE,
580 NULL);
581 } else {
582 XtVaSetValues(child,
583 XmNleftAttachment, XmATTACH_FORM,
584 NULL);
586 XtVaSetValues(child,
587 XmNtopAttachment, XmATTACH_FORM,
588 XmNbottomAttachment, XmATTACH_FORM,
589 XmNrightAttachment, XmATTACH_FORM,
590 NULL);
591 WidgetSetUserData(form, child);
594 void FormAddVChild(Widget form, Widget child)
596 Widget last_widget;
598 if (XtIsSubclass(child, listtreeWidgetClass) ||
599 (XmIsText(child) && XmIsScrolledWindow(XtParent(child)))) {
600 child = XtParent(child);
603 last_widget = WidgetGetUserData(form);
604 if (last_widget) {
605 XtVaSetValues(child,
606 XmNtopAttachment, XmATTACH_WIDGET,
607 XmNtopWidget, last_widget,
608 NULL);
609 XtVaSetValues(last_widget,
610 XmNbottomAttachment, XmATTACH_NONE,
611 NULL);
612 } else {
613 XtVaSetValues(child,
614 XmNtopAttachment, XmATTACH_FORM,
615 NULL);
617 XtVaSetValues(child,
618 XmNleftAttachment, XmATTACH_FORM,
619 XmNrightAttachment, XmATTACH_FORM,
620 XmNbottomAttachment, XmATTACH_FORM,
621 NULL);
622 WidgetSetUserData(form, child);
625 void FormFixateVChild(Widget w)
627 Widget prev;
628 XtVaGetValues(w, XmNtopWidget, &prev, NULL);
629 XtVaSetValues(w, XmNtopAttachment, XmATTACH_NONE, NULL);
630 XtVaSetValues(prev, XmNbottomAttachment, XmATTACH_WIDGET,
631 XmNbottomWidget, w,
632 NULL);
635 /* Label */
636 Widget CreateLabel(Widget parent, char *s)
638 Widget label;
640 label = XtVaCreateManagedWidget("label",
641 xmLabelWidgetClass, parent,
642 XmNalignment, XmALIGNMENT_BEGINNING,
643 XmNrecomputeSize, True,
644 NULL);
646 LabelSetString(label, s);
648 return label;
651 void LabelSetString(Widget w, char *s)
653 XmString str;
655 str = XmStringCreateLocalized(s);
656 XtVaSetValues(w, XmNlabelString, str, NULL);
657 XmStringFree(str);
661 void LabelSetPixmap(Widget w, int width, int height, const unsigned char *bits)
663 Pixmap pm;
665 X11Stuff *xstuff = gapp->gui->xstuff;
666 Pixel fg, bg;
668 XtVaGetValues(w,
669 XmNforeground, &fg,
670 XmNbackground, &bg,
671 NULL);
673 pm = XCreatePixmapFromBitmapData(xstuff->disp,
674 xstuff->root, (char *) bits, width, height, fg, bg, xstuff->depth);
676 XtVaSetValues(w,
677 XmNlabelType, XmPIXMAP,
678 XmNlabelPixmap, pm,
679 NULL);
682 /* Text */
683 Widget CreateLineTextEdit(Widget parent, int len)
685 Widget w;
687 w = XtVaCreateManagedWidget("text", xmTextWidgetClass, parent,
688 XmNtraversalOn, True,
689 NULL);
690 if (len > 0) {
691 XtVaSetValues(w, XmNcolumns, len, NULL);
694 return w;
697 Widget CreateMultiLineTextEdit(Widget parent, int nrows)
699 Widget w;
700 Arg args[3];
701 int ac;
703 ac = 0;
704 if (nrows > 0) {
705 XtSetArg(args[ac], XmNrows, nrows); ac++;
707 XtSetArg(args[ac], XmNeditMode, XmMULTI_LINE_EDIT); ac++;
708 XtSetArg(args[ac], XmNvisualPolicy, XmVARIABLE); ac++;
710 w = XmCreateScrolledText(parent, "text", args, ac);
711 WidgetManage(w);
713 return w;
716 void TextSetLength(TextStructure *cst, int len)
718 XtVaSetValues(cst->text, XmNcolumns, len, NULL);
721 char *TextGetString(TextStructure *cst)
723 char *s, *buf;
725 s = XmTextGetString(cst->text);
726 buf = copy_string(NULL, s);
727 XtFree(s);
729 return buf;
732 void TextSetString(TextStructure *cst, char *s)
734 cst->locked = TRUE;
735 XmTextSetString(cst->text, s ? s : "");
736 XmTextSetInsertionPosition(cst->text, s ? strlen(s):0);
737 cst->locked = FALSE;
740 typedef struct {
741 TextStructure *cst;
742 TextValidate_CBProc cbproc;
743 void *anydata;
744 } TextValidate_CBData;
746 static void text_int_validate_cb_proc(Widget_CBData *wcbdata)
748 XmTextBlock text;
749 TextValidate_CBData *cbdata = (TextValidate_CBData *) wcbdata->anydata;
750 XmTextVerifyCallbackStruct *tcbs =
751 (XmTextVerifyCallbackStruct *) wcbdata->calldata;
753 if (cbdata->cst->locked) return;
755 text = tcbs->text;
757 if (!cbdata->cbproc(&text->ptr, &text->length, cbdata->anydata)) {
758 tcbs->doit = False;
762 void AddTextValidateCB(TextStructure *cst, TextValidate_CBProc cbproc, void *anydata)
764 TextValidate_CBData *cbdata;
766 cbdata = (TextValidate_CBData *) xmalloc(sizeof(TextValidate_CBData));
767 cbdata->cst = cst;
768 cbdata->cbproc = cbproc;
769 cbdata->anydata = anydata;
770 cst->locked = FALSE;
772 AddWidgetCB(cst->text, "modifyVerify", text_int_validate_cb_proc, cbdata);
775 int TextGetCursorPos(TextStructure *cst)
777 return XmTextGetInsertionPosition(cst->text);
780 void TextSetCursorPos(TextStructure *cst, int pos)
782 XmTextSetInsertionPosition(cst->text, pos);
785 int TextGetLastPosition(TextStructure *cst)
787 return XmTextGetLastPosition(cst->text);
790 void TextInsert(TextStructure *cst, int pos, char *s)
792 XmTextInsert(cst->text, pos, s);
795 void TextSetEditable(TextStructure *cst, int onoff)
797 XtVaSetValues(cst->text, XmNeditable, onoff? True:False, NULL);
800 /* Tab */
801 Widget CreateTab(Widget parent)
803 Widget tab;
805 tab = XtVaCreateManagedWidget("tab", xmTabWidgetClass, parent, NULL);
807 return tab;
810 Widget CreateTabPage(Widget parent, char *s)
812 Widget w;
813 XmString str;
815 w = CreateVContainer(parent);
816 str = XmStringCreateLocalized(s);
817 XtVaSetValues(w, XmNtabLabel, str, NULL);
818 XmStringFree(str);
820 return w;
823 void SelectTabPage(Widget tab, Widget w)
825 XmTabSetTabWidget(tab, w, True);
828 /* Button */
829 Widget CreateButton(Widget parent, char *label)
831 Widget button;
833 button = XtVaCreateManagedWidget(label,
834 xmPushButtonWidgetClass, parent,
835 NULL);
837 XtVaSetValues(button,
838 XmNalignment, XmALIGNMENT_CENTER,
839 NULL);
841 return button;
844 Widget CreateBitmapButton(Widget parent,
845 int width, int height, const unsigned char *bits)
847 Widget button;
849 button = XtVaCreateWidget("button",
850 xmPushButtonWidgetClass, parent,
851 NULL);
852 LabelSetPixmap(button, width, height, bits);
853 WidgetManage(button);
855 return button;
858 /* ToggleButton */
859 Widget CreateToggleButton(Widget parent, char *s)
861 return (XtVaCreateManagedWidget(s, xmToggleButtonWidgetClass, parent, NULL));
864 int GetToggleButtonState(Widget w)
866 if (!w) {
867 errmsg("Internal error: GetToggleButtonState() called with NULL widget");
868 return 0;
869 } else {
870 return XmToggleButtonGetState(w);
874 void SetToggleButtonState(Widget w, int value)
876 if (w == NULL) {
877 return;
879 XmToggleButtonSetState(w, value ? True:False, False);
881 return;
884 /* Grid */
885 typedef struct {
886 int ncols;
887 int nrows;
888 } GridData;
890 Widget CreateGrid(Widget parent, int ncols, int nrows)
892 Widget w;
893 int nfractions;
894 GridData *gd;
896 if (ncols <= 0 || nrows <= 0) {
897 errmsg("Wrong call to CreateGrid()");
898 ncols = 1;
899 nrows = 1;
902 nfractions = 0;
903 do {
904 nfractions++;
905 } while (nfractions % ncols || nfractions % nrows);
907 gd = xmalloc(sizeof(GridData));
908 gd->ncols = ncols;
909 gd->nrows = nrows;
911 w = CreateForm(parent);
913 XtVaSetValues(w,
914 XmNfractionBase, nfractions,
915 XmNuserData, gd,
916 NULL);
918 WidgetManage(w);
920 return w;
923 void PlaceGridChild(Widget grid, Widget w, int col, int row)
925 int nfractions, w1, h1;
926 GridData *gd;
928 XtVaGetValues(grid,
929 XmNfractionBase, &nfractions,
930 XmNuserData, &gd,
931 NULL);
933 if (gd == NULL) {
934 /* errmsg("PlaceGridChild() called with a non-grid widget"); */
935 return;
937 if (col < 0 || col >= gd->ncols) {
938 errmsg("PlaceGridChild() called with wrong `col' argument");
939 return;
941 if (row < 0 || row >= gd->nrows) {
942 errmsg("PlaceGridChild() called with wrong `row' argument");
943 return;
946 w1 = nfractions/gd->ncols;
947 h1 = nfractions/gd->nrows;
949 XtVaSetValues(w,
950 XmNleftAttachment , XmATTACH_POSITION,
951 XmNleftPosition , col*w1 ,
952 XmNrightAttachment , XmATTACH_POSITION,
953 XmNrightPosition , (col + 1)*w1 ,
954 XmNtopAttachment , XmATTACH_POSITION,
955 XmNtopPosition , row*h1 ,
956 XmNbottomAttachment, XmATTACH_POSITION,
957 XmNbottomPosition , (row + 1)*h1 ,
958 NULL);
961 /* OptionChoice */
962 #define MAX_PULLDOWN_LENGTH 30
964 OptionStructure *CreateOptionChoice(Widget parent, char *labelstr,
965 int ncols, int nchoices, OptionItem *items)
967 Arg args[2];
968 XmString str;
969 OptionStructure *retval;
971 retval = xcalloc(1, sizeof(OptionStructure));
972 if (!retval) {
973 return NULL;
976 XtSetArg(args[0], XmNpacking, XmPACK_COLUMN);
977 retval->pulldown = XmCreatePulldownMenu(parent, "pulldownMenu", args, 1);
979 retval->ncols = ncols;
981 UpdateOptionChoice(retval, nchoices, items);
983 str = XmStringCreateLocalized(labelstr);
984 XtSetArg(args[0], XmNlabelString, str);
985 XtSetArg(args[1], XmNsubMenuId, retval->pulldown);
987 retval->menu = XmCreateOptionMenu(parent, "optionMenu", args, 2);
989 XmStringFree(str);
991 WidgetManage(retval->menu);
993 return retval;
996 OptionStructure *CreateOptionChoiceVA(Widget parent, char *labelstr, ...)
998 OptionStructure *retval;
999 int nchoices = 0;
1000 OptionItem *oi = NULL;
1001 va_list var;
1002 char *s;
1003 int value;
1005 va_start(var, labelstr);
1006 while ((s = va_arg(var, char *)) != NULL) {
1007 value = va_arg(var, int);
1008 nchoices++;
1009 oi = xrealloc(oi, nchoices*sizeof(OptionItem));
1010 oi[nchoices - 1].value = value;
1011 oi[nchoices - 1].label = copy_string(NULL, s);
1013 va_end(var);
1015 retval = CreateOptionChoice(parent, labelstr, 1, nchoices, oi);
1017 while (nchoices) {
1018 nchoices--;
1019 xfree(oi[nchoices].label);
1021 xfree(oi);
1023 return retval;
1026 static void oc_int_cb_proc(Widget_CBData *wcbdata)
1028 int value;
1030 OC_CBdata *cbdata = (OC_CBdata *) wcbdata->anydata;
1032 value = GetOptionChoice(cbdata->opt);
1033 cbdata->cbproc(cbdata->opt, value, cbdata->anydata);
1036 void AddOptionChoiceCB(OptionStructure *opt, OC_CBProc cbproc, void *anydata)
1038 OC_CBdata *cbdata;
1039 unsigned int i;
1041 cbdata = xmalloc(sizeof(OC_CBdata));
1043 cbdata->opt = opt;
1044 cbdata->cbproc = cbproc;
1045 cbdata->anydata = anydata;
1047 opt->cblist = xrealloc(opt->cblist, (opt->cbnum + 1)*sizeof(OC_CBdata *));
1048 opt->cblist[opt->cbnum] = cbdata;
1049 opt->cbnum++;
1051 for (i = 0; i < opt->nchoices; i++) {
1052 AddWidgetCB(opt->options[i].widget, "activate", oc_int_cb_proc, cbdata);
1056 void UpdateOptionChoice(OptionStructure *optp, int nchoices, OptionItem *items)
1058 int i, nold, ncols, nw;
1059 Widget *wlist;
1061 nold = optp->nchoices;
1063 if (optp->ncols == 0) {
1064 ncols = 1;
1065 } else {
1066 ncols = optp->ncols;
1069 /* Don't create too tall pulldowns */
1070 if (nchoices > MAX_PULLDOWN_LENGTH*ncols) {
1071 ncols = (nchoices + MAX_PULLDOWN_LENGTH - 1)/MAX_PULLDOWN_LENGTH;
1074 XtVaSetValues(optp->pulldown, XmNnumColumns, ncols, NULL);
1076 nw = nold - nchoices;
1077 if (nw > 0) {
1078 /* Unmanage extra items before destroying to speed the things up */
1079 wlist = xmalloc(nw*sizeof(Widget));
1080 for (i = nchoices; i < nold; i++) {
1081 wlist[i - nchoices] = optp->options[i].widget;
1083 XtUnmanageChildren(wlist, nw);
1084 xfree(wlist);
1086 for (i = nchoices; i < nold; i++) {
1087 XtDestroyWidget(optp->options[i].widget);
1091 optp->options = xrealloc(optp->options, nchoices*sizeof(OptionWidgetItem));
1092 optp->nchoices = nchoices;
1094 for (i = nold; i < nchoices; i++) {
1095 unsigned int j;
1096 optp->options[i].widget = CreateButton(optp->pulldown, "");
1097 for (j = 0; j < optp->cbnum; j++) {
1098 OC_CBdata *cbdata = optp->cblist[j];
1099 AddWidgetCB(optp->options[i].widget, "activate", oc_int_cb_proc, cbdata);
1103 for (i = 0; i < nchoices; i++) {
1104 optp->options[i].value = items[i].value;
1105 if (items[i].label != NULL) {
1106 XmString str, ostr;
1107 XtVaGetValues(optp->options[i].widget, XmNlabelString, &ostr, NULL);
1108 str = XmStringCreateLocalized(items[i].label);
1109 if (XmStringCompare(str, ostr) != True) {
1110 XtVaSetValues(optp->options[i].widget, XmNlabelString, str, NULL);
1112 XmStringFree(str);
1116 nw = nchoices - nold;
1117 if (nw > 0) {
1118 wlist = xmalloc(nw*sizeof(Widget));
1119 for (i = nold; i < nchoices; i++) {
1120 wlist[i - nold] = optp->options[i].widget;
1122 XtManageChildren(wlist, nw);
1123 xfree(wlist);
1127 /* Menu */
1128 Widget CreatePopupMenu(Widget parent)
1130 return XmCreatePopupMenu(parent, "popupMenu", NULL, 0);
1133 Widget CreateMenuBar(Widget parent)
1135 Widget menubar;
1137 menubar = XmCreateMenuBar(parent, "menuBar", NULL, 0);
1138 return menubar;
1141 Widget CreateMenu(Widget parent, char *label, char mnemonic, int help)
1143 Widget menupane, cascade;
1144 char ms[2];
1146 menupane = XmCreatePulldownMenu(parent, "menu", NULL, 0);
1148 ms[0] = mnemonic;
1149 ms[1] = '\0';
1151 cascade = XtVaCreateManagedWidget("cascade",
1152 xmCascadeButtonGadgetClass, parent,
1153 XmNsubMenuId, menupane,
1154 XmNmnemonic, XStringToKeysym(ms),
1155 NULL);
1157 LabelSetString(cascade, label);
1159 if (help) {
1160 XtVaSetValues(parent, XmNmenuHelpWidget, cascade, NULL);
1161 CreateMenuButton(menupane, "On context", 'x',
1162 ContextHelpCB, NULL);
1163 CreateSeparator(menupane);
1166 return menupane;
1169 Widget CreateMenuButton(Widget parent, char *label, char mnemonic,
1170 Button_CBProc cb, void *data)
1172 return CreateMenuButtonA(parent, label, mnemonic, NULL, NULL, cb, data);
1175 Widget CreateMenuButtonA(Widget parent, char *label, char mnemonic,
1176 char *accelerator, char* acceleratorText, Button_CBProc cb, void *data)
1178 Widget button;
1179 XmString str;
1180 char *name, ms[2];
1182 ms[0] = mnemonic;
1183 ms[1] = '\0';
1185 name = label_to_resname(label, "Button");
1187 button = CreateButton(parent, name);
1188 xfree(name);
1190 XtVaSetValues(button,
1191 XmNmnemonic, XStringToKeysym(ms),
1192 XmNalignment, XmALIGNMENT_BEGINNING,
1193 NULL);
1195 if (accelerator && acceleratorText) {
1196 str = XmStringCreateLocalized(acceleratorText);
1197 XtVaSetValues(button,
1198 XmNaccelerator, accelerator,
1199 XmNacceleratorText, str,
1200 NULL);
1201 XmStringFree(str);
1204 LabelSetString(button, label);
1206 AddButtonCB(button, cb, data);
1208 return button;
1211 Widget CreateMenuHelpButton(Widget parent, char *label, char mnemonic,
1212 Widget form, char *ha)
1214 Widget wbut;
1216 wbut = CreateMenuButton(parent, label, mnemonic, HelpCB, ha);
1217 AddHelpCB(form, ha);
1219 return wbut;
1222 Widget CreateMenuToggle(Widget parent, char *label, char mnemonic,
1223 TB_CBProc cb, void *data)
1225 Widget button;
1226 char *name, ms[2];
1228 ms[0] = mnemonic;
1229 ms[1] = '\0';
1231 name = label_to_resname(label, NULL);
1232 button = CreateToggleButton(parent, name);
1233 xfree(name);
1235 XtVaSetValues(button,
1236 XmNmnemonic, XStringToKeysym(ms),
1237 XmNvisibleWhenOff, True,
1238 XmNindicatorOn, True,
1239 NULL);
1241 LabelSetString(button, label);
1243 if (cb) {
1244 AddToggleButtonCB(button, cb, data);
1247 return button;