Reimplemented CreateCharOptionChoice
[grace.git] / src / motif.c
blob1b230b52f0b13b503b89287ec565e22da2590476
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"
33 #include "utils.h"
35 #include <ctype.h>
36 #include <stdarg.h>
37 #include <Xm/Xm.h>
38 #include <Xm/ArrowBG.h>
39 #include <Xm/CascadeBG.h>
40 #include <Xm/DialogS.h>
41 #include <Xm/FileSB.h>
42 #include <Xm/Form.h>
43 #include <Xm/Frame.h>
44 #include <Xm/Label.h>
45 #include <Xm/LabelG.h>
46 #include <Xbae/Matrix.h>
48 #if XmVersion >= 2000
49 # define USE_PANEDW 1
50 # include <Xm/PanedW.h>
51 #else
52 # define USE_PANEDW 0
53 #endif
55 #include <Xm/PushB.h>
56 #include <Xm/RowColumn.h>
57 #include <Xm/Separator.h>
58 #include <Xm/Scale.h>
59 #include <Xm/ScrolledW.h>
60 #include <Xm/Text.h>
61 #include <Xm/ToggleB.h>
62 #include "Tab.h"
63 #include "ListTree.h"
65 #include "globals.h"
67 extern XtAppContext app_con;
69 /* Timer */
70 Timer_CBdata *CreateTimer(unsigned long interval, Timer_CBProc cbproc, void *anydata)
72 Timer_CBdata *cbdata;
74 cbdata = xmalloc(sizeof(Timer_CBdata));
76 cbdata->timer_id = 0;
77 cbdata->interval = interval;
78 cbdata->cbproc = cbproc;
79 cbdata->anydata = anydata;
81 return cbdata;
84 static void timer_proc(XtPointer client_data, XtIntervalId *id)
86 Timer_CBdata *cbdata = (Timer_CBdata *) client_data;
88 cbdata->cbproc(cbdata->anydata);
89 cbdata->timer_id = 0;
92 void TimerStart(Timer_CBdata *cbdata)
94 /* we count elapsed time since the last event, so first remove
95 an existing timeout, if there is one */
96 if (cbdata->timer_id) {
97 XtRemoveTimeOut(cbdata->timer_id);
100 cbdata->timer_id = XtAppAddTimeOut(app_con, cbdata->interval, timer_proc, cbdata);
103 /* Widgets */
104 void WidgetManage(Widget w)
106 XtManageChild(w);
109 void WidgetUnmanage(Widget w)
111 XtUnmanageChild(w);
114 int WidgetIsManaged(Widget w)
116 return (XtIsManaged(w) == True) ? TRUE:FALSE;
119 void *WidgetGetUserData(Widget w)
121 void *udata = NULL;
122 XtVaGetValues(w, XmNuserData, &udata, NULL);
124 return udata;
127 void WidgetSetUserData(Widget w, void *udata)
129 XtVaSetValues(w, XmNuserData, udata, NULL);
132 void WidgetSetSensitive(Widget w, int onoff)
134 XtSetSensitive(w, onoff ? True : False);
137 void WidgetSetFocus(Widget w)
139 XmProcessTraversal(w, XmTRAVERSE_CURRENT);
142 void WidgetSetWidth(Widget w, unsigned int width)
144 XtVaSetValues(w, XmNwidth, (Dimension) width, NULL);
147 void WidgetSetHeight(Widget w, unsigned int height)
149 XtVaSetValues(w, XmNheight, (Dimension) height, NULL);
152 void WidgetSetSize(Widget w, unsigned int width, unsigned int height)
154 XtVaSetValues(w,
155 XmNwidth, (Dimension) width,
156 XmNheight, (Dimension) height,
157 NULL);
160 void WidgetGetSize(Widget w, unsigned int *width, unsigned int *height)
162 Dimension ww, wh;
164 XtVaGetValues(w,
165 XmNwidth, &ww,
166 XmNheight, &wh,
167 NULL);
169 *width = (unsigned int) ww;
170 *height = (unsigned int) wh;
173 static int toolkit_modifiers_to_grace_modifiers(void *event)
175 XEvent *e = (XEvent *) event;
176 unsigned int state;
177 int modifiers = NO_MODIFIER;
179 switch (e->type) {
180 case ButtonPress:
181 case ButtonRelease:
182 state = e->xbutton.state;
183 break;
184 case KeyPress:
185 case KeyRelease:
186 state = e->xkey.state;
187 break;
188 default:
189 return modifiers;
192 if (state & ControlMask) {
193 modifiers = modifiers ^ CONTROL_MODIFIER;
196 if (state & ShiftMask) {
197 modifiers = modifiers ^ SHIFT_MODIFIER;
200 return modifiers;
203 static int toolkit_key_to_grace_key(void *event)
205 XKeyEvent *xke = (XKeyEvent *) event;
206 KeySym keybuf;
208 keybuf = XLookupKeysym(xke, 0);
210 switch (keybuf) {
211 case XK_e: /* e */
212 return KEY_E;
213 case XK_Up: /* Up */
214 return KEY_UP;
215 case XK_Down: /* Down */
216 return KEY_DOWN;
217 default:
218 return KEY_NONE;
222 static int toolkit_button_to_grace_button(void *event)
224 XButtonEvent *xbe = (XButtonEvent *) event;
226 switch (xbe->button) {
227 case Button4:
228 return WHEEL_UP_BUTTON;
229 case Button5:
230 return WHEEL_DOWN_BUTTON;
231 default:
232 return NO_BUTTON;
236 static int toolkit_to_grace(void *event)
238 XEvent *e = (XEvent *) event;
240 switch (e->type) {
241 case ButtonPress:
242 case ButtonRelease:
243 return toolkit_button_to_grace_button(event);
244 case KeyPress:
245 case KeyRelease:
246 return toolkit_key_to_grace_key(event);
247 default:
248 return KEY_NONE;
252 static void action(Widget w, XEvent *event, String *par, Cardinal *npar)
256 static void keyHook(Widget w, XtPointer client_data, String action_name,
257 XEvent *event, String *params, Cardinal *num_params)
259 Key_CBData *cbdata = (Key_CBData *) client_data;
261 if (strcmp(action_name, "action")) return;
263 /* In case if we have the same widget */
264 if (cbdata->key != toolkit_to_grace(event)) return;
265 if (cbdata->modifiers != toolkit_modifiers_to_grace_modifiers(event)) return;
267 if (w != cbdata->w) return;
269 cbdata->cbproc(cbdata->anydata);
272 void AddWidgetKeyPressCB(Widget w, int key, Key_CBProc cbproc, void *anydata)
274 AddWidgetKeyPressCB2(w, NO_MODIFIER, key, cbproc, anydata);
277 void AddWidgetKeyPressCB2(Widget w, int modifiers, int key, Key_CBProc cbproc, void *anydata)
279 char *table = NULL;
280 XtActionsRec actions[1];
281 Key_CBData *cbdata;
283 cbdata = (Key_CBData *) xmalloc(sizeof(Key_CBData));
284 cbdata->w = w;
285 cbdata->modifiers = modifiers;
286 cbdata->key = key;
287 cbdata->cbproc = cbproc;
288 cbdata->anydata = anydata;
290 modifiers = modifiers ^ NO_MODIFIER;
292 if (modifiers & CONTROL_MODIFIER) {
293 table = copy_string(table, "Ctrl");
296 switch (key) {
297 case KEY_E:
298 table = concat_strings(table, "<Key>E: action()");
299 break;
300 case KEY_UP:
301 table = concat_strings(table, "<Key>osfUp: action()");
302 break;
303 case KEY_DOWN:
304 table = concat_strings(table, "<Key>osfDown: action()");
305 break;
306 default:
307 return;
310 actions[0].string = "action";
311 actions[0].proc = action;
313 XtOverrideTranslations(w, XtParseTranslationTable(table));
314 XtAppAddActions(app_con, actions, XtNumber(actions));
315 XtAppAddActionHook(app_con, keyHook, cbdata);
317 xfree(table);
320 void AddWidgetButtonPressCB(Widget w, int button, Key_CBProc cbproc, void *anydata)
322 char *table = NULL;
323 XtActionsRec actions[1];
324 Key_CBData *cbdata;
326 cbdata = (Key_CBData *) xmalloc(sizeof(Key_CBData));
327 cbdata->w = w;
328 cbdata->modifiers = NO_MODIFIER;
329 cbdata->key = button;
330 cbdata->cbproc = cbproc;
331 cbdata->anydata = anydata;
333 switch (button) {
334 case WHEEL_UP_BUTTON:
335 table = concat_strings(table, "<Btn4Down>: action()");
336 break;
337 case WHEEL_DOWN_BUTTON:
338 table = concat_strings(table, "<Btn5Down>: action()");
339 break;
340 default:
341 return;
344 actions[0].string = "action";
345 actions[0].proc = action;
347 XtOverrideTranslations(w, XtParseTranslationTable(table));
348 XtAppAddActions(app_con, actions, XtNumber(actions));
349 XtAppAddActionHook(app_con, keyHook, cbdata);
351 xfree(table);
354 static XmStringCharSet charset = XmFONTLIST_DEFAULT_TAG;
355 static char *GetStringSimple(XmString xms)
357 char *s;
359 if (XmStringGetLtoR(xms, charset, &s)) {
360 return s;
361 } else {
362 return NULL;
366 static void widgetCB(Widget w, XtPointer client_data, XtPointer call_data)
368 Widget_CBData *cbdata = (Widget_CBData *) client_data;
369 TextValidate_CD *cdata;
370 XmTextVerifyCallbackStruct *tcbs;
371 XmTextBlock text;
372 char *str = NULL;
373 int is_fsb = XmIsFileSelectionBox(w);
374 int is_text = XmIsText(w);
376 if (is_fsb) {
377 XmFileSelectionBoxCallbackStruct *cbs =
378 (XmFileSelectionBoxCallbackStruct *) call_data;
380 char *buf = GetStringSimple(cbs->value);
382 if (buf == NULL) {
383 errmsg("Error converting XmString to char string");
384 return;
387 str = copy_string(NULL, buf);
388 XtFree(buf);
390 cbdata->calldata = str;
391 } else if (is_text) {
392 tcbs = (XmTextVerifyCallbackStruct *) call_data;
394 text = tcbs->text;
396 cdata = (TextValidate_CD *) xmalloc(sizeof(TextValidate_CD));
397 cdata->text = &text->ptr;
398 cdata->allow_change = TRUE;
400 cbdata->calldata = cdata;
401 } else {
402 cbdata->calldata = call_data;
405 cbdata->cbproc(cbdata);
407 if (is_fsb) {
408 xfree(str);
409 } else if (is_text) {
411 text->length = strlen(text->ptr);
413 if (!cdata->allow_change) {
414 tcbs->doit = False;
417 xfree(cdata);
421 void AddWidgetCB(Widget w, const char *callback, Widget_CBProc cbproc, void *anydata)
423 char *cb;
424 Widget_CBData *cbdata;
426 cbdata = (Widget_CBData *) xmalloc(sizeof(Widget_CBData));
427 cbdata->w = w;
428 cbdata->cbproc = cbproc;
429 cbdata->anydata = anydata;
431 cb = copy_string(NULL, callback);
432 cb = concat_strings(cb, "Callback");
434 XtAddCallback(w, cb, widgetCB, (XtPointer) cbdata);
436 xfree(cb);
439 static char *label_to_resname(const char *s, const char *suffix)
441 char *retval, *rs;
442 int capitalize = FALSE;
444 retval = copy_string(NULL, s);
445 rs = retval;
446 while (*s) {
447 if (isalnum(*s)) {
448 if (capitalize == TRUE) {
449 *rs = toupper(*s);
450 capitalize = FALSE;
451 } else {
452 *rs = tolower(*s);
454 rs++;
455 } else {
456 capitalize = TRUE;
458 s++;
460 *rs = '\0';
461 if (suffix != NULL) {
462 retval = concat_strings(retval, suffix);
464 return retval;
467 /* Dialog Window */
468 static void close_dialogCB(Widget_CBData *wcbdata)
470 WidgetUnmanage(wcbdata->anydata);
473 Widget CreateDialogWindow(Widget parent, const char *s)
475 Widget dialog;
476 char *bufp;
478 bufp = label_to_resname(s, "Dialog");
479 dialog = XmCreateDialogShell(parent, bufp, NULL, 0);
480 xfree(bufp);
482 AddWindowCloseCB(dialog, close_dialogCB, dialog);
484 bufp = copy_string(NULL, "Grace: ");
485 bufp = concat_strings(bufp, s);
486 XtVaSetValues(dialog, XmNtitle, bufp, NULL);
487 xfree(bufp);
489 return dialog;
492 /* Dialog */
493 Widget CreateDialog(Widget parent, const char *s)
495 Widget w;
497 w = CreateDialogWindow(parent, s);
498 w = CreateForm(w);
500 return w;
503 void DialogRaise(Widget form)
505 Widget w = XtParent(form);
507 WidgetManage(w);
508 XMapRaised(XtDisplay(w), XtWindow(w));
511 void DialogClose(Widget form)
513 WidgetUnmanage(XtParent(form));
516 void DialogSetResizable(Widget form, int onoff)
518 XtVaSetValues(form,
519 XmNresizePolicy, onoff ? XmRESIZE_ANY:XmRESIZE_NONE,
520 NULL);
521 XtVaSetValues(XtParent(form),
522 XmNallowShellResize, onoff ? True:False,
523 NULL);
526 /* File selection box */
527 Widget CreateFileSelectionBox(Widget parent)
529 Widget w;
531 w = XmCreateFileSelectionBox(parent, "FSB", NULL, 0);
533 AddMouseWheelSupport(XmFileSelectionBoxGetChild(w, XmDIALOG_LIST));
534 AddMouseWheelSupport(XmFileSelectionBoxGetChild(w, XmDIALOG_DIR_LIST));
536 return w;
539 /* File selection filter */
540 #if XmVersion >= 2000
541 static void show_hidden_cb(Widget but, int onoff, void *data)
543 Widget fsb = (Widget) data;
544 XtVaSetValues(fsb, XmNfileFilterStyle,
545 onoff ? XmFILTER_NONE:XmFILTER_HIDDEN_FILES, NULL);
547 #endif
549 void CreateFileSelectionFilter(Widget parent, Widget fsb)
551 #if XmVersion >= 2000
552 Widget button;
554 button = CreateToggleButton(parent, "Show hidden files");
555 AddToggleButtonCB(button, show_hidden_cb, fsb);
556 XtVaSetValues(fsb, XmNfileFilterStyle, XmFILTER_HIDDEN_FILES, NULL);
557 #endif
560 /* File selection dialog */
561 static void fsb_setcwd_cb(Widget but, void *data)
563 char *bufp;
564 XmString directory;
565 Widget fsb = (Widget) data;
567 XtVaGetValues(fsb, XmNdirectory, &directory, NULL);
568 bufp = GetStringSimple(directory);
569 XmStringFree(directory);
570 if (bufp != NULL) {
571 set_workingdir(gapp, bufp);
572 XtFree(bufp);
576 #define FSB_CWD 0
577 #define FSB_HOME 1
578 #define FSB_ROOT 2
579 #define FSB_CYGDRV 3
581 static void fsb_cd_cb(OptionStructure *opt, int value, void *data)
583 char *dir;
584 FSBStructure *fsb = (FSBStructure *) data;
586 switch (value) {
587 case FSB_CWD:
588 dir = get_workingdir(gapp);
589 break;
590 case FSB_HOME:
591 dir = grace_get_userhome(gapp->grace);
592 break;
593 case FSB_ROOT:
594 dir = "/";
595 break;
596 case FSB_CYGDRV:
597 dir = "/cygdrive/";
598 break;
599 default:
600 return;
603 FSBDialogSetDirectory(fsb, dir);
606 static OptionItem fsb_items[] = {
607 {FSB_CWD, "Cwd"},
608 {FSB_HOME, "Home"},
609 {FSB_ROOT, "/"}
610 #ifdef __CYGWIN__
611 ,{FSB_CYGDRV, "My Computer"}
612 #endif
615 #define FSB_ITEMS_NUM sizeof(fsb_items)/sizeof(OptionItem)
617 FSBStructure *CreateFSBDialog(Widget parent, char *s)
619 FSBStructure *retval;
620 OptionStructure *opt;
621 Widget dialog, fr, form, button;
623 retval = xmalloc(sizeof(FSBStructure));
625 dialog = CreateDialogWindow(parent, s);
626 retval->FSB = CreateFileSelectionBox(dialog);
628 FSBDialogSetDirectory(retval, get_workingdir(gapp));
629 AddWidgetCB(retval->FSB, "cancel", close_dialogCB, dialog);
630 AddHelpCB(retval->FSB, "doc/UsersGuide.html#FS-dialog");
632 retval->rc = CreateVContainer(retval->FSB);
634 CreateFileSelectionFilter(retval->rc, retval->FSB);
636 fr = CreateFrame(retval->rc, NULL);
638 form = CreateForm(fr);
640 opt = CreateOptionChoice(form, "Chdir to:", 1, FSB_ITEMS_NUM, fsb_items);
641 AddOptionChoiceCB(opt, fsb_cd_cb, retval);
642 FormAddHChild(form, opt->menu);
644 button = CreateButton(form, "Set as cwd");
645 AddButtonCB(button, fsb_setcwd_cb, retval->FSB);
646 FormAddHChild(form, button);
647 FormFixateHChild(button);
649 WidgetManage(form);
651 return retval;
654 typedef struct {
655 FSBStructure *fsb;
656 FSB_CBProc cbproc;
657 void *anydata;
658 } FSB_CBdata;
660 static void fsb_int_cb_proc(Widget_CBData *wcbdata)
662 FSB_CBdata *cbdata = (FSB_CBdata *) wcbdata->anydata;
663 char *s = (char *) wcbdata->calldata;
664 int ok;
666 set_wait_cursor();
668 ok = cbdata->cbproc(cbdata->fsb, s, cbdata->anydata);
670 if (ok) {
671 DialogClose(cbdata->fsb->FSB);
673 unset_wait_cursor();
676 void AddFSBDialogCB(FSBStructure *fsb, FSB_CBProc cbproc, void *anydata)
678 FSB_CBdata *cbdata;
680 cbdata = xmalloc(sizeof(FSB_CBdata));
681 cbdata->fsb = fsb;
682 cbdata->cbproc = (FSB_CBProc) cbproc;
683 cbdata->anydata = anydata;
685 AddWidgetCB(fsb->FSB, "ok", fsb_int_cb_proc, cbdata);
688 void FSBDialogSetPattern(FSBStructure *fsb, char *pattern)
690 XmString xmstr;
692 if (pattern != NULL) {
693 xmstr = XmStringCreateLocalized(pattern);
694 XtVaSetValues(fsb->FSB, XmNpattern, xmstr, NULL);
695 XmStringFree(xmstr);
699 void FSBDialogSetDirectory(FSBStructure *fsb, char *directory)
701 XmString xmstr;
703 if (directory != NULL) {
704 xmstr = XmStringCreateLocalized(directory);
705 XtVaSetValues(fsb->FSB, XmNdirectory, xmstr, NULL);
706 XmStringFree(xmstr);
710 /* Containers */
711 Widget CreateVContainer(Widget parent)
713 Widget rc;
715 rc = XmCreateRowColumn(parent, "VContainer", NULL, 0);
716 WidgetManage(rc);
718 return rc;
721 Widget CreateHContainer(Widget parent)
723 Widget rc;
725 rc = XmCreateRowColumn(parent, "HContainer", NULL, 0);
726 XtVaSetValues(rc, XmNorientation, XmHORIZONTAL, NULL);
727 WidgetManage(rc);
729 return rc;
732 /* Form */
733 Widget CreateForm(Widget parent)
735 Widget w;
737 w = XmCreateForm(parent, "form", NULL, 0);
739 return w;
742 void FormAddHChild(Widget form, Widget child)
744 Widget last_widget;
746 last_widget = WidgetGetUserData(form);
747 if (last_widget) {
748 XtVaSetValues(child,
749 XmNleftAttachment, XmATTACH_WIDGET,
750 XmNleftWidget, last_widget,
751 NULL);
752 XtVaSetValues(last_widget,
753 XmNrightAttachment, XmATTACH_NONE,
754 NULL);
755 } else {
756 XtVaSetValues(child,
757 XmNleftAttachment, XmATTACH_FORM,
758 NULL);
760 XtVaSetValues(child,
761 XmNtopAttachment, XmATTACH_FORM,
762 XmNbottomAttachment, XmATTACH_FORM,
763 XmNrightAttachment, XmATTACH_FORM,
764 NULL);
765 WidgetSetUserData(form, child);
768 void FormAddVChild(Widget form, Widget child)
770 Widget last_widget;
772 if (XtIsSubclass(child, listtreeWidgetClass) ||
773 (XmIsText(child) && XmIsScrolledWindow(XtParent(child)))) {
774 child = XtParent(child);
777 last_widget = WidgetGetUserData(form);
778 if (last_widget) {
779 XtVaSetValues(child,
780 XmNtopAttachment, XmATTACH_WIDGET,
781 XmNtopWidget, last_widget,
782 NULL);
783 XtVaSetValues(last_widget,
784 XmNbottomAttachment, XmATTACH_NONE,
785 NULL);
786 } else {
787 XtVaSetValues(child,
788 XmNtopAttachment, XmATTACH_FORM,
789 NULL);
791 XtVaSetValues(child,
792 XmNleftAttachment, XmATTACH_FORM,
793 XmNrightAttachment, XmATTACH_FORM,
794 XmNbottomAttachment, XmATTACH_FORM,
795 NULL);
796 WidgetSetUserData(form, child);
799 void FormFixateHChild(Widget w)
801 Widget prev;
802 XtVaGetValues(w, XmNleftWidget, &prev, NULL);
803 XtVaSetValues(w, XmNleftAttachment, XmATTACH_NONE, NULL);
804 XtVaSetValues(prev, XmNrightAttachment, XmATTACH_WIDGET,
805 XmNrightWidget, w,
806 NULL);
809 void FormFixateVChild(Widget w)
811 Widget prev;
812 XtVaGetValues(w, XmNtopWidget, &prev, NULL);
813 XtVaSetValues(w, XmNtopAttachment, XmATTACH_NONE, NULL);
814 XtVaSetValues(prev, XmNbottomAttachment, XmATTACH_WIDGET,
815 XmNbottomWidget, w,
816 NULL);
819 /* Grid */
820 typedef struct {
821 int ncols;
822 int nrows;
823 } GridData;
825 Widget CreateGrid(Widget parent, int ncols, int nrows)
827 Widget w;
828 int nfractions;
829 GridData *gd;
831 if (ncols <= 0 || nrows <= 0) {
832 errmsg("Wrong call to CreateGrid()");
833 ncols = 1;
834 nrows = 1;
837 nfractions = 0;
838 do {
839 nfractions++;
840 } while (nfractions % ncols || nfractions % nrows);
842 gd = xmalloc(sizeof(GridData));
843 gd->ncols = ncols;
844 gd->nrows = nrows;
846 w = CreateForm(parent);
848 XtVaSetValues(w,
849 XmNfractionBase, nfractions,
850 XmNuserData, gd,
851 NULL);
853 WidgetManage(w);
855 return w;
858 void PlaceGridChild(Widget grid, Widget w, int col, int row)
860 int nfractions, w1, h1;
861 GridData *gd;
863 XtVaGetValues(grid,
864 XmNfractionBase, &nfractions,
865 XmNuserData, &gd,
866 NULL);
868 if (gd == NULL) {
869 /* errmsg("PlaceGridChild() called with a non-grid widget"); */
870 return;
872 if (col < 0 || col >= gd->ncols) {
873 errmsg("PlaceGridChild() called with wrong `col' argument");
874 return;
876 if (row < 0 || row >= gd->nrows) {
877 errmsg("PlaceGridChild() called with wrong `row' argument");
878 return;
881 w1 = nfractions/gd->ncols;
882 h1 = nfractions/gd->nrows;
884 XtVaSetValues(w,
885 XmNleftAttachment , XmATTACH_POSITION,
886 XmNleftPosition , col*w1 ,
887 XmNrightAttachment , XmATTACH_POSITION,
888 XmNrightPosition , (col + 1)*w1 ,
889 XmNtopAttachment , XmATTACH_POSITION,
890 XmNtopPosition , row*h1 ,
891 XmNbottomAttachment, XmATTACH_POSITION,
892 XmNbottomPosition , (row + 1)*h1 ,
893 NULL);
896 /* Frame */
897 Widget CreateFrame(Widget parent, char *s)
899 Widget fr;
901 fr = XtVaCreateManagedWidget("frame", xmFrameWidgetClass, parent, NULL);
902 if (s != NULL) {
903 XtVaCreateManagedWidget(s, xmLabelGadgetClass, fr,
904 XmNchildType, XmFRAME_TITLE_CHILD,
905 NULL);
908 return fr;
911 /* Scrolled window */
912 Widget CreateScrolledWindow(Widget parent)
914 return XtVaCreateManagedWidget("scrolledWindow",
915 xmScrolledWindowWidgetClass, parent,
916 XmNscrollingPolicy, XmAUTOMATIC,
917 NULL);
920 /* Paned window */
921 Widget CreatePanedWindow(Widget parent)
923 #if USE_PANEDW
924 return XtVaCreateManagedWidget("panedWindow",
925 xmPanedWindowWidgetClass, parent,
926 XmNorientation, XmHORIZONTAL,
927 NULL);
928 #else
929 return CreateGrid(parent, 2, 1);
930 #endif
933 void PanedWindowSetMinWidth(Widget w, unsigned int width)
935 XtVaSetValues(w, XmNpaneMinimum, (Dimension) width, NULL);
938 /* Tab */
939 Widget CreateTab(Widget parent)
941 Widget tab;
943 tab = XtVaCreateManagedWidget("tab", xmTabWidgetClass, parent, NULL);
945 return tab;
948 Widget CreateTabPage(Widget parent, char *s)
950 Widget w;
951 XmString str;
953 w = CreateVContainer(parent);
954 str = XmStringCreateLocalized(s);
955 XtVaSetValues(w, XmNtabLabel, str, NULL);
956 XmStringFree(str);
958 return w;
961 void SelectTabPage(Widget tab, Widget w)
963 XmTabSetTabWidget(tab, w, True);
966 /* Separator */
967 Widget CreateSeparator(Widget parent)
969 Widget sep;
971 sep = XmCreateSeparator(parent, "sep", NULL, 0);
972 WidgetManage(sep);
974 return sep;
977 /* Label */
978 Widget CreateLabel(Widget parent, char *s)
980 Widget label;
982 label = XtVaCreateManagedWidget("label",
983 xmLabelWidgetClass, parent,
984 XmNalignment, XmALIGNMENT_BEGINNING,
985 XmNrecomputeSize, True,
986 NULL);
988 LabelSetString(label, s);
990 return label;
993 void LabelSetString(Widget w, char *s)
995 XmString str;
997 if (s == NULL) return;
999 str = XmStringCreateLocalized(s);
1000 XtVaSetValues(w, XmNlabelString, str, NULL);
1001 XmStringFree(str);
1004 static Pixmap BitmapToPixmap(Widget w, int width, int height, const unsigned char *bits)
1006 Pixmap pm;
1008 X11Stuff *xstuff = gapp->gui->xstuff;
1009 Pixel fg, bg;
1011 XtVaGetValues(w,
1012 XmNforeground, &fg,
1013 XmNbackground, &bg,
1014 NULL);
1016 pm = XCreatePixmapFromBitmapData(xstuff->disp,
1017 xstuff->root, (char *) bits, width, height, fg, bg, xstuff->depth);
1019 return pm;
1022 void LabelSetPixmap(Widget w, Pixmap pixmap)
1024 XtVaSetValues(w,
1025 XmNlabelType, XmPIXMAP,
1026 XmNlabelPixmap, pixmap,
1027 NULL);
1030 /* Text edit */
1031 Widget CreateLineTextEdit(Widget parent, int len)
1033 Widget w;
1035 w = XtVaCreateManagedWidget("text", xmTextWidgetClass, parent,
1036 XmNtraversalOn, True,
1037 NULL);
1038 if (len > 0) {
1039 XtVaSetValues(w, XmNcolumns, len, NULL);
1042 return w;
1045 Widget CreateMultiLineTextEdit(Widget parent, int nrows)
1047 Widget w;
1048 Arg args[3];
1049 int ac;
1051 ac = 0;
1052 if (nrows > 0) {
1053 XtSetArg(args[ac], XmNrows, nrows); ac++;
1055 XtSetArg(args[ac], XmNeditMode, XmMULTI_LINE_EDIT); ac++;
1056 XtSetArg(args[ac], XmNvisualPolicy, XmVARIABLE); ac++;
1058 w = XmCreateScrolledText(parent, "text", args, ac);
1059 WidgetManage(w);
1061 return w;
1064 char *TextEditGetString(Widget w)
1066 char *s, *buf;
1068 s = XmTextGetString(w);
1069 buf = copy_string(NULL, s);
1070 XtFree(s);
1072 return buf;
1075 void TextEditSetString(Widget w, char *s)
1077 XmTextSetString(w, s ? s : "");
1080 /* Text */
1081 void TextInsertString(TextStructure *cst, int pos, char *s)
1083 XmTextInsert(cst->text, pos, s);
1086 int TextGetCursorPos(TextStructure *cst)
1088 return XmTextGetInsertionPosition(cst->text);
1091 void TextSetCursorPos(TextStructure *cst, int pos)
1093 XmTextSetInsertionPosition(cst->text, pos);
1096 int TextGetLastPosition(TextStructure *cst)
1098 return XmTextGetLastPosition(cst->text);
1101 void TextSetLength(TextStructure *cst, int len)
1103 XtVaSetValues(cst->text, XmNcolumns, len, NULL);
1106 void TextSetEditable(TextStructure *cst, int onoff)
1108 XtVaSetValues(cst->text, XmNeditable, onoff? True:False, NULL);
1111 /* Button */
1112 Widget CreateButton(Widget parent, char *label)
1114 Widget button;
1116 button = XtVaCreateManagedWidget(label,
1117 xmPushButtonWidgetClass, parent,
1118 NULL);
1120 XtVaSetValues(button,
1121 XmNalignment, XmALIGNMENT_CENTER,
1122 NULL);
1124 return button;
1127 Widget CreateBitmapButton(Widget parent,
1128 int width, int height, const unsigned char *bits)
1130 Widget button;
1131 Pixmap pm;
1133 button = XtVaCreateWidget("button",
1134 xmPushButtonWidgetClass, parent,
1135 NULL);
1137 pm = BitmapToPixmap(button, width, height, bits);
1139 LabelSetPixmap(button, pm);
1140 WidgetManage(button);
1142 return button;
1145 Widget CreateArrowButton(Widget parent, int arrow_type)
1147 Widget w;
1149 w = XtVaCreateManagedWidget("arrow", xmArrowButtonGadgetClass, parent,
1150 XmNarrowDirection, (arrow_type == ARROW_UP) ? XmARROW_UP : XmARROW_DOWN,
1151 NULL);
1153 return w;
1156 /* ToggleButton */
1157 Widget CreateToggleButton(Widget parent, char *s)
1159 return (XtVaCreateManagedWidget(s, xmToggleButtonWidgetClass, parent, NULL));
1162 int ToggleButtonGetState(Widget w)
1164 if (!w) {
1165 errmsg("Internal error: GetToggleButtonState() called with NULL widget");
1166 return 0;
1167 } else {
1168 return XmToggleButtonGetState(w);
1172 void ToggleButtonSetState(Widget w, int value)
1174 if (w == NULL) {
1175 return;
1177 XmToggleButtonSetState(w, value ? True:False, False);
1179 return;
1182 /* Scale */
1183 Widget CreateScale(Widget parent, char *s, int min, int max, int delta)
1185 Widget w;
1186 XmString str;
1188 str = XmStringCreateLocalized(s);
1190 w = XtVaCreateManagedWidget("scroll",
1191 xmScaleWidgetClass, parent,
1192 XmNtitleString, str,
1193 XmNminimum, min,
1194 XmNmaximum, max,
1195 XmNscaleMultiple, delta,
1196 XmNvalue, 0,
1197 XmNshowValue, True,
1198 XmNprocessingDirection, XmMAX_ON_RIGHT,
1199 XmNorientation, XmHORIZONTAL,
1200 #if XmVersion >= 2000
1201 XmNsliderMark, XmROUND_MARK,
1202 #endif
1203 NULL);
1205 XmStringFree(str);
1207 return w;
1210 void ScaleSetValue(Widget w, int value)
1212 XtVaSetValues(w, XmNvalue, value, NULL);
1215 int ScaleGetValue(Widget w)
1217 int value;
1218 XtVaGetValues(w, XmNvalue, &value, NULL);
1219 return value;
1222 /* OptionChoice */
1223 static void combobox_press(Widget_CBData *wcbdata)
1225 Widget but = wcbdata->w;
1226 Widget popup = XtParent(wcbdata->anydata);
1227 Widget table = wcbdata->anydata;
1229 Dimension wh;
1230 Position wx, wy, root_x_return, root_y_return;
1232 XtVaGetValues(but,
1233 XtNx, &wx,
1234 XtNy, &wy,
1235 XmNheight, &wh,
1236 NULL);
1238 XtTranslateCoords(but, 0, 0, &root_x_return, &root_y_return);
1240 XtVaSetValues(popup,
1241 XtNx, root_x_return,
1242 XtNy, root_y_return + wh,
1243 NULL);
1245 XtPopup(popup, XtGrabNone);
1246 XtGrabPointer(table, False, ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
1249 static int oc_drawCB(TableEvent *event)
1251 OptionStructure *optp = (OptionStructure *) event->anydata;
1252 int i;
1254 i = event->row + event->col * TableGetNrows(optp->pulldown);
1256 if (optp->items[i].label) {
1257 event->value_type = TABLE_CELL_STRING;
1258 event->value = optp->items[i].label;
1259 } else {
1260 event->value_type = TABLE_CELL_PIXMAP;
1261 event->pixmap = optp->items[i].pixmap;
1264 if (optp->update_colors) {
1265 event->background = optp->items[i].background;
1266 event->foreground = optp->items[i].foreground;
1269 return TRUE;
1272 static void table_event_proc(Widget w, XtPointer data, XEvent *event, Boolean *cont)
1274 OptionStructure *opt = (OptionStructure *)data;
1275 int row, col;
1277 XtCallActionProc(opt->menu, "Disarm", NULL, NULL, 0);
1278 XtUngrabPointer(w, CurrentTime);
1280 if(XbaeMatrixGetEventRowColumn(w, event, &row, &col)) {
1281 int i;
1282 OC_CBdata *cbdata;
1284 i = row + col * TableGetNrows(opt->pulldown);
1286 if (opt->items[i].label) {
1287 LabelSetString(opt->menu, opt->items[i].label);
1288 } else {
1289 LabelSetPixmap(opt->menu, opt->items[i].pixmap);
1291 opt->cvalue = opt->items[i].value;
1293 for (i = 0; i < opt->cbnum; i++) {
1294 cbdata = opt->cblist[i];
1295 cbdata->cbproc(opt, opt->cvalue, cbdata->anydata);
1299 XtPopdown(XtParent(opt->pulldown));
1302 OptionStructure *CreateOptionChoice(Widget parent, char *labelstr,
1303 int ncols, int nchoices, OptionItem *items)
1305 OptionStructure *retval;
1306 Widget rc, popup;
1308 retval = xcalloc(1, sizeof(OptionStructure));
1309 if (!retval) {
1310 return NULL;
1313 rc = CreateHContainer(parent);
1314 CreateLabel(rc, labelstr);
1316 retval->menu = CreateButton(rc, "ComboBox");
1318 popup = XtCreatePopupShell("popup", overrideShellWidgetClass, retval->menu, NULL, 0);
1319 retval->pulldown = CreateTable("pulldownTable", popup, 1, 1, 0, 0);
1320 TableOptionChoiceInit(retval->pulldown);
1321 AddWidgetCB(retval->menu, "arm", combobox_press, retval->pulldown);
1322 XtAddEventHandler(retval->pulldown, ButtonReleaseMask, False, table_event_proc, retval);
1324 retval->ncols = ncols;
1325 retval->nchoices = 0;
1326 retval->items = NULL;
1327 retval->update_colors = FALSE;
1329 UpdateOptionChoice(retval, nchoices, items);
1330 AddTableDrawCellCB(retval->pulldown, oc_drawCB, retval);
1332 if (retval->items[0].label) {
1333 LabelSetString(retval->menu, retval->items[0].label);
1334 } else {
1335 LabelSetPixmap(retval->menu, retval->items[0].pixmap);
1337 retval->cvalue = retval->items[0].value;
1339 return retval;
1342 OptionStructure *CreateOptionChoiceVA(Widget parent, char *labelstr, ...)
1344 OptionStructure *retval;
1345 int nchoices = 0;
1346 OptionItem *oi = NULL;
1347 va_list var;
1348 char *s;
1349 int value;
1351 va_start(var, labelstr);
1352 while ((s = va_arg(var, char *)) != NULL) {
1353 value = va_arg(var, int);
1354 nchoices++;
1355 oi = xrealloc(oi, nchoices*sizeof(OptionItem));
1356 oi[nchoices - 1].value = value;
1357 oi[nchoices - 1].label = copy_string(NULL, s);
1359 va_end(var);
1361 retval = CreateOptionChoice(parent, labelstr, 1, nchoices, oi);
1363 while (nchoices) {
1364 nchoices--;
1365 xfree(oi[nchoices].label);
1367 xfree(oi);
1369 return retval;
1372 OptionStructure *CreateBitmapOptionChoice(Widget parent, char *labelstr, int ncols,
1373 int nchoices, int width, int height, BitmapOptionItem *items)
1375 int i;
1376 OptionStructure *retval;
1377 OptionItem *pixmap_items;
1379 pixmap_items = xmalloc(nchoices*sizeof(OptionItem));
1380 if (pixmap_items == NULL) {
1381 errmsg("Malloc error in CreateBitmapOptionChoice()");
1382 return NULL;
1385 for (i = 0; i < nchoices; i++) {
1386 pixmap_items[i].value = items[i].value;
1387 if (items[i].bitmap) {
1388 pixmap_items[i].label = NULL;
1389 pixmap_items[i].pixmap = BitmapToPixmap(parent, width, height, items[i].bitmap);
1390 } else {
1391 pixmap_items[i].label = "None";
1395 retval = CreateOptionChoice(parent, labelstr, ncols, nchoices, pixmap_items);
1397 xfree(pixmap_items);
1399 return retval;
1402 static unsigned char dummy_bits[] = {
1403 0x00, 0x00, 0x00, 0x00, 0xec, 0x2e, 0x04, 0x20, 0x00, 0x20, 0x04, 0x00,
1404 0x04, 0x20, 0x04, 0x20, 0x00, 0x20, 0x04, 0x00, 0x04, 0x20, 0x04, 0x20,
1405 0x00, 0x20, 0xdc, 0x1d, 0x00, 0x00, 0x00, 0x00};
1407 OptionStructure *CreateCharOptionChoice(Widget parent, char *s)
1409 int i;
1410 int nchoices = 256;
1411 int *fontid;
1413 OptionStructure *retval;
1414 OptionItem *pixmap_items;
1415 Pixmap pixmap;
1417 pixmap_items = xmalloc(nchoices*sizeof(OptionItem));
1418 if (pixmap_items == NULL) {
1419 errmsg("Malloc error in CreateCharOptionChoice()");
1420 return NULL;
1423 pixmap = BitmapToPixmap(parent, 16, 16, dummy_bits);
1424 for (i = 0; i < nchoices; i++) {
1425 pixmap_items[i].value = (char) i;
1426 pixmap_items[i].label = NULL;
1427 pixmap_items[i].pixmap = pixmap;
1430 retval = CreateOptionChoice(parent, s, 16, nchoices, pixmap_items);
1432 xfree(pixmap_items);
1434 fontid = xmalloc(SIZEOF_INT);
1435 *fontid = -1;
1436 WidgetSetUserData(retval->menu, fontid);
1438 return retval;
1441 void UpdateCharOptionChoice(OptionStructure *opt, int font)
1443 int *old_font;
1444 old_font = (int *) WidgetGetUserData(opt->menu);
1445 if (*old_font != font) {
1446 int i;
1447 for (i = 0; i < opt->nchoices; i++) {
1448 Pixmap pixmap = char_to_pixmap(opt->pulldown, font, (char) i, 24);
1449 if (pixmap) {
1450 opt->items[i].pixmap = pixmap;
1452 //TODO:
1453 // WidgetSetSensitive(w, ptmp ? TRUE:FALSE);
1455 *old_font = font;
1459 void SetOptionChoice(OptionStructure *opt, int value)
1461 int i;
1463 if (opt->items == NULL || opt->nchoices <= 0) {
1464 return;
1467 for (i = 0; i < opt->nchoices; i++) {
1468 if (opt->items[i].value == value) {
1469 if (opt->items[i].label) {
1470 LabelSetString(opt->menu, opt->items[i].label);
1471 } else {
1472 LabelSetPixmap(opt->menu, opt->items[i].pixmap);
1474 opt->cvalue = opt->items[i].value;
1475 return;
1479 errmsg("Value not found in SetOptionChoice()");
1482 int GetOptionChoice(OptionStructure *opt)
1484 if (opt->items == NULL || opt->nchoices <= 0) {
1485 errmsg("Internal error in GetOptionChoice()");
1486 return 0;
1489 return opt->cvalue;
1492 #define MAX_PULLDOWN_LENGTH 30
1493 void UpdateOptionChoice(OptionStructure *optp, int nchoices, OptionItem *items)
1495 int i, ncols, nrows, nc, nr;
1496 int delta_nc, delta_nr;
1497 int width = 0;
1499 if (optp->ncols == 0) {
1500 ncols = 1;
1501 } else {
1502 ncols = optp->ncols;
1505 /* Don't create too tall pulldowns */
1506 if (nchoices > MAX_PULLDOWN_LENGTH*ncols) {
1507 ncols = (nchoices + MAX_PULLDOWN_LENGTH - 1)/MAX_PULLDOWN_LENGTH;
1510 nrows = nchoices / ncols;
1512 nr = TableGetNrows(optp->pulldown);
1513 nc = TableGetNcols(optp->pulldown);
1515 delta_nr = nrows - nr;
1516 delta_nc = ncols - nc;
1518 if (delta_nr > 0) {
1519 TableAddRows(optp->pulldown, delta_nr);
1520 } else if (delta_nr < 0) {
1521 TableDeleteRows(optp->pulldown, -delta_nr);
1523 if (delta_nc > 0) {
1524 TableAddCols(optp->pulldown, delta_nc);
1525 } else if (delta_nc < 0) {
1526 TableDeleteCols(optp->pulldown, -delta_nc);
1529 for (i = 0; i < optp->nchoices; i++) {
1530 xfree(optp->items[i].label);
1533 optp->items = xrealloc(optp->items, nchoices*sizeof(OptionItem));
1535 for (i = 0; i < nchoices; i++) {
1536 char *label;
1537 optp->items[i].value = items[i].value;
1539 label = items[i].label;
1540 if (label) {
1541 if (width < strlen(label)) {
1542 width = strlen(label);
1544 optp->items[i].label = copy_string(NULL, label);
1545 } else {
1546 optp->items[i].label = NULL;
1547 optp->items[i].pixmap = items[i].pixmap;
1550 optp->items[i].background = items[i].background;
1551 optp->items[i].foreground = items[i].foreground;
1554 optp->nchoices = nchoices;
1556 if (width) {
1557 TableSetDefaultColWidth(optp->pulldown, width);
1559 TableUpdateVisibleRowsCols(optp->pulldown);
1562 void OptionChoiceSetColorUpdate(OptionStructure *opt, int update)
1564 opt->update_colors = update;
1567 void AddOptionChoiceCB(OptionStructure *opt, OC_CBProc cbproc, void *anydata)
1569 OC_CBdata *cbdata;
1571 cbdata = xmalloc(sizeof(OC_CBdata));
1573 cbdata->opt = opt;
1574 cbdata->cbproc = cbproc;
1575 cbdata->anydata = anydata;
1577 opt->cblist = xrealloc(opt->cblist, (opt->cbnum + 1)*sizeof(OC_CBdata *));
1578 opt->cblist[opt->cbnum] = cbdata;
1579 opt->cbnum++;
1582 /* Menu */
1583 Widget CreatePopupMenu(Widget parent)
1585 return XmCreatePopupMenu(parent, "popupMenu", NULL, 0);
1588 void PopupMenuShow(Widget w, void *data)
1590 XmMenuPosition(w, (XButtonEvent *) data);
1591 WidgetManage(w);
1594 Widget CreateMenuBar(Widget parent)
1596 Widget menubar;
1598 menubar = XmCreateMenuBar(parent, "menuBar", NULL, 0);
1599 return menubar;
1602 Widget CreateMenu(Widget parent, char *label, char mnemonic, int help)
1604 Widget menupane, cascade;
1605 char ms[2];
1607 menupane = XmCreatePulldownMenu(parent, "menu", NULL, 0);
1609 ms[0] = mnemonic;
1610 ms[1] = '\0';
1612 cascade = XtVaCreateManagedWidget("cascade",
1613 xmCascadeButtonGadgetClass, parent,
1614 XmNsubMenuId, menupane,
1615 XmNmnemonic, XStringToKeysym(ms),
1616 NULL);
1618 LabelSetString(cascade, label);
1620 if (help) {
1621 XtVaSetValues(parent, XmNmenuHelpWidget, cascade, NULL);
1622 CreateMenuButton(menupane, "On context", 'x',
1623 ContextHelpCB, NULL);
1624 CreateSeparator(menupane);
1627 return menupane;
1630 Widget CreateMenuButton(Widget parent, char *label, char mnemonic,
1631 Button_CBProc cb, void *data)
1633 return CreateMenuButtonA(parent, label, mnemonic, NULL, NULL, cb, data);
1636 Widget CreateMenuButtonA(Widget parent, char *label, char mnemonic,
1637 char *accelerator, char* acceleratorText, Button_CBProc cb, void *data)
1639 Widget button;
1640 XmString str;
1641 char *name, ms[2];
1643 ms[0] = mnemonic;
1644 ms[1] = '\0';
1646 name = label_to_resname(label, "Button");
1648 button = CreateButton(parent, name);
1649 xfree(name);
1651 XtVaSetValues(button,
1652 XmNmnemonic, XStringToKeysym(ms),
1653 XmNalignment, XmALIGNMENT_BEGINNING,
1654 NULL);
1656 if (accelerator && acceleratorText) {
1657 str = XmStringCreateLocalized(acceleratorText);
1658 XtVaSetValues(button,
1659 XmNaccelerator, accelerator,
1660 XmNacceleratorText, str,
1661 NULL);
1662 XmStringFree(str);
1665 LabelSetString(button, label);
1667 AddButtonCB(button, cb, data);
1669 return button;
1672 Widget CreateMenuHelpButton(Widget parent, char *label, char mnemonic,
1673 Widget form, char *ha)
1675 Widget wbut;
1677 wbut = CreateMenuButton(parent, label, mnemonic, HelpCB, ha);
1678 AddHelpCB(form, ha);
1680 return wbut;
1683 Widget CreateMenuToggle(Widget parent, char *label, char mnemonic,
1684 TB_CBProc cb, void *data)
1686 Widget button;
1687 char *name, ms[2];
1689 ms[0] = mnemonic;
1690 ms[1] = '\0';
1692 name = label_to_resname(label, NULL);
1693 button = CreateToggleButton(parent, name);
1694 xfree(name);
1696 XtVaSetValues(button,
1697 XmNmnemonic, XStringToKeysym(ms),
1698 XmNvisibleWhenOff, True,
1699 XmNindicatorOn, True,
1700 NULL);
1702 LabelSetString(button, label);
1704 if (cb) {
1705 AddToggleButtonCB(button, cb, data);
1708 return button;
1711 Widget CreateMenuSeparator(Widget parent)
1713 return CreateSeparator(parent);