/*
* Grace - GRaphing, Advanced Computation and Exploration of data
*
* Home page: http://plasma-gate.weizmann.ac.il/Grace/
*
* Copyright (c) 1991-1995 Paul J Turner, Portland, OR
* Copyright (c) 1996-2003 Grace Development Team
*
* Maintained by Evgeny Stambulchik
*
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
*
* utilities for Motif
*
*/
#include <config.h>
#include <cmath.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdarg.h>
#include <X11/X.h>
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#include <Xm/Xm.h>
#include <Xm/Protocols.h>
#include <Xm/BulletinB.h>
#include <Xm/MessageB.h>
#include <Xm/DialogS.h>
#include <Xm/FileSB.h>
#include <Xm/Frame.h>
#include <Xm/Form.h>
#include <Xm/Scale.h>
#include <Xm/Label.h>
#include <Xm/LabelG.h>
#include <Xm/List.h>
#include <Xm/PushB.h>
#include <Xm/CascadeBG.h>
#include <Xm/RowColumn.h>
#include <Xm/Separator.h>
#include <Xm/Text.h>
#include <Xm/ToggleB.h>
#include <Xm/ArrowBG.h>
#ifdef WITH_EDITRES
# include <X11/Xmu/Editres.h>
#endif
#if XmVersion < 2000
# define XmStringConcatAndFree(a, b) XmStringConcat(a, b); XmStringFree(a); XmStringFree(b)
#endif
#include "Tab.h"
#include "motifinc.h"
#include "defines.h"
#include "globals.h"
#include "draw.h"
#include "patterns.h"
#include "jbitmaps.h"
#include "t1fonts.h"
#include "graphs.h"
#include "utils.h"
#include "events.h"
#include "parser.h"
#include "protos.h"
static XmStringCharSet charset = XmFONTLIST_DEFAULT_TAG;
/* lookup table to determine if character is a floating point digit
* only allowable char's [0-9.eE]
*/
unsigned char fpdigit[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
extern Display *disp;
extern Window root;
extern int depth;
extern XtAppContext app_con;
extern unsigned long xvlibcolors[];
static OptionItem *color_option_items = NULL;
static int ncolor_option_items = 0;
static OptionStructure **color_selectors = NULL;
static int ncolor_selectors = 0;
static char *label_to_resname(const char *s, const char *suffix)
{
char *retval, *rs;
int capitalize = FALSE;
retval = copy_string(NULL, s);
rs = retval;
while (*s) {
if (isalnum(*s)) {
if (capitalize == TRUE) {
*rs = toupper(*s);
capitalize = FALSE;
} else {
*rs = tolower(*s);
}
rs++;
} else {
capitalize = TRUE;
}
s++;
}
*rs = '\0';
if (suffix != NULL) {
retval = concat_strings(retval, suffix);
}
return retval;
}
void ManageChild(Widget w)
{
XtManageChild(w);
}
void UnmanageChild(Widget w)
{
XtUnmanageChild(w);
}
void SetSensitive(Widget w, int onoff)
{
XtSetSensitive(w, onoff ? True : False);
}
Widget GetParent(Widget w)
{
if (w) {
return (XtParent(w));
} else {
errmsg("Internal error: GetParent() called with NULL widget");
return NULL;
}
}
void RegisterEditRes(Widget shell)
{
#ifdef WITH_EDITRES
XtAddEventHandler(shell, (EventMask) 0, True, _XEditResCheckMessages, NULL);
#endif
}
void SetDimensions(Widget w, unsigned int width, unsigned int height)
{
XtVaSetValues(w,
XmNwidth, (Dimension) width,
XmNheight, (Dimension) height,
NULL);
}
void GetDimensions(Widget w, unsigned int *width, unsigned int *height)
{
Dimension ww, wh;
XtVaGetValues(w,
XmNwidth, &ww,
XmNheight, &wh,
NULL);
*width = (unsigned int) ww;
*height = (unsigned int) wh;
}
#define MAX_PULLDOWN_LENGTH 30
OptionStructure *CreateOptionChoice(Widget parent, char *labelstr, int ncols,
int nchoices, OptionItem *items)
{
Arg args[2];
XmString str;
OptionStructure *retval;
retval = xmalloc(sizeof(OptionStructure));
XtSetArg(args[0], XmNpacking, XmPACK_COLUMN);
retval->pulldown = XmCreatePulldownMenu(parent, "pulldownMenu", args, 1);
retval->ncols = ncols;
retval->nchoices = 0;
retval->options = NULL;
UpdateOptionChoice(retval, nchoices, items);
str = XmStringCreateLocalized(labelstr);
XtSetArg(args[0], XmNlabelString, str);
XtSetArg(args[1], XmNsubMenuId, retval->pulldown);
retval->menu = XmCreateOptionMenu(parent, "optionMenu", args, 2);
XmStringFree(str);
XtManageChild(retval->menu);
return retval;
}
void UpdateOptionChoice(OptionStructure *optp, int nchoices, OptionItem *items)
{
int i, nold, ncols, nw;
Widget *wlist;
nold = optp->nchoices;
if (optp->ncols == 0) {
ncols = 1;
} else {
ncols = optp->ncols;
}
/* Don't create too tall pulldowns */
if (nchoices > MAX_PULLDOWN_LENGTH*ncols) {
ncols = (nchoices + MAX_PULLDOWN_LENGTH - 1)/MAX_PULLDOWN_LENGTH;
}
XtVaSetValues(optp->pulldown, XmNnumColumns, ncols, NULL);
nw = nold - nchoices;
if (nw > 0) {
/* Unmanage extra items before destroying to speed the things up */
wlist = xmalloc(nw*sizeof(Widget));
for (i = nchoices; i < nold; i++) {
wlist[i - nchoices] = optp->options[i].widget;
}
XtUnmanageChildren(wlist, nw);
xfree(wlist);
for (i = nchoices; i < nold; i++) {
XtDestroyWidget(optp->options[i].widget);
}
}
optp->options = xrealloc(optp->options, nchoices*sizeof(OptionWidgetItem));
optp->nchoices = nchoices;
for (i = nold; i < nchoices; i++) {
optp->options[i].widget =
XmCreatePushButton(optp->pulldown, "button", NULL, 0);
}
for (i = 0; i < nchoices; i++) {
optp->options[i].value = items[i].value;
if (items[i].label != NULL) {
XmString str, ostr;
XtVaGetValues(optp->options[i].widget, XmNlabelString, &ostr, NULL);
str = XmStringCreateLocalized(items[i].label);
if (XmStringCompare(str, ostr) != True) {
XtVaSetValues(optp->options[i].widget, XmNlabelString, str, NULL);
}
XmStringFree(str);
}
}
nw = nchoices - nold;
if (nw > 0) {
wlist = xmalloc(nw*sizeof(Widget));
for (i = nold; i < nchoices; i++) {
wlist[i - nold] = optp->options[i].widget;
}
XtManageChildren(wlist, nw);
xfree(wlist);
}
}
OptionStructure *CreateBitmapOptionChoice(Widget parent, char *labelstr, int ncols,
int nchoices, int width, int height, BitmapOptionItem *items)
{
int i;
XmString str;
OptionStructure *retval;
Pixel fg, bg;
Pixmap ptmp;
retval = xmalloc(sizeof(OptionStructure));
if (retval == NULL) {
errmsg("Malloc error in CreateBitmapOptionChoice()");
}
retval->nchoices = nchoices;
retval->options = xmalloc(nchoices*sizeof(OptionWidgetItem));
if (retval->options == NULL) {
errmsg("Malloc error in CreateBitmapOptionChoice()");
XCFREE(retval);
return retval;
}
retval->pulldown = XmCreatePulldownMenu(parent, "pulldownMenu", NULL, 0);
XtVaSetValues(retval->pulldown,
XmNentryAlignment, XmALIGNMENT_CENTER,
NULL);
if (ncols > 0) {
XtVaSetValues(retval->pulldown,
XmNpacking, XmPACK_COLUMN,
XmNnumColumns, ncols,
NULL);
}
XtVaGetValues(retval->pulldown,
XmNforeground, &fg,
XmNbackground, &bg,
NULL);
for (i = 0; i < nchoices; i++) {
retval->options[i].value = items[i].value;
if (items[i].bitmap != NULL) {
ptmp = XCreatePixmapFromBitmapData(disp, root,
(char *) items[i].bitmap, width, height,
fg, bg, depth);
retval->options[i].widget =
XtVaCreateWidget("pixButton", xmPushButtonWidgetClass,
retval->pulldown,
XmNlabelType, XmPIXMAP,
XmNlabelPixmap, ptmp,
NULL);
} else {
retval->options[i].widget =
XmCreatePushButton(retval->pulldown, "None", NULL, 0);
}
}
for (i = 0; i < nchoices; i++) {
XtManageChild(retval->options[i].widget);
}
retval->menu = XmCreateOptionMenu(parent, "optionMenu", NULL, 0);
str = XmStringCreateLocalized(labelstr);
XtVaSetValues(retval->menu,
XmNlabelString, str,
XmNsubMenuId, retval->pulldown,
NULL);
XmStringFree(str);
XtManageChild(retval->menu);
return retval;
}
void SetOptionChoice(OptionStructure *opt, int value)
{
int i;
Arg a;
if (opt->options == NULL || opt->nchoices <= 0) {
return;
}
for (i = 0; i < opt->nchoices; i++) {
if (opt->options[i].value == value) {
XtSetArg(a, XmNmenuHistory, opt->options[i].widget);
XtSetValues(opt->menu, &a, 1);
return;
}
}
}
int GetOptionChoice(OptionStructure *opt)
{
Arg a;
Widget warg;
int i;
if (opt->options == NULL || opt->nchoices <= 0) {
errmsg("Internal error in GetOptionChoice()");
return 0;
}
XtSetArg(a, XmNmenuHistory, &warg);
XtGetValues(opt->menu, &a, 1);
for (i = 0; i < opt->nchoices; i++) {
if (opt->options[i].widget == warg) {
return(opt->options[i].value);
}
}
errmsg("Internal error in GetOptionChoice()");
return 0;
}
typedef struct {
OptionStructure *opt;
void (*cbproc)();
void *anydata;
} OC_CBdata;
static void oc_int_cb_proc(Widget w, XtPointer client_data, XtPointer call_data)
{
int value;
OC_CBdata *cbdata = (OC_CBdata *) client_data;
value = GetOptionChoice(cbdata->opt);
cbdata->cbproc(value, cbdata->anydata);
}
void AddOptionChoiceCB(OptionStructure *opt, OC_CBProc cbproc, void *anydata)
{
OC_CBdata *cbdata;
int i;
cbdata = xmalloc(sizeof(OC_CBdata));
cbdata->opt = opt;
cbdata->cbproc = cbproc;
cbdata->anydata = anydata;
for (i = 0; i < opt->nchoices; i++) {
XtAddCallback(opt->options[i].widget, XmNactivateCallback,
oc_int_cb_proc, (XtPointer) cbdata);
}
}
static char list_translation_table[] = "\
Ctrl<Key>A: list_selectall_action()\n\
Ctrl<Key>U: list_unselectall_action()\n\
Ctrl<Key>I: list_invertselection_action()";
ListStructure *CreateListChoice(Widget parent, char *labelstr, int type,
int nvisible, int nchoices, OptionItem *items)
{
Arg args[4];
Widget lab;
ListStructure *retval;
retval = xmalloc(sizeof(ListStructure));
retval->rc = XmCreateRowColumn(parent, "rcList", NULL, 0);
AddHelpCB(retval->rc, "doc/UsersGuide.html#list-selector");
lab = XmCreateLabel(retval->rc, labelstr, NULL, 0);
XtManageChild(lab);
XtSetArg(args[0], XmNlistSizePolicy, XmCONSTANT);
XtSetArg(args[1], XmNscrollBarDisplayPolicy, XmSTATIC);
if (type == LIST_TYPE_SINGLE) {
XtSetArg(args[2], XmNselectionPolicy, XmSINGLE_SELECT);
} else {
XtSetArg(args[2], XmNselectionPolicy, XmEXTENDED_SELECT);
}
XtSetArg(args[3], XmNvisibleItemCount, nvisible);
retval->list = XmCreateScrolledList(retval->rc, "listList", args, 4);
retval->values = NULL;
XtOverrideTranslations(retval->list,
XtParseTranslationTable(list_translation_table));
UpdateListChoice(retval, nchoices, items);
XtManageChild(retval->list);
XtManageChild(retval->rc);
return retval;
}
void UpdateListChoice(ListStructure *listp, int nchoices, OptionItem *items)
{
int i, nsel;
int *selvalues;
XmString str;
if (listp == NULL) {
return;
}
nsel = GetListChoices(listp, &selvalues);
listp->nchoices = nchoices;
listp->values = xrealloc(listp->values, nchoices*SIZEOF_INT);
for (i = 0; i < nchoices; i++) {
listp->values[i] = items[i].value;
}
XmListDeleteAllItems(listp->list);
for (i = 0; i < nchoices; i++) {
str = XmStringCreateLocalized(items[i].label);
XmListAddItemUnselected(listp->list, str, 0);
XmStringFree(str);
}
SelectListChoices(listp, nsel, selvalues);
if (nsel > 0) {
xfree(selvalues);
}
}
int SelectListChoice(ListStructure *listp, int choice)
{
int top, visible;
int i = 0;
while (i < listp->nchoices && listp->values[i] != choice) {
i++;
}
if (i < listp->nchoices) {
i++;
XmListDeselectAllItems(listp->list);
XmListSelectPos(listp->list, i, True);
XtVaGetValues(listp->list, XmNtopItemPosition, &top,
XmNvisibleItemCount, &visible,
NULL);
if (i < top) {
XmListSetPos(listp->list, i);
} else if (i >= top + visible) {
XmListSetBottomPos(listp->list, i);
}
return RETURN_SUCCESS;
} else {
return RETURN_FAILURE;
}
}
void SelectListChoices(ListStructure *listp, int nchoices, int *choices)
{
int i = 0, j;
unsigned char selection_type_save;
int bottom, visible;
XtVaGetValues(listp->list, XmNselectionPolicy, &selection_type_save, NULL);
XtVaSetValues(listp->list, XmNselectionPolicy, XmMULTIPLE_SELECT, NULL);
XmListDeselectAllItems(listp->list);
for (j = 0; j < nchoices; j++) {
i = 0;
while (i < listp->nchoices && listp->values[i] != choices[j]) {
i++;
}
if (i < listp->nchoices) {
i++;
XmListSelectPos(listp->list, i, True);
}
}
if (nchoices > 0) {
/* Rewind list so the last choice is always visible */
XtVaGetValues(listp->list, XmNtopItemPosition, &bottom,
XmNvisibleItemCount, &visible,
NULL);
if (i > bottom) {
XmListSetBottomPos(listp->list, i);
} else if (i <= bottom - visible) {
XmListSetPos(listp->list, i);
}
}
XtVaSetValues(listp->list, XmNselectionPolicy, selection_type_save, NULL);
}
int GetListChoices(ListStructure *listp, int **values)
{
int i, n;
if (XmListGetSelectedPos(listp->list, values, &n) != True) {
return 0;
}
for (i = 0; i < n; i++) {
(*values)[i] = listp->values[(*values)[i] - 1];
}
return n;
}
int GetSingleListChoice(ListStructure *listp, int *value)
{
int n, *values, retval;
n = GetListChoices(listp, &values);
if (n == 1) {
*value = values[0];
retval = RETURN_SUCCESS;
} else {
retval = RETURN_FAILURE;
}
if (n > 0) {
xfree(values);
}
return retval;
}
typedef struct {
ListStructure *listp;
void (*cbproc)();
void *anydata;
} List_CBdata;
static void list_int_cb_proc(Widget w, XtPointer client_data, XtPointer call_data)
{
int n, *values;
List_CBdata *cbdata = (List_CBdata *) client_data;
n = GetListChoices(cbdata->listp, &values);
cbdata->cbproc(n, values, cbdata->anydata);
if (n > 0) {
xfree(values);
}
}
void AddListChoiceCB(ListStructure *listp, List_CBProc cbproc, void *anydata)
{
List_CBdata *cbdata;
cbdata = xmalloc(sizeof(List_CBdata));
cbdata->listp = listp;
cbdata->cbproc = (List_CBProc) cbproc;
cbdata->anydata = anydata;
XtAddCallback(listp->list,
XmNsingleSelectionCallback, list_int_cb_proc, (XtPointer) cbdata);
XtAddCallback(listp->list,
XmNmultipleSelectionCallback, list_int_cb_proc, (XtPointer) cbdata);
XtAddCallback(listp->list,
XmNextendedSelectionCallback, list_int_cb_proc, (XtPointer) cbdata);
}
static void spin_arrow_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
SpinStructure *spinp;
double value, incr;
spinp = (SpinStructure *) client_data;
value = GetSpinChoice(spinp);
incr = spinp->incr;
if (w == spinp->arrow_up) {
incr = spinp->incr;
} else if (w == spinp->arrow_down) {
incr = -spinp->incr;
} else {
errmsg("Wrong call to spin_arrow_cb()");
return;
}
value += incr;
SetSpinChoice(spinp, value);
}
SpinStructure *CreateSpinChoice(Widget parent, char *s, int len,
int type, double min, double max, double incr)
{
SpinStructure *retval;
Widget fr, form;
XmString str;
if (min >= max) {
errmsg("min >= max in CreateSpinChoice()!");
return NULL;
}
retval = xmalloc(sizeof(SpinStructure));
retval->type = type;
retval->min = min;
retval->max = max;
retval->incr = incr;
retval->rc = XtVaCreateWidget("rc", xmRowColumnWidgetClass, parent,
XmNorientation, XmHORIZONTAL,
NULL);
str = XmStringCreateLocalized(s);
XtVaCreateManagedWidget("label", xmLabelWidgetClass, retval->rc,
XmNlabelString, str,
NULL);
XmStringFree(str);
fr = XtVaCreateWidget("fr", xmFrameWidgetClass, retval->rc,
XmNshadowType, XmSHADOW_ETCHED_OUT,
NULL);
form = XtVaCreateWidget("form", xmFormWidgetClass, fr,
NULL);
retval->text = XtVaCreateWidget("text", xmTextWidgetClass, form,
XmNtraversalOn, True,
XmNcolumns, len,
NULL);
retval->arrow_up = XtVaCreateWidget("form", xmArrowButtonGadgetClass, form,
XmNarrowDirection, XmARROW_UP,
NULL);
XtAddCallback(retval->arrow_up, XmNactivateCallback,
spin_arrow_cb, (XtPointer) retval);
retval->arrow_down = XtVaCreateWidget("form", xmArrowButtonGadgetClass, form,
XmNarrowDirection, XmARROW_DOWN,
NULL);
XtAddCallback(retval->arrow_down, XmNactivateCallback,
spin_arrow_cb, (XtPointer) retval);
XtVaSetValues(retval->text,
XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_NONE,
NULL);
XtVaSetValues(retval->arrow_down,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, retval->text,
XmNrightAttachment, XmATTACH_NONE,
NULL);
XtVaSetValues(retval->arrow_up,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, retval->arrow_down,
NULL);
XtManageChild(retval->text);
XtManageChild(retval->arrow_up);
XtManageChild(retval->arrow_down);
XtManageChild(form);
XtManageChild(fr);
XtManageChild(retval->rc);
return retval;
}
void SetSpinChoice(SpinStructure *spinp, double value)
{
char buf[64];
if (value < spinp->min) {
XBell(disp, 50);
value = spinp->min;
} else if (value > spinp->max) {
XBell(disp, 50);
value = spinp->max;
}
if (spinp->type == SPIN_TYPE_FLOAT) {
sprintf(buf, "%g", value);
} else {
sprintf(buf, "%d", (int) rint(value));
}
XmTextSetString(spinp->text, buf);
}
double GetSpinChoice(SpinStructure *spinp)
{
double retval;
xv_evalexpr(spinp->text, &retval);
if (retval < spinp->min) {
errmsg("Input value below min limit in GetSpinChoice()");
retval = spinp->min;
SetSpinChoice(spinp, retval);
} else if (retval > spinp->max) {
errmsg("Input value above max limit in GetSpinChoice()");
retval = spinp->max;
SetSpinChoice(spinp, retval);
}
if (spinp->type == SPIN_TYPE_INT) {
return rint(retval);
} else {
return retval;
}
}
TextStructure *CreateTextInput(Widget parent, char *s)
{
TextStructure *retval;
XmString str;
retval = xmalloc(sizeof(TextStructure));
retval->form = XtVaCreateWidget("form", xmFormWidgetClass, parent, NULL);
str = XmStringCreateLocalized(s);
retval->label = XtVaCreateManagedWidget("label",
xmLabelWidgetClass, retval->form,
XmNlabelString, str,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_NONE,
NULL);
XmStringFree(str);
retval->text = XtVaCreateManagedWidget("cstext",
xmTextWidgetClass, retval->form,
XmNtraversalOn, True,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, retval->label,
XmNrightAttachment, XmATTACH_FORM,
NULL);
XtManageChild(retval->form);
return retval;
}
void cstext_edit_action(Widget w, XEvent *e, String *par, Cardinal *npar)
{
create_fonttool(w);
}
static char cstext_translation_table[] = "\
Ctrl<Key>E: cstext_edit_action()";
TextStructure *CreateCSText(Widget parent, char *s)
{
TextStructure *retval;
retval = CreateTextInput(parent, s);
XtOverrideTranslations(retval->text,
XtParseTranslationTable(cstext_translation_table));
return retval;
}
char *GetTextString(TextStructure *cst)
{
static char *buf = NULL;
char *s;
s = XmTextGetString(cst->text);
buf = copy_string(buf, s);
XtFree(s);
return buf;
}
void SetTextString(TextStructure *cst, char *s)
{
XmTextSetString(cst->text, s ? s : "");
}
typedef struct {
void (*cbproc)();
void *anydata;
} Text_CBdata;
static void text_int_cb_proc(Widget w, XtPointer client_data, XtPointer call_data)
{
Text_CBdata *cbdata = (Text_CBdata *) client_data;
cbdata->cbproc(cbdata->anydata);
}
void AddTextInputCB(TextStructure *cst, Text_CBProc cbproc, void *data)
{
Text_CBdata *cbdata;
cbdata = xmalloc(sizeof(Text_CBdata));
cbdata->anydata = data;
cbdata->cbproc = cbproc;
XtAddCallback(cst->text,
XmNactivateCallback, text_int_cb_proc, (XtPointer) cbdata);
}
int GetTextCursorPos(TextStructure *cst)
{
return XmTextGetInsertionPosition(cst->text);
}
void TextInsert(TextStructure *cst, int pos, char *s)
{
XmTextInsert(cst->text, pos, s);
}
typedef struct {
void (*cbproc)();
void *anydata;
} Button_CBdata;
Widget CreateButton(Widget parent, char *label)
{
Widget button;
XmString xmstr;
xmstr = XmStringCreateLocalized(label);
button = XtVaCreateManagedWidget("button",
xmPushButtonWidgetClass, parent,
XmNalignment, XmALIGNMENT_CENTER,
XmNlabelString, xmstr,
/*
* XmNmarginLeft, 5,
* XmNmarginRight, 5,
* XmNmarginTop, 3,
* XmNmarginBottom, 2,
*/
NULL);
XmStringFree(xmstr);
return button;
}
Widget CreateBitmapButton(Widget parent,
int width, int height, const unsigned char *bits)
{
Widget button;
Pixmap pm;
Pixel fg, bg;
button = XtVaCreateManagedWidget("button",
xmPushButtonWidgetClass, parent,
XmNlabelType, XmPIXMAP,
NULL);
/*
* We need to get right fore- and background colors for pixmap.
*/
XtVaGetValues(button,
XmNforeground, &fg,
XmNbackground, &bg,
NULL);
pm = XCreatePixmapFromBitmapData(disp,
root, (char *) bits, width, height, fg, bg, depth);
XtVaSetValues(button, XmNlabelPixmap, pm, NULL);
return button;
}
static void button_int_cb_proc(Widget w, XtPointer client_data, XtPointer call_data)
{
Button_CBdata *cbdata = (Button_CBdata *) client_data;
cbdata->cbproc(cbdata->anydata);
}
void AddButtonCB(Widget button, Button_CBProc cbproc, void *data)
{
Button_CBdata *cbdata;
cbdata = xmalloc(sizeof(Button_CBdata));
cbdata->anydata = data;
cbdata->cbproc = cbproc;
XtAddCallback(button,
XmNactivateCallback, button_int_cb_proc, (XtPointer) cbdata);
}
static void fsb_setcwd_cb(void *data)
{
char *bufp;
XmString directory;
Widget fsb = (Widget) data;
XtVaGetValues(fsb, XmNdirectory, &directory, NULL);
bufp = GetStringSimple(directory);
XmStringFree(directory);
if (bufp != NULL) {
set_workingdir(bufp);
XtFree(bufp);
}
}
#define FSB_CWD 0
#define FSB_HOME 1
#define FSB_ROOT 2
#define FSB_CYGDRV 3
static void fsb_cd_cb(int value, void *data)
{
char *bufp;
XmString dir, pattern, dirmask;
Widget FSB = (Widget) data;
switch (value) {
case FSB_CWD:
bufp = get_workingdir();
break;
case FSB_HOME:
bufp = get_userhome();
break;
case FSB_ROOT:
bufp = "/";
break;
case FSB_CYGDRV:
bufp = "/cygdrive/";
break;
default:
return;
}
XtVaGetValues(FSB, XmNpattern, &pattern, NULL);
dir = XmStringCreateLocalized(bufp);
dirmask = XmStringConcatAndFree(dir, pattern);
XmFileSelectionDoSearch(FSB, dirmask);
XmStringFree(dirmask);
}
static OptionItem fsb_items[] = {
{FSB_CWD, "Cwd"},
{FSB_HOME, "Home"},
{FSB_ROOT, "/"}
#ifdef __CYGWIN__
,{FSB_CYGDRV, "My Computer"}
#endif
};
#define FSB_ITEMS_NUM sizeof(fsb_items)/sizeof(OptionItem)
#if XmVersion >= 2000
static void show_hidden_cb(int onoff, void *data)
{
FSBStructure *fsb = (FSBStructure *) data;
XtVaSetValues(fsb->FSB, XmNfileFilterStyle,
onoff ? XmFILTER_NONE:XmFILTER_HIDDEN_FILES, NULL);
}
#endif
FSBStructure *CreateFileSelectionBox(Widget parent, char *s)
{
FSBStructure *retval;
OptionStructure *opt;
Widget fr, form, button;
XmString xmstr;
char *bufp, *resname;
retval = xmalloc(sizeof(FSBStructure));
resname = label_to_resname(s, "FSB");
retval->FSB = XmCreateFileSelectionDialog(parent, resname, NULL, 0);
xfree(resname);
retval->dialog = XtParent(retval->FSB);
handle_close(retval->dialog);
bufp = copy_string(NULL, "Grace: ");
bufp = concat_strings(bufp, s);
XtVaSetValues(retval->dialog, XmNtitle, bufp, NULL);
xfree(bufp);
xmstr = XmStringCreateLocalized(get_workingdir());
XtVaSetValues(retval->FSB, XmNdirectory, xmstr, NULL);
XmStringFree(xmstr);
XtAddCallback(retval->FSB,
XmNcancelCallback, destroy_dialog, retval->dialog);
AddHelpCB(retval->FSB, "doc/UsersGuide.html#FS-dialog");
retval->rc = XmCreateRowColumn(retval->FSB, "rc", NULL, 0);
#if XmVersion >= 2000
button = CreateToggleButton(retval->rc, "Show hidden files");
AddToggleButtonCB(button, show_hidden_cb, retval);
XtVaSetValues(retval->FSB, XmNfileFilterStyle, XmFILTER_HIDDEN_FILES, NULL);
#endif
fr = CreateFrame(retval->rc, NULL);
form = XtVaCreateWidget("form", xmFormWidgetClass, fr, NULL);
opt = CreateOptionChoice(form, "Chdir to:", 1, FSB_ITEMS_NUM, fsb_items);
AddOptionChoiceCB(opt, fsb_cd_cb, (void *) retval->FSB);
button = CreateButton(form, "Set as cwd");
AddButtonCB(button, fsb_setcwd_cb, (void *) retval->FSB);
XtVaSetValues(opt->menu,
XmNleftAttachment, XmATTACH_FORM,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_NONE,
NULL);
XtVaSetValues(button,
XmNleftAttachment, XmATTACH_NONE,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
NULL);
XtManageChild(form);
XtManageChild(retval->rc);
return retval;
}
typedef struct {
FSBStructure *fsb;
int (*cbproc)();
void *anydata;
} FSB_CBdata;
static void fsb_int_cb_proc(Widget w, XtPointer client_data, XtPointer call_data)
{
char *s;
int ok;
FSB_CBdata *cbdata = (FSB_CBdata *) client_data;
XmFileSelectionBoxCallbackStruct *cbs =
(XmFileSelectionBoxCallbackStruct *) call_data;
s = GetStringSimple(cbs->value);
if (s == NULL) {
errmsg("Error converting XmString to char string");
return;
}
set_wait_cursor();
ok = cbdata->cbproc(s, cbdata->anydata);
XtFree(s);
if (ok) {
XtUnmanageChild(cbdata->fsb->dialog);
}
unset_wait_cursor();
}
void AddFileSelectionBoxCB(FSBStructure *fsb, FSB_CBProc cbproc, void *anydata)
{
FSB_CBdata *cbdata;
cbdata = xmalloc(sizeof(FSB_CBdata));
cbdata->fsb = fsb;
cbdata->cbproc = (FSB_CBProc) cbproc;
cbdata->anydata = anydata;
XtAddCallback(fsb->FSB,
XmNokCallback, fsb_int_cb_proc, (XtPointer) cbdata);
}
void SetFileSelectionBoxPattern(FSBStructure *fsb, char *pattern)
{
XmString xmstr;
if (pattern != NULL) {
xmstr = XmStringCreateLocalized(pattern);
XtVaSetValues(fsb->FSB, XmNpattern, xmstr, NULL);
XmStringFree(xmstr);
}
}
Widget CreateLabel(Widget parent, char *s)
{
Widget label;
label = XtVaCreateManagedWidget(s,
xmLabelWidgetClass, parent,
XmNalignment, XmALIGNMENT_BEGINNING,
XmNrecomputeSize, True,
NULL);
return label;
}
void AlignLabel(Widget w, int alignment)
{
unsigned char xm_alignment;
switch(alignment) {
case ALIGN_BEGINNING:
xm_alignment = XmALIGNMENT_BEGINNING;
break;
case ALIGN_CENTER:
xm_alignment = XmALIGNMENT_CENTER;
break;
case ALIGN_END:
xm_alignment = XmALIGNMENT_END;
break;
default:
errmsg("Internal error in AlignLabel()");
return;
break;
}
XtVaSetValues(w,
XmNalignment, xm_alignment,
NULL);
}
static OptionItem *font_option_items;
static OptionItem *settype_option_items;
static BitmapOptionItem *pattern_option_items;
static BitmapOptionItem *lines_option_items;
#define LINES_BM_HEIGHT 15
#define LINES_BM_WIDTH 64
int init_option_menus(void) {
int i, j, k, l, n;
n = number_of_fonts();
font_option_items = xmalloc(n*sizeof(OptionItem));
if (font_option_items == NULL) {
errmsg("Malloc error in init_option_menus()");
return RETURN_FAILURE;
}
for (i = 0; i < n; i++) {
font_option_items[i].value = i;
font_option_items[i].label = get_fontalias(i);
}
n = number_of_patterns();
pattern_option_items = xmalloc(n*sizeof(BitmapOptionItem));
if (pattern_option_items == NULL) {
errmsg("Malloc error in init_option_menus()");
xfree(font_option_items);
return RETURN_FAILURE;
}
for (i = 0; i < n; i++) {
pattern_option_items[i].value = i;
if (i == 0) {
pattern_option_items[i].bitmap = NULL;
} else {
pattern_option_items[i].bitmap = pat_bits[i];
}
}
n = number_of_linestyles();
lines_option_items = xmalloc(n*sizeof(BitmapOptionItem));
if (lines_option_items == NULL) {
errmsg("Malloc error in init_option_menus()");
xfree(pattern_option_items);
xfree(font_option_items);
return RETURN_FAILURE;
}
for (i = 0; i < n; i++) {
lines_option_items[i].value = i;
if (i == 0) {
lines_option_items[i].bitmap = NULL;
continue;
}
lines_option_items[i].bitmap =
xcalloc(LINES_BM_HEIGHT*LINES_BM_WIDTH/8/SIZEOF_CHAR, SIZEOF_CHAR);
k = LINES_BM_WIDTH*(LINES_BM_HEIGHT/2);
while (k < LINES_BM_WIDTH*(LINES_BM_HEIGHT/2 + 1)) {
for (j = 0; j < dash_array_length[i]; j++) {
for (l = 0; l < dash_array[i][j]; l++) {
if (k < LINES_BM_WIDTH*(LINES_BM_HEIGHT/2 + 1)) {
if (j % 2 == 0) {
/* black */
lines_option_items[i].bitmap[k/8] |= 1 << k % 8;
}
k++;
}
}
}
}
}
settype_option_items = xmalloc(NUMBER_OF_SETTYPES*sizeof(OptionItem));
if (settype_option_items == NULL) {
errmsg("Malloc error in init_option_menus()");
return RETURN_FAILURE;
}
for (i = 0; i < NUMBER_OF_SETTYPES; i++) {
settype_option_items[i].value = i;
settype_option_items[i].label = copy_string(NULL, set_types(i));
lowtoupper(settype_option_items[i].label);
}
return RETURN_SUCCESS;
}
OptionStructure *CreateFontChoice(Widget parent, char *s)
{
return (CreateOptionChoice(parent,
s, 0, number_of_fonts(), font_option_items));
}
OptionStructure *CreatePatternChoice(Widget parent, char *s)
{
return (CreateBitmapOptionChoice(parent, s, 4, number_of_patterns(),
16, 16, pattern_option_items));
}
OptionStructure *CreateLineStyleChoice(Widget parent, char *s)
{
return (CreateBitmapOptionChoice(parent, s, 0, number_of_linestyles(),
LINES_BM_WIDTH, LINES_BM_HEIGHT, lines_option_items));
}
OptionStructure *CreateSetTypeChoice(Widget parent, char *s)
{
return (CreateOptionChoice(parent,
s, 0, NUMBER_OF_SETTYPES, settype_option_items));
}
static BitmapOptionItem just_option_items[12] =
{
{JUST_LEFT |JUST_BLINE , j_lm_o_bits},
{JUST_CENTER|JUST_BLINE , j_cm_o_bits},
{JUST_RIGHT |JUST_BLINE , j_rm_o_bits},
{JUST_LEFT |JUST_BOTTOM, j_lb_b_bits},
{JUST_CENTER|JUST_BOTTOM, j_cb_b_bits},
{JUST_RIGHT |JUST_BOTTOM, j_rb_b_bits},
{JUST_LEFT |JUST_MIDDLE, j_lm_b_bits},
{JUST_CENTER|JUST_MIDDLE, j_cm_b_bits},
{JUST_RIGHT |JUST_MIDDLE, j_rm_b_bits},
{JUST_LEFT |JUST_TOP , j_lt_b_bits},
{JUST_CENTER|JUST_TOP , j_ct_b_bits},
{JUST_RIGHT |JUST_TOP , j_rt_b_bits}
};
OptionStructure *CreateJustChoice(Widget parent, char *s)
{
return (CreateBitmapOptionChoice(parent, s, 4,
12, JBITMAP_WIDTH, JBITMAP_HEIGHT, just_option_items));
}
RestrictionStructure *CreateRestrictionChoice(Widget parent, char *s)
{
RestrictionStructure *retval;
Widget rc;
OptionItem restr_items[7];
restr_items[0].value = RESTRICT_NONE;
restr_items[0].label = "None";
restr_items[1].value = RESTRICT_REG0;
restr_items[1].label = "Region 0";
restr_items[2].value = RESTRICT_REG1;
restr_items[2].label = "Region 1";
restr_items[3].value = RESTRICT_REG2;
restr_items[3].label = "Region 2";
restr_items[4].value = RESTRICT_REG3;
restr_items[4].label = "Region 3";
restr_items[5].value = RESTRICT_REG4;
restr_items[5].label = "Region 4";
restr_items[6].value = RESTRICT_WORLD;
restr_items[6].label = "Inside graph";
retval = xmalloc(sizeof(RestrictionStructure));
retval->frame = CreateFrame(parent, s);
rc = XtVaCreateWidget("rc",
xmRowColumnWidgetClass, retval->frame,
XmNorientation, XmHORIZONTAL,
NULL);
retval->r_sel = CreateOptionChoice(rc,
"Restriction:", 1, 7, restr_items);
retval->negate = CreateToggleButton(rc, "Negated");
XtManageChild(rc);
return retval;
}
static OptionItem *graph_select_items = NULL;
static int ngraph_select_items = 0;
static ListStructure **graph_selectors = NULL;
static int ngraph_selectors = 0;
void graph_select_cb(Widget list, XtPointer client_data, XtPointer call_data)
{
XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
ListStructure *plist = (ListStructure *) client_data;
int gno;
gno = plist->values[cbs->item_position - 1];
switch_current_graph(gno);
}
void update_graph_selectors(void)
{
int i, new_n = number_of_graphs();
char buf[64];
OptionItem *p;
for (i = 0; i < ngraph_select_items; i++) {
xfree(graph_select_items[i].label);
}
p = xrealloc(graph_select_items, new_n*sizeof(OptionItem));
if (p == NULL && new_n != 0) {
ngraph_select_items = 0;
return;
} else {
graph_select_items = p;
}
for (i = 0; i < new_n; i++) {
graph_select_items[i].value = i;
sprintf(buf, "(%c) G%d (%d sets)",
is_graph_hidden(i) ? '-':'+', i, number_of_sets(i));
graph_select_items[i].label = copy_string(NULL, buf);
}
ngraph_select_items = new_n;
for (i = 0; i < ngraph_selectors; i++) {
UpdateListChoice(graph_selectors[i],
ngraph_select_items, graph_select_items);
}
}
typedef struct {
Widget popup;
Widget label_item;
Widget focus_item;
Widget hide_item;
Widget show_item;
Widget duplicate_item;
Widget kill_item;
Widget copy12_item;
Widget copy21_item;
Widget move12_item;
Widget move21_item;
Widget swap_item;
} GraphPopupMenu;
typedef enum {
GraphMenuFocusCB,
GraphMenuHideCB,
GraphMenuShowCB,
GraphMenuDuplicateCB,
GraphMenuKillCB,
GraphMenuCopy12CB,
GraphMenuCopy21CB,
GraphMenuMove12CB,
GraphMenuMove21CB,
GraphMenuSwapCB,
GraphMenuNewCB
} GraphMenuCBtype;
void graph_menu_cb(ListStructure *listp, GraphMenuCBtype type)
{
int err = FALSE;
int i, n, *values;
char buf[32];
n = GetListChoices(listp, &values);
switch (type) {
case GraphMenuFocusCB:
if (n == 1) {
switch_current_graph(values[0]);
} else {
err = TRUE;
}
break;
case GraphMenuHideCB:
if (n > 0) {
for (i = 0; i < n; i++) {
set_graph_hidden(values[i], TRUE);
}
} else {
err = TRUE;
}
break;
case GraphMenuShowCB:
if (n > 0) {
for (i = 0; i < n; i++) {
set_graph_hidden(values[i], FALSE);
}
} else {
err = TRUE;
}
break;
case GraphMenuDuplicateCB:
if (n > 0) {
for (i = 0; i < n; i++) {
duplicate_graph(values[i]);
}
} else {
err = TRUE;
}
break;
case GraphMenuKillCB:
if (n > 0) {
if (yesno("Kill selected graph(s)?", NULL, NULL, NULL)) {
for (i = n - 1; i >= 0; i--) {
kill_graph(values[i]);
}
}
} else {
err = TRUE;
}
break;
case GraphMenuCopy12CB:
if (n == 2) {
sprintf(buf, "Overwrite G%d?", values[1]);
if (yesno(buf, NULL, NULL, NULL)) {
copy_graph(values[0], values[1]);
}
} else {
err = TRUE;
}
break;
case GraphMenuCopy21CB:
if (n == 2) {
sprintf(buf, "Overwrite G%d?", values[0]);
if (yesno(buf, NULL, NULL, NULL)) {
copy_graph(values[1], values[0]);
}
} else {
err = TRUE;
}
break;
case GraphMenuMove12CB:
if (n == 2) {
sprintf(buf, "Replace G%d?", values[1]);
if (yesno(buf, NULL, NULL, NULL)) {
move_graph(values[0], values[1]);
}
} else {
err = TRUE;
}
break;
case GraphMenuMove21CB:
if (n == 2) {
sprintf(buf, "Replace G%d?", values[0]);
if (yesno(buf, NULL, NULL, NULL)) {
move_graph(values[1], values[0]);
}
} else {
err = TRUE;
}
break;
case GraphMenuSwapCB:
if (n == 2) {
swap_graph(values[0], values[1]);
} else {
err = TRUE;
}
break;
case GraphMenuNewCB:
set_graph_active(number_of_graphs());
break;
default:
err = TRUE;
break;
}
if (n > 0) {
xfree(values);
}
if (err == FALSE) {
update_all();
xdrawgraph();
}
}
void switch_focus_proc(void *data)
{
graph_menu_cb((ListStructure *) data, GraphMenuFocusCB);
}
void hide_graph_proc(void *data)
{
graph_menu_cb((ListStructure *) data, GraphMenuHideCB);
}
void show_graph_proc(void *data)
{
graph_menu_cb((ListStructure *) data, GraphMenuShowCB);
}
void duplicate_graph_proc(void *data)
{
graph_menu_cb((ListStructure *) data, GraphMenuDuplicateCB);
}
void kill_graph_proc(void *data)
{
graph_menu_cb((ListStructure *) data, GraphMenuKillCB);
}
void copy12_graph_proc(void *data)
{
graph_menu_cb((ListStructure *) data, GraphMenuCopy12CB);
}
void copy21_graph_proc(void *data)
{
graph_menu_cb((ListStructure *) data, GraphMenuCopy21CB);
}
void move12_graph_proc(void *data)
{
graph_menu_cb((ListStructure *) data, GraphMenuMove12CB);
}
void move21_graph_proc(void *data)
{
graph_menu_cb((ListStructure *) data, GraphMenuMove21CB);
}
void swap_graph_proc(void *data)
{
graph_menu_cb((ListStructure *) data, GraphMenuSwapCB);
}
void create_new_graph_proc(void *data)
{
graph_menu_cb((ListStructure *) data, GraphMenuNewCB);
}
GraphPopupMenu *CreateGraphPopupEntries(ListStructure *listp)
{
GraphPopupMenu *graph_popup_menu;
Widget popup;
graph_popup_menu = xmalloc(sizeof(GraphPopupMenu));
popup = XmCreatePopupMenu(listp->list, "graphPopupMenu", NULL, 0);
graph_popup_menu->popup = popup;
graph_popup_menu->label_item = CreateMenuLabel(popup, "Selection:");
CreateMenuSeparator(popup);
graph_popup_menu->focus_item = CreateMenuButton(popup, "Focus to", 'F',
switch_focus_proc, (void *) listp);
CreateMenuSeparator(popup);
graph_popup_menu->hide_item = CreateMenuButton(popup, "Hide", 'H',
hide_graph_proc, (void *) listp);
graph_popup_menu->show_item = CreateMenuButton(popup, "Show", 'S',
show_graph_proc, (void *) listp);
graph_popup_menu->duplicate_item = CreateMenuButton(popup,"Duplicate", 'D',
duplicate_graph_proc, (void *) listp);
graph_popup_menu->kill_item = CreateMenuButton(popup, "Kill", 'K',
kill_graph_proc, (void *) listp);
CreateMenuSeparator(popup);
graph_popup_menu->copy12_item = CreateMenuButton(popup, "Copy 1 to 2", '\0',
copy12_graph_proc, (void *) listp);
graph_popup_menu->copy21_item = CreateMenuButton(popup, "Copy 2 to 1", '\0',
copy21_graph_proc, (void *) listp);
graph_popup_menu->move12_item = CreateMenuButton(popup, "Move 1 to 2", '\0',
move12_graph_proc, (void *) listp);
graph_popup_menu->move21_item = CreateMenuButton(popup, "Move 2 to 1", '\0',
move21_graph_proc, (void *) listp);
graph_popup_menu->swap_item = CreateMenuButton(popup, "Swap", 'w',
swap_graph_proc, (void *) listp);
CreateMenuSeparator(popup);
CreateMenuButton(popup, "Create new", 'C',
create_new_graph_proc, (void *) listp);
return graph_popup_menu;
}
void graph_popup(Widget parent, ListStructure *listp, XButtonPressedEvent *event)
{
int i, n;
int *values;
char buf[64];
Widget popup;
GraphPopupMenu* graph_popup_menu;
if (event->button != 3) {
return;
}
graph_popup_menu = (GraphPopupMenu*) listp->anydata;
popup = graph_popup_menu->popup;
n = GetListChoices(listp, &values);
if (n > 0) {
sprintf(buf, "G%d", values[0]);
for (i = 1; i < n; i++) {
if (strlen(buf) > 30) {
strcat(buf, "...");
break;
}
sprintf(buf, "%s, G%d", buf, values[i]);
}
} else {
strcpy(buf, "None");
}
SetLabel(graph_popup_menu->label_item, buf);
if (n == 0) {
XtSetSensitive(graph_popup_menu->hide_item, False);
XtSetSensitive(graph_popup_menu->show_item, False);
XtSetSensitive(graph_popup_menu->duplicate_item, False);
XtSetSensitive(graph_popup_menu->kill_item, False);
} else {
XtSetSensitive(graph_popup_menu->hide_item, True);
XtSetSensitive(graph_popup_menu->show_item, True);
XtSetSensitive(graph_popup_menu->duplicate_item, True);
XtSetSensitive(graph_popup_menu->kill_item, True);
}
if (n == 1) {
XtSetSensitive(graph_popup_menu->focus_item, True);
} else {
XtSetSensitive(graph_popup_menu->focus_item, False);
}
if (n == 2) {
sprintf(buf, "Copy G%d to G%d", values[0], values[1]);
SetLabel(graph_popup_menu->copy12_item, buf);
XtManageChild(graph_popup_menu->copy12_item);
sprintf(buf, "Copy G%d to G%d", values[1], values[0]);
SetLabel(graph_popup_menu->copy21_item, buf);
XtManageChild(graph_popup_menu->copy21_item);
sprintf(buf, "Move G%d to G%d", values[0], values[1]);
SetLabel(graph_popup_menu->move12_item, buf);
XtManageChild(graph_popup_menu->move12_item);
sprintf(buf, "Move G%d to G%d", values[1], values[0]);
SetLabel(graph_popup_menu->move21_item, buf);
XtManageChild(graph_popup_menu->move21_item);
XtSetSensitive(graph_popup_menu->swap_item, True);
} else {
XtUnmanageChild(graph_popup_menu->copy12_item);
XtUnmanageChild(graph_popup_menu->copy21_item);
XtUnmanageChild(graph_popup_menu->move12_item);
XtUnmanageChild(graph_popup_menu->move21_item);
XtSetSensitive(graph_popup_menu->swap_item, False);
}
if (n > 0) {
xfree(values);
}
XmMenuPosition(popup, event);
XtManageChild(popup);
}
static void list_selectall(Widget list)
{
int i, n;
unsigned char selection_type_save;
XtVaGetValues(list,
XmNselectionPolicy, &selection_type_save,
XmNitemCount, &n,
NULL);
if (selection_type_save == XmSINGLE_SELECT) {
XBell(disp, 50);
return;
}
XtVaSetValues(list, XmNselectionPolicy, XmMULTIPLE_SELECT, NULL);
XmListDeselectAllItems(list);
for (i = 1; i <= n; i++) {
XmListSelectPos(list, i, False);
}
XtVaSetValues(list, XmNselectionPolicy, selection_type_save, NULL);
}
void list_selectall_action(Widget w, XEvent *e, String *par, Cardinal *npar)
{
list_selectall(w);
}
static void list_selectall_cb(void *data)
{
ListStructure *listp = (ListStructure *) data;
list_selectall(listp->list);
}
static void list_unselectall(Widget list)
{
XmListDeselectAllItems(list);
}
void list_unselectall_action(Widget w, XEvent *e, String *par, Cardinal *npar)
{
list_unselectall(w);
}
static void list_unselectall_cb(void *data)
{
ListStructure *listp = (ListStructure *) data;
list_unselectall(listp->list);
}
static void list_invertselection(Widget list)
{
int i, n;
unsigned char selection_type_save;
XtVaGetValues(list,
XmNselectionPolicy, &selection_type_save,
XmNitemCount, &n,
NULL);
if (selection_type_save == XmSINGLE_SELECT) {
XBell(disp, 50);
return;
}
XtVaSetValues(list, XmNselectionPolicy, XmMULTIPLE_SELECT, NULL);
for (i = 0; i < n; i++) {
XmListSelectPos(list, i, False);
}
XtVaSetValues(list, XmNselectionPolicy, selection_type_save, NULL);
}
static void list_invertselection_cb(void *data)
{
ListStructure *listp = (ListStructure *) data;
list_invertselection(listp->list);
}
void list_invertselection_action(Widget w, XEvent *e, String *par,
Cardinal *npar)
{
list_invertselection(w);
}
void set_graph_selectors(int gno)
{
int i;
for (i = 0; i < ngraph_selectors; i++) {
SelectListChoice(graph_selectors[i], gno);
}
}
ListStructure *CreateGraphChoice(Widget parent, char *labelstr, int type)
{
ListStructure *retvalp;
int nvisible;
ngraph_selectors++;
graph_selectors = xrealloc(graph_selectors,
ngraph_selectors*sizeof(ListStructure *));
nvisible = (type == LIST_TYPE_SINGLE) ? 2 : 4;
retvalp = CreateListChoice(parent, labelstr, type, nvisible,
ngraph_select_items, graph_select_items);
if (retvalp == NULL) {
return NULL;
}
AddHelpCB(retvalp->rc, "doc/UsersGuide.html#graph-selector");
graph_selectors[ngraph_selectors - 1] = retvalp;
XtAddCallback(retvalp->list, XmNdefaultActionCallback,
graph_select_cb, retvalp);
retvalp->anydata = CreateGraphPopupEntries(retvalp);
XtAddEventHandler(retvalp->list, ButtonPressMask, False,
(XtEventHandler) graph_popup, retvalp);
if (ngraph_select_items == 0) {
update_graph_selectors();
} else {
UpdateListChoice(retvalp, ngraph_select_items, graph_select_items);
}
SelectListChoice(retvalp, get_cg());
return retvalp;
}
/* Set selectors */
static ListStructure **set_selectors = NULL;
static int nset_selectors = 0;
void UpdateSetChoice(ListStructure *listp, int gno)
{
int i, j, n = number_of_sets(gno);
char buf[64];
OptionItem *set_select_items;
SetChoiceData *sdata;
sdata = (SetChoiceData *) listp->anydata;
sdata->gno = gno;
if (n <= 0) {
UpdateListChoice(listp, 0, NULL);
return;
}
set_select_items = xmalloc(n*sizeof(OptionItem));
if (set_select_items == NULL) {
return;
}
for (i = 0, j = 0; i < n; i++) {
if ((sdata->show_nodata == TRUE || is_set_active(gno, i) == TRUE) &&
(sdata->show_hidden == TRUE || is_set_hidden(gno, i) != TRUE )) {
set_select_items[j].value = i;
sprintf(buf, "(%c) G%d.S%d[%d][%d]",
is_set_hidden(gno, i) ? '-':'+',
gno, i, dataset_cols(gno, i), getsetlength(gno, i));
set_select_items[j].label = copy_string(NULL, buf);
if (sdata->view_comments == TRUE) {
set_select_items[j].label =
concat_strings(set_select_items[j].label, " \"");
set_select_items[j].label =
concat_strings(set_select_items[j].label,
getcomment(gno, i));
set_select_items[j].label =
concat_strings(set_select_items[j].label, "\"");
}
j++;
}
}
UpdateListChoice(listp, j, set_select_items);
xfree(set_select_items);
}
void update_set_selectors(int gno)
{
int i, cg;
SetChoiceData *sdata;
cg = get_cg();
update_graph_selectors();
for (i = 0; i < nset_selectors; i++) {
sdata = (SetChoiceData *) set_selectors[i]->anydata;
if (sdata->standalone == TRUE && (gno == cg || gno == ALL_GRAPHS)) {
UpdateSetChoice(set_selectors[i], cg);
} else if (sdata->standalone == FALSE && sdata->gno == gno) {
UpdateSetChoice(set_selectors[i], gno);
}
}
}
void set_menu_cb(ListStructure *listp, SetMenuCBtype type)
{
SetChoiceData *sdata;
int err = FALSE;
int gno;
int i, n, setno, *values;
char buf[32];
n = GetListChoices(listp, &values);
sdata = (SetChoiceData *) listp->anydata;
gno = sdata->gno;
switch (type) {
case SetMenuHideCB:
if (n > 0) {
for (i = 0; i < n; i++) {
set_set_hidden(gno, values[i], TRUE);
}
} else {
err = TRUE;
}
break;
case SetMenuShowCB:
if (n > 0) {
for (i = 0; i < n; i++) {
set_set_hidden(gno, values[i], FALSE);
}
} else {
err = TRUE;
}
break;
case SetMenuBringfCB:
if (n == 1) {
pushset(gno, values[0], PUSH_SET_TOFRONT);
} else {
err = TRUE;
}
break;
case SetMenuSendbCB:
if (n == 1) {
pushset(gno, values[0], PUSH_SET_TOBACK);
} else {
err = TRUE;
}
break;
case SetMenuDuplicateCB:
if (n > 0) {
for (i = 0; i < n; i++) {
setno = nextset(gno);
do_copyset(gno, values[i], gno, setno);
}
} else {
err = TRUE;
}
break;
case SetMenuKillCB:
if (n > 0) {
if (yesno("Kill selected set(s)?", NULL, NULL, NULL)) {
for (i = 0; i < n; i++) {
killset(gno, values[i]);
}
}
} else {
err = TRUE;
}
break;
case SetMenuKillDCB:
if (n > 0) {
if (yesno("Kill data in selected set(s)?", NULL, NULL, NULL)) {
for (i = 0; i < n; i++) {
killsetdata(gno, values[i]);
}
}
} else {
err = TRUE;
}
break;
case SetMenuCopy12CB:
if (n == 2) {
sprintf(buf, "Overwrite S%d?", values[1]);
if (yesno(buf, NULL, NULL, NULL)) {
do_copyset(gno, values[0], gno, values[1]);
}
} else {
err = TRUE;
}
break;
case SetMenuCopy21CB:
if (n == 2) {
sprintf(buf, "Overwrite S%d?", values[0]);
if (yesno(buf, NULL, NULL, NULL)) {
do_copyset(gno, values[1], gno, values[0]);
}
} else {
err = TRUE;
}
break;
case SetMenuMove12CB:
if (n == 2) {
sprintf(buf, "Replace S%d?", values[1]);
if (yesno(buf, NULL, NULL, NULL)) {
moveset(gno, values[0], gno, values[1]);
}
} else {
err = TRUE;
}
break;
case SetMenuMove21CB:
if (n == 2) {
sprintf(buf, "Replace S%d?", values[0]);
if (yesno(buf, NULL, NULL, NULL)) {
moveset(gno, values[1], gno, values[0]);
}
} else {
err = TRUE;
}
break;
case SetMenuSwapCB:
if (n == 2) {
swapset(gno, values[0], gno, values[1]);
} else {
err = TRUE;
}
break;
case SetMenuNewFCB:
create_leval_frame((void *) gno);
break;
case SetMenuNewSCB:
if ((setno = nextset(gno)) != -1) {
setcomment(gno, setno, "Editor");
set_set_hidden(gno, setno, FALSE);
create_ss_frame(gno, setno);
} else {
err = TRUE;
}
break;
case SetMenuNewECB:
if ((setno = nextset(gno)) != -1) {
setcomment(gno, setno, "Editor");
set_set_hidden(gno, setno, FALSE);
do_ext_editor(gno, setno);
} else {
err = TRUE;
}
break;
case SetMenuNewBCB:
create_eblock_frame(gno);
break;
case SetMenuEditSCB:
if (n == 1) {
create_ss_frame(gno, values[0]);
} else {
err = TRUE;
}
break;
case SetMenuEditECB:
if (n == 1) {
do_ext_editor(gno, values[0]);
} else {
err = TRUE;
}
break;
case SetMenuPackCB:
packsets(gno);
break;
default:
err = TRUE;
break;
}
if (n > 0) {
xfree(values);
}
if (err == FALSE) {
update_all();
xdrawgraph();
}
}
void hide_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuHideCB);
}
void show_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuShowCB);
}
void bringf_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuBringfCB);
}
void sendb_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuSendbCB);
}
void duplicate_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuDuplicateCB);
}
void kill_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuKillCB);
}
void killd_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuKillDCB);
}
void copy12_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuCopy12CB);
}
void copy21_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuCopy21CB);
}
void move12_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuMove12CB);
}
void move21_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuMove21CB);
}
void swap_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuSwapCB);
}
void newF_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuNewFCB);
}
void newS_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuNewSCB);
}
void newE_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuNewECB);
}
void newB_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuNewBCB);
}
void editS_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuEditSCB);
}
void editE_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuEditECB);
}
void pack_set_proc(void *data)
{
set_menu_cb((ListStructure *) data, SetMenuPackCB);
}
void shownd_set_proc(int onoff, void *data)
{
ListStructure *listp = (ListStructure *) data;
SetChoiceData *sdata = (SetChoiceData *) listp->anydata;
sdata->show_nodata = onoff;
UpdateSetChoice(listp, sdata->gno);
}
void showh_set_proc(int onoff, void *data)
{
ListStructure *listp = (ListStructure *) data;
SetChoiceData *sdata = (SetChoiceData *) listp->anydata;
sdata->show_hidden = onoff;
UpdateSetChoice(listp, sdata->gno);
}
void view_comments_set_proc(int onoff, void *data)
{
ListStructure *listp = (ListStructure *) data;
SetChoiceData *sdata = (SetChoiceData *) listp->anydata;
sdata->view_comments = onoff;
UpdateSetChoice(listp, sdata->gno);
}
void update_set_proc(void *data)
{
ListStructure *listp = (ListStructure *) data;
SetChoiceData *sdata = (SetChoiceData *) listp->anydata;
UpdateSetChoice(listp, sdata->gno);
}
SetPopupMenu *CreateSetPopupEntries(ListStructure *listp)
{
SetPopupMenu *set_popup_menu;
Widget popup, submenupane;
set_popup_menu = xmalloc(sizeof(SetPopupMenu));
popup = XmCreatePopupMenu(listp->list, "setPopupMenu", NULL, 0);
set_popup_menu->popup = popup;
set_popup_menu->label_item = CreateMenuLabel(popup, "Selection:");
CreateMenuSeparator(popup);
set_popup_menu->hide_item = CreateMenuButton(popup, "Hide", '\0',
hide_set_proc, (void *) listp);
set_popup_menu->show_item = CreateMenuButton(popup, "Show", '\0',
show_set_proc, (void *) listp);
set_popup_menu->bringf_item = CreateMenuButton(popup, "Bring to front", '\0',
bringf_set_proc, (void *) listp);
set_popup_menu->sendb_item = CreateMenuButton(popup, "Send to back", '\0',
sendb_set_proc, (void *) listp);
CreateMenuSeparator(popup);
set_popup_menu->duplicate_item = CreateMenuButton(popup, "Duplicate", '\0',
duplicate_set_proc, (void *) listp);
set_popup_menu->kill_item = CreateMenuButton(popup, "Kill", '\0',
kill_set_proc, (void *) listp);
set_popup_menu->killd_item = CreateMenuButton(popup, "Kill data", '\0',
killd_set_proc, (void *) listp);
CreateMenuSeparator(popup);
set_popup_menu->copy12_item = CreateMenuButton(popup, "Copy 1 to 2", '\0',
copy12_set_proc, (void *) listp);
set_popup_menu->copy21_item = CreateMenuButton(popup, "Copy 2 to 1", '\0',
copy21_set_proc, (void *) listp);
set_popup_menu->move12_item = CreateMenuButton(popup, "Move 1 to 2", '\0',
move12_set_proc, (void *) listp);
set_popup_menu->move21_item = CreateMenuButton(popup, "Move 2 to 1", '\0',
move21_set_proc, (void *) listp);
set_popup_menu->swap_item = CreateMenuButton(popup, "Swap", '\0',
swap_set_proc, (void *) listp);
CreateMenuSeparator(popup);
set_popup_menu->edit_item = CreateMenu(popup, "Edit", 'E', FALSE);
CreateMenuButton(set_popup_menu->edit_item, "In spreadsheet", '\0',
editS_set_proc, (void *) listp);
CreateMenuButton(set_popup_menu->edit_item, "In text editor", '\0',
editE_set_proc, (void *) listp);
submenupane = CreateMenu(popup, "Create new", '\0', FALSE);
CreateMenuButton(submenupane, "By formula", '\0',
newF_set_proc, (void *) listp);
CreateMenuButton(submenupane, "In spreadsheet", '\0',
newS_set_proc, (void *) listp);
CreateMenuButton(submenupane, "In text editor", '\0',
newE_set_proc, (void *) listp);
CreateMenuButton(submenupane, "From block data", '\0',
newB_set_proc, (void *) listp);
CreateMenuSeparator(popup);
CreateMenuButton(popup, "Pack all sets", '\0',
pack_set_proc, (void *) listp);
CreateMenuSeparator(popup);
submenupane = CreateMenu(popup, "Selector operations", 'o', FALSE);
CreateMenuToggle(submenupane,
"View set comments", '\0', view_comments_set_proc, (void *) listp);
CreateMenuSeparator(submenupane);
set_popup_menu->shownd_item = CreateMenuToggle(submenupane,
"Show data-less", '\0', shownd_set_proc, (void *) listp);
set_popup_menu->showh_item = CreateMenuToggle(submenupane,
"Show hidden", '\0', showh_set_proc, (void *) listp);
CreateMenuSeparator(submenupane);
CreateMenuButton(submenupane, "Select all", '\0',
list_selectall_cb, (void *) listp);
CreateMenuButton(submenupane, "Unselect all", '\0',
list_unselectall_cb, (void *) listp);
CreateMenuButton(submenupane, "Invert selection", '\0',
list_invertselection_cb, (void *) listp);
CreateMenuSeparator(submenupane);
CreateMenuButton(submenupane, "Update", '\0',
update_set_proc, (void *) listp);
return set_popup_menu;
}
void set_popup(Widget parent, ListStructure *listp, XButtonPressedEvent *event)
{
SetChoiceData *sdata;
int i, n;
int *values;
char buf[64];
Widget popup;
SetPopupMenu* set_popup_menu;
if (event->button != 3) {
return;
}
sdata = (SetChoiceData *) listp->anydata;
set_popup_menu = sdata->menu;
popup = set_popup_menu->popup;
n = GetListChoices(listp, &values);
if (n > 0) {
sprintf(buf, "S%d", values[0]);
for (i = 1; i < n; i++) {
if (strlen(buf) > 30) {
strcat(buf, "...");
break;
}
sprintf(buf, "%s, S%d", buf, values[i]);
}
} else {
strcpy(buf, "None");
}
SetLabel(set_popup_menu->label_item, buf);
SetToggleButtonState(set_popup_menu->shownd_item, sdata->show_nodata);
SetToggleButtonState(set_popup_menu->showh_item, sdata->show_hidden);
if (n == 0) {
XtSetSensitive(set_popup_menu->hide_item, False);
XtSetSensitive(set_popup_menu->show_item, False);
XtSetSensitive(set_popup_menu->duplicate_item, False);
XtSetSensitive(set_popup_menu->kill_item, False);
XtSetSensitive(set_popup_menu->killd_item, False);
} else {
XtSetSensitive(set_popup_menu->hide_item, True);
XtSetSensitive(set_popup_menu->show_item, True);
XtSetSensitive(set_popup_menu->duplicate_item, True);
XtSetSensitive(set_popup_menu->kill_item, True);
XtSetSensitive(set_popup_menu->killd_item, True);
}
if (n == 1) {
XtSetSensitive(set_popup_menu->bringf_item, True);
XtSetSensitive(set_popup_menu->sendb_item, True);
XtSetSensitive(set_popup_menu->edit_item, True);
} else {
XtSetSensitive(set_popup_menu->bringf_item, False);
XtSetSensitive(set_popup_menu->sendb_item, False);
XtSetSensitive(set_popup_menu->edit_item, False);
}
if (n == 2) {
sprintf(buf, "Copy S%d to S%d", values[0], values[1]);
SetLabel(set_popup_menu->copy12_item, buf);
XtManageChild(set_popup_menu->copy12_item);
sprintf(buf, "Copy S%d to S%d", values[1], values[0]);
SetLabel(set_popup_menu->copy21_item, buf);
XtManageChild(set_popup_menu->copy21_item);
sprintf(buf, "Move S%d to S%d", values[0], values[1]);
SetLabel(set_popup_menu->move12_item, buf);
XtManageChild(set_popup_menu->move12_item);
sprintf(buf, "Move S%d to S%d", values[1], values[0]);
SetLabel(set_popup_menu->move21_item, buf);
XtManageChild(set_popup_menu->move21_item);
XtSetSensitive(set_popup_menu->swap_item, True);
} else {
XtUnmanageChild(set_popup_menu->copy12_item);
XtUnmanageChild(set_popup_menu->copy21_item);
XtUnmanageChild(set_popup_menu->move12_item);
XtUnmanageChild(set_popup_menu->move21_item);
XtSetSensitive(set_popup_menu->swap_item, False);
}
if (n > 0) {
xfree(values);
}
XmMenuPosition(popup, event);
XtManageChild(popup);
}
static void ss_edit_cb(Widget list, XtPointer client_data, XtPointer call_data)
{
XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
ListStructure *plist = (ListStructure *) client_data;
SetChoiceData *sdata = (SetChoiceData *) plist->anydata;
int gno, setno;
gno = sdata->gno;
setno = plist->values[cbs->item_position - 1];
create_ss_frame(gno, setno);
}
ListStructure *CreateSetChoice(Widget parent, char *labelstr,
int type, int standalone)
{
ListStructure *retvalp;
SetChoiceData *sdata;
int nvisible;
nvisible = (type == LIST_TYPE_SINGLE) ? 4 : 8;
retvalp = CreateListChoice(parent, labelstr, type, nvisible, 0, NULL);
if (retvalp == NULL) {
return NULL;
}
AddHelpCB(retvalp->rc, "doc/UsersGuide.html#set-selector");
sdata = xmalloc(sizeof(SetChoiceData));
if (sdata == NULL) {
XCFREE(retvalp);
return NULL;
}
sdata->standalone = standalone;
sdata->view_comments = FALSE;
sdata->show_hidden = TRUE;
sdata->show_nodata = FALSE;
sdata->menu = CreateSetPopupEntries(retvalp);
XtAddEventHandler(retvalp->list, ButtonPressMask, False,
(XtEventHandler) set_popup, retvalp);
XtAddCallback(retvalp->list, XmNdefaultActionCallback, ss_edit_cb, retvalp);
retvalp->anydata = sdata;
if (standalone == TRUE) {
UpdateSetChoice(retvalp, get_cg());
}
nset_selectors++;
set_selectors = xrealloc(set_selectors,
nset_selectors*sizeof(ListStructure *));
set_selectors[nset_selectors - 1] = retvalp;
return retvalp;
}
static void update_sets_cb(int n, int *values, void *data)
{
int gno;
ListStructure *set_listp = (ListStructure *) data;
if (n == 1) {
gno = values[0];
} else {
gno = -1;
}
UpdateSetChoice(set_listp, gno);
}
GraphSetStructure *CreateGraphSetSelector(Widget parent, char *s, int sel_type)
{
GraphSetStructure *retval;
Widget rc;
retval = xmalloc(sizeof(GraphSetStructure));
retval->frame = CreateFrame(parent, s);
rc = XtVaCreateWidget("rc", xmRowColumnWidgetClass, retval->frame, NULL);
retval->graph_sel = CreateGraphChoice(rc, "Graph:", LIST_TYPE_SINGLE);
retval->set_sel = CreateSetChoice(rc, "Set:", sel_type, FALSE);
AddListChoiceCB(retval->graph_sel,
update_sets_cb, (void *) retval->set_sel);
UpdateSetChoice(retval->set_sel, get_cg());
XtManageChild(rc);
return retval;
}
SrcDestStructure *CreateSrcDestSelector(Widget parent, int sel_type)
{
SrcDestStructure *retval;
retval = xmalloc(sizeof(SrcDestStructure));
retval->form = XtVaCreateWidget("form",
xmFormWidgetClass, parent,
XmNfractionBase, 2,
NULL);
retval->src = CreateGraphSetSelector(retval->form, "Source", sel_type);
retval->dest = CreateGraphSetSelector(retval->form, "Destination", sel_type);
XtVaSetValues(retval->src->frame,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 1,
NULL);
XtVaSetValues(retval->dest->frame,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 1,
XmNrightAttachment, XmATTACH_FORM,
NULL);
XtManageChild(retval->form);
return retval;
}
void paint_color_selector(OptionStructure *optp)
{
int i, color;
long bg, fg;
for (i = 0; i < ncolor_option_items; i++) {
color = color_option_items[i].value;
bg = xvlibcolors[color];
if ((get_colorintensity(color) < 0.5 && is_video_reversed() == FALSE) ||
(get_colorintensity(color) > 0.5 && is_video_reversed() == TRUE )) {
fg = xvlibcolors[0];
} else {
fg = xvlibcolors[1];
}
XtVaSetValues(optp->options[i].widget,
XmNbackground, bg,
XmNforeground, fg,
NULL);
}
}
void update_color_selectors(void)
{
int i, j;
CMap_entry *pcmap;
for (i = 0, j = 0; i < number_of_colors(); i++) {
pcmap = get_cmap_entry(i);
if (pcmap != NULL && pcmap->ctype == COLOR_MAIN) {
j++;
}
}
ncolor_option_items = j;
color_option_items = xrealloc(color_option_items,
ncolor_option_items*sizeof(OptionItem));
for (i = 0, j = 0; i < number_of_colors(); i++) {
pcmap = get_cmap_entry(i);
if (pcmap != NULL && pcmap->ctype == COLOR_MAIN) {
color_option_items[j].value = i;
color_option_items[j].label = get_colorname(i);
j++;
}
}
for (i = 0; i < ncolor_selectors; i++) {
UpdateOptionChoice(color_selectors[i],
ncolor_option_items, color_option_items);
paint_color_selector(color_selectors[i]);
}
}
OptionStructure *CreateColorChoice(Widget parent, char *s)
{
OptionStructure *retvalp = NULL;
ncolor_selectors++;
color_selectors = xrealloc(color_selectors,
ncolor_selectors*sizeof(OptionStructure *));
if (color_selectors == NULL) {
errmsg("Malloc failed in CreateColorChoice()");
return retvalp;
}
retvalp = CreateOptionChoice(parent, s, 4,
ncolor_option_items, color_option_items);
color_selectors[ncolor_selectors - 1] = retvalp;
paint_color_selector(retvalp);
return retvalp;
}
SpinStructure *CreateLineWidthChoice(Widget parent, char *s)
{
return CreateSpinChoice(parent, s, 3, SPIN_TYPE_FLOAT, 0.0, MAX_LINEWIDTH, 0.5);
}
Widget *CreatePanelChoice(Widget parent, char *labelstr, int nchoices,...)
{
va_list var;
int i = 0;
XmString str;
char *s;
Widget *retval;
nchoices--;
retval = (Widget *) XtMalloc((nchoices + 2) * sizeof(Widget));
retval[1] = XmCreatePulldownMenu(parent, "pulldown", NULL, 0);
va_start(var, nchoices);
i = 0;
while ((s = va_arg(var, char *)) != NULL) {
retval[i + 2] = XmCreatePushButton(retval[1], s, NULL, 0);
i++;
}
if (i != nchoices) {
errmsg("Incorrect number of selections in CreatePanelChoice()");
}
va_end(var);
XtManageChildren(retval + 2, nchoices);
retval[0] = XmCreateOptionMenu(parent, "optionmenu", NULL, 0);
str = XmStringCreateLocalized(labelstr);
XtVaSetValues(retval[0],
XmNlabelString, str,
XmNsubMenuId, retval[1],
NULL);
XmStringFree(str);
XtManageChild(retval[0]);
return retval;
}
void SetChoice(Widget * w, int value)
{
Arg a;
if (w == (Widget *) NULL) {
return;
}
if (w[value + 2] == (Widget) NULL) {
errwin("Internal error, SetChoice: Attempt to set NULL Widget");
return;
}
XtSetArg(a, XmNmenuHistory, w[value + 2]);
XtSetValues(w[0], &a, 1);
}
int GetChoice(Widget * w)
{
Arg a;
Widget warg;
int i;
if (w == NULL) {
errwin("Internal error, GetChoice called with NULL argument");
return 0;
}
XtSetArg(a, XmNmenuHistory, &warg);
XtGetValues(w[0], &a, 1);
i = 0;
while (w[i + 2] != warg) {
if (w[i + 2] == NULL) {
errwin("Internal error, GetChoice: Found NULL in Widget list");
return 0;
}
i++;
}
return i;
}
static OptionItem fmt_option_items[32] =
{
{FORMAT_DECIMAL, "Decimal" },
{FORMAT_EXPONENTIAL, "Exponential" },
{FORMAT_GENERAL, "General" },
{FORMAT_POWER, "Power" },
{FORMAT_SCIENTIFIC, "Scientific" },
{FORMAT_ENGINEERING, "Engineering" },
{FORMAT_COMPUTING, "Computing (K,M,G,...)"},
{FORMAT_DDMMYY, "DD-MM-YY" },
{FORMAT_MMDDYY, "MM-DD-YY" },
{FORMAT_YYMMDD, "YY-MM-DD" },
{FORMAT_MMYY, "MM-YY" },
{FORMAT_MMDD, "MM-DD" },
{FORMAT_MONTHDAY, "Month-DD" },
{FORMAT_DAYMONTH, "DD-Month" },
{FORMAT_MONTHS, "Month (abrev.)" },
{FORMAT_MONTHSY, "Month (abrev.)-YY" },
{FORMAT_MONTHL, "Month" },
{FORMAT_DAYOFWEEKS, "Day of week (abrev.)"},
{FORMAT_DAYOFWEEKL, "Day of week" },
{FORMAT_DAYOFYEAR, "Day of year" },
{FORMAT_HMS, "HH:MM:SS" },
{FORMAT_MMDDHMS, "MM-DD HH:MM:SS" },
{FORMAT_MMDDYYHMS, "MM-DD-YY HH:MM:SS" },
{FORMAT_YYMMDDHMS, "YY-MM-DD HH:MM:SS" },
{FORMAT_DEGREESLON, "Degrees (lon)" },
{FORMAT_DEGREESMMLON, "DD MM' (lon)" },
{FORMAT_DEGREESMMSSLON, "DD MM' SS.s\" (lon)" },
{FORMAT_MMSSLON, "MM' SS.s\" (lon)" },
{FORMAT_DEGREESLAT, "Degrees (lat)" },
{FORMAT_DEGREESMMLAT, "DD MM' (lat)" },
{FORMAT_DEGREESMMSSLAT, "DD MM' SS.s\" (lat)" },
{FORMAT_MMSSLAT, "MM' SS.s\" (lat)" }
};
OptionStructure *CreateFormatChoice(Widget parent, char *s)
{
OptionStructure *retval;
retval = CreateOptionChoice(parent, s, 4, 31, fmt_option_items);
return(retval);
}
static OptionItem as_option_items[4] =
{
{AUTOSCALE_NONE, "None"},
{AUTOSCALE_X, "X"},
{AUTOSCALE_Y, "Y"},
{AUTOSCALE_XY, "XY"}
};
OptionStructure *CreateASChoice(Widget parent, char *s)
{
OptionStructure *retval;
retval = CreateOptionChoice(parent, s, 1, 4, as_option_items);
/* As init value, use this */
SetOptionChoice(retval, autoscale_onread);
return(retval);
}
Widget *CreatePrecisionChoice(Widget parent, char *s)
{
Widget *w;
w = CreatePanelChoice(parent, s,
11,
"0", "1", "2", "3", "4",
"5", "6", "7", "8", "9",
NULL);
return(w);
}
Widget CreateScale(Widget parent, char *s, int min, int max, int delta)
{
Widget w;
XmString str;
str = XmStringCreateLocalized(s);
w = XtVaCreateManagedWidget("scroll",
xmScaleWidgetClass, parent,
XmNtitleString, str,
XmNminimum, min,
XmNmaximum, max,
XmNscaleMultiple, delta,
XmNvalue, 0,
XmNshowValue, True,
XmNprocessingDirection, XmMAX_ON_RIGHT,
XmNorientation, XmHORIZONTAL,
#if XmVersion >= 2000
XmNsliderMark, XmROUND_MARK,
#endif
NULL);
XmStringFree(str);
return w;
}
void SetScaleValue(Widget w, int value)
{
XtVaSetValues(w, XmNvalue, value, NULL);
}
int GetScaleValue(Widget w)
{
int value;
XtVaGetValues(w, XmNvalue, &value, NULL);
return value;
}
void SetScaleWidth(Widget w, int width)
{
XtVaSetValues(w, XmNscaleWidth, (Dimension) width, NULL);
}
Widget CreateAngleChoice(Widget parent, char *s)
{
return CreateScale(parent, s, 0, 360, 10);
}
int GetAngleChoice(Widget w)
{
return GetScaleValue(w);
}
void SetAngleChoice(Widget w, int angle)
{
SetScaleValue(w, angle);
}
Widget CreateCharSizeChoice(Widget parent, char *s)
{
return CreateScale(parent, s, 0, 1000, 25);
}
double GetCharSizeChoice(Widget w)
{
return ((double) GetScaleValue(w)/100);
}
void SetCharSizeChoice(Widget w, double size)
{
int value = (int) rint(size*100);
SetScaleValue(w, value);
}
Widget CreateToggleButton(Widget parent, char *s)
{
return (XtVaCreateManagedWidget(s, xmToggleButtonWidgetClass, parent, NULL));
}
int GetToggleButtonState(Widget w)
{
return (XmToggleButtonGetState(w));
}
void SetToggleButtonState(Widget w, int value)
{
if (w == NULL) {
return;
}
XmToggleButtonSetState(w, value ? True:False, False);
return;
}
typedef struct {
void (*cbproc)();
void *anydata;
} TB_CBdata;
static void tb_int_cb_proc(Widget w, XtPointer client_data, XtPointer call_data)
{
int onoff;
TB_CBdata *cbdata = (TB_CBdata *) client_data;
onoff = GetToggleButtonState(w);
cbdata->cbproc(onoff, cbdata->anydata);
}
void AddToggleButtonCB(Widget w, TB_CBProc cbproc, void *anydata)
{
TB_CBdata *cbdata;
cbdata = xmalloc(sizeof(TB_CBdata));
cbdata->cbproc = cbproc;
cbdata->anydata = anydata;
XtAddCallback(w,
XmNvalueChangedCallback, tb_int_cb_proc, (XtPointer) cbdata);
}
Widget CreateDialogForm(Widget parent, char *s)
{
Widget dialog, w;
char *bufp;
int standalone;
if (parent == NULL) {
standalone = TRUE;
parent = XtAppCreateShell("XMgrace", "XMgrace",
topLevelShellWidgetClass, disp,
NULL, 0);
} else {
standalone = FALSE;
}
bufp = label_to_resname(s, "Dialog");
dialog = XmCreateDialogShell(parent, bufp, NULL, 0);
xfree(bufp);
if (standalone) {
RegisterEditRes(dialog);
}
handle_close(dialog);
bufp = copy_string(NULL, "Grace: ");
bufp = concat_strings(bufp, s);
XtVaSetValues(dialog,
XmNtitle, bufp,
NULL);
xfree(bufp);
w = XmCreateForm(dialog, "form", NULL, 0);
return w;
}
void SetDialogFormResizable(Widget form, int onoff)
{
XtVaSetValues(form,
XmNresizePolicy, onoff ? XmRESIZE_ANY:XmRESIZE_NONE,
NULL);
XtVaSetValues(XtParent(form),
XmNallowShellResize, onoff ? True:False,
NULL);
}
void AddDialogFormChild(Widget form, Widget child)
{
Widget last_widget;
XtVaGetValues(form, XmNuserData, &last_widget, NULL);
if (last_widget) {
XtVaSetValues(child,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, last_widget,
NULL);
XtVaSetValues(last_widget,
XmNbottomAttachment, XmATTACH_NONE,
NULL);
} else {
XtVaSetValues(child,
XmNtopAttachment, XmATTACH_FORM,
NULL);
}
XtVaSetValues(child,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
NULL);
XtVaSetValues(form,
XmNuserData, child,
NULL);
}
typedef struct {
Widget form;
int close;
int (*cbproc)();
void *anydata;
} AACDialog_CBdata;
void aacdialog_int_cb_proc(void *data)
{
AACDialog_CBdata *cbdata;
int retval;
set_wait_cursor();
cbdata = (AACDialog_CBdata *) data;
retval = cbdata->cbproc(cbdata->anydata);
if (cbdata->close && retval == RETURN_SUCCESS) {
XtUnmanageChild(XtParent(cbdata->form));
}
unset_wait_cursor();
}
void CreateAACDialog(Widget form,
Widget container, AACDialog_CBProc cbproc, void *data)
{
Widget fr, aacbut[3];
AACDialog_CBdata *cbdata_accept, *cbdata_apply;
char *aaclab[3] = {"Apply", "Accept", "Close"};
fr = CreateFrame(form, NULL);
XtVaSetValues(fr,
XmNtopAttachment, XmATTACH_NONE,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
NULL);
CreateCommandButtons(fr, 3, aacbut, aaclab);
AddDialogFormChild(form, container);
XtVaSetValues(container,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, fr,
NULL);
XtVaSetValues(form, XmNcancelButton, aacbut[2], NULL);
cbdata_accept = xmalloc(sizeof(AACDialog_CBdata));
cbdata_accept->form = form;
cbdata_accept->anydata = data;
cbdata_accept->cbproc = cbproc;
cbdata_accept->close = TRUE;
cbdata_apply = xmalloc(sizeof(AACDialog_CBdata));
cbdata_apply->form = form;
cbdata_apply->anydata = data;
cbdata_apply->cbproc = cbproc;
cbdata_apply->close = FALSE;
AddButtonCB(aacbut[0], aacdialog_int_cb_proc, cbdata_apply);
AddButtonCB(aacbut[1], aacdialog_int_cb_proc, cbdata_accept);
AddButtonCB(aacbut[2], destroy_dialog_cb, XtParent(form));
XtManageChild(container);
XtManageChild(form);
}
TransformStructure *CreateTransformDialogForm(Widget parent,
char *s, int sel_type)
{
TransformStructure *retval;
retval = xmalloc(sizeof(TransformStructure));
retval->form = CreateDialogForm(parent, s);
retval->srcdest = CreateSrcDestSelector(retval->form, sel_type);
AddDialogFormChild(retval->form, retval->srcdest->form);
/*
* retval->restr = CreateRestrictionChoice(retval->form, "Source data filtering");
* AddDialogFormChild(retval->form, retval->restr->frame);
*/
return retval;
}
int GetTransformDialogSettings(TransformStructure *tdialog, int exclusive,
int *gsrc, int *gdest,
int *nssrc, int **svaluessrc, int *nsdest, int **svaluesdest)
{
int gsrc_ok, gdest_ok;
gsrc_ok = GetSingleListChoice(tdialog->srcdest->src->graph_sel, gsrc);
gdest_ok = GetSingleListChoice(tdialog->srcdest->dest->graph_sel, gdest);
if (gsrc_ok == RETURN_FAILURE || gdest_ok == RETURN_FAILURE) {
errmsg("Please select single source and destination graphs");
return RETURN_FAILURE;
}
*nssrc = GetListChoices(tdialog->srcdest->src->set_sel, svaluessrc);
if (*nssrc == 0) {
errmsg("No source sets selected");
return RETURN_FAILURE;
}
*nsdest = GetListChoices(tdialog->srcdest->dest->set_sel, svaluesdest);
if (*nsdest != 0 && *nssrc != *nsdest) {
errmsg("Different number of source and destination sets");
xfree(*svaluessrc);
xfree(*svaluesdest);
return RETURN_FAILURE;
}
/* check for mutually exclusive selections */
if (exclusive && *gsrc == *gdest && *nsdest != 0) {
int i;
for (i = 0; i < *nssrc; i++) {
if ((*svaluessrc)[i] == (*svaluesdest)[i]) {
xfree(*svaluessrc);
xfree(*svaluesdest);
errmsg("Source and destination set(s) are not mutually exclusive");
return RETURN_FAILURE;
}
}
}
return RETURN_SUCCESS;
}
Widget CreateVContainer(Widget parent)
{
Widget rc;
rc = XmCreateRowColumn(parent, "VContainer", NULL, 0);
XtManageChild(rc);
return rc;
}
Widget CreateHContainer(Widget parent)
{
Widget rc;
rc = XmCreateRowColumn(parent, "HContainer", NULL, 0);
XtVaSetValues(rc, XmNorientation, XmHORIZONTAL, NULL);
XtManageChild(rc);
return rc;
}
Widget CreateFrame(Widget parent, char *s)
{
Widget fr;
fr = XtVaCreateManagedWidget("frame", xmFrameWidgetClass, parent, NULL);
if (s != NULL) {
XtVaCreateManagedWidget(s, xmLabelGadgetClass, fr,
XmNchildType, XmFRAME_TITLE_CHILD,
NULL);
}
return (fr);
}
typedef struct {
int ncols;
int nrows;
} GridData;
Widget CreateGrid(Widget parent, int ncols, int nrows)
{
Widget w;
int nfractions;
GridData *gd;
if (ncols <= 0 || nrows <= 0) {
errmsg("Wrong call to CreateGrid()");
ncols = 1;
nrows = 1;
}
nfractions = 0;
do {
nfractions++;
} while (nfractions % ncols || nfractions % nrows);
gd = xmalloc(sizeof(GridData));
gd->ncols = ncols;
gd->nrows = nrows;
w = XmCreateForm(parent, "grid_form", NULL, 0);
XtVaSetValues(w,
XmNfractionBase, nfractions,
XmNuserData, gd,
NULL);
XtManageChild(w);
return w;
}
void PlaceGridChild(Widget grid, Widget w, int col, int row)
{
int nfractions, w1, h1;
GridData *gd;
XtVaGetValues(grid,
XmNfractionBase, &nfractions,
XmNuserData, &gd,
NULL);
if (gd == NULL) {
errmsg("PlaceGridChild() called with a non-grid widget");
return;
}
if (col < 0 || col >= gd->ncols) {
errmsg("PlaceGridChild() called with wrong `col' argument");
return;
}
if (row < 0 || row >= gd->nrows) {
errmsg("PlaceGridChild() called with wrong `row' argument");
return;
}
w1 = nfractions/gd->ncols;
h1 = nfractions/gd->nrows;
XtVaSetValues(w,
XmNleftAttachment , XmATTACH_POSITION,
XmNleftPosition , col*w1 ,
XmNrightAttachment , XmATTACH_POSITION,
XmNrightPosition , (col + 1)*w1 ,
XmNtopAttachment , XmATTACH_POSITION,
XmNtopPosition , row*h1 ,
XmNbottomAttachment, XmATTACH_POSITION,
XmNbottomPosition , (row + 1)*h1 ,
NULL);
}
Widget CreateTab(Widget parent)
{
Widget tab;
tab = XtVaCreateManagedWidget("tab", xmTabWidgetClass, parent, NULL);
return (tab);
}
Widget CreateTabPage(Widget parent, char *s)
{
Widget w;
XmString str;
w = XmCreateRowColumn(parent, "tabPage", NULL, 0);
str = XmStringCreateLocalized(s);
XtVaSetValues(w, XmNtabLabel, str, NULL);
XmStringFree(str);
XtManageChild(w);
return (w);
}
void SelectTabPage(Widget tab, Widget w)
{
XmTabSetTabWidget(tab, w, True);
}
Widget CreateTextItem2(Widget parent, int len, char *s)
{
Widget w;
Widget rc;
XmString str;
rc = XmCreateRowColumn(parent, "rc", NULL, 0);
XtVaSetValues(rc, XmNorientation, XmHORIZONTAL, NULL);
str = XmStringCreateLocalized(s);
XtVaCreateManagedWidget("label", xmLabelWidgetClass, rc,
XmNlabelString, str,
NULL);
XmStringFree(str);
w = XtVaCreateManagedWidget("text", xmTextWidgetClass, rc,
XmNtraversalOn, True,
XmNcolumns, len,
NULL);
XtManageChild(rc);
return w;
}
Widget CreateTextItem4(Widget parent, int len, char *label)
{
Widget retval;
XtVaCreateManagedWidget(label, xmLabelWidgetClass, parent, NULL);
retval = XtVaCreateManagedWidget("text",
xmTextWidgetClass, parent,
XmNcolumns, len,
NULL);
return retval;
}
/*
* create a multiline editable window
* parent = parent widget
* hgt = number of lines in edit window
* s = label for window
*
* returns the edit window widget
*/
Widget CreateScrollTextItem2(Widget parent, int hgt, char *s)
{
Widget w, form, label;
XmString str;
Arg args[4];
int ac;
form = XmCreateForm(parent, "form", NULL, 0);
str = XmStringCreateLocalized(s);
label = XtVaCreateManagedWidget("label",
xmLabelWidgetClass, form,
XmNlabelString, str,
XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
NULL);
XmStringFree(str);
ac = 0;
if (hgt > 0) {
XtSetArg(args[ac], XmNrows, hgt); ac++;
}
XtSetArg(args[ac], XmNeditMode, XmMULTI_LINE_EDIT); ac++;
XtSetArg(args[ac], XmNwordWrap, True); ac++;
XtSetArg(args[ac], XmNvisualPolicy, XmVARIABLE); ac++;
w = XmCreateScrolledText(form, "text", args, ac);
XtVaSetValues(XtParent(w),
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, label,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
NULL);
XtManageChild(w);
XtManageChild(form);
return w;
}
char *xv_getstr(Widget w)
/*
* return the string from a text widget
*
* NB - newlines are converted to spaces
*/
{
char *s;
int i;
static char buf[MAX_STRING_LENGTH];
strncpy(buf, s = XmTextGetString(w), MAX_STRING_LENGTH - 1);
XtFree(s);
i=strlen(buf);
for (i--; i >= 0; i--) {
if (buf[i] == '\n') {
buf[i] = ' ';
}
}
return buf;
}
/*
* xv_evalexpr - take a text field and pass it to the parser if it needs to
* evaluated, else use atof().
* place the double result in answer
* if an error, return False, else True
*/
Boolean xv_evalexpr(Widget w, double *answer )
{
char *s;
static char *buf = NULL;
int i, len, ier = 0;
double result;
buf = copy_string(buf, s = XmTextGetString(w));
XtFree(s);
if (!(len = strlen( buf ) )) { /* check for zero length */
*answer = 0;
return RETURN_FAILURE;
}
/* first character may be a sign */
if (!fpdigit[(int) buf[0]] && buf[0] != '-' && buf[0] != '+') {
i = len +1;
} else {
i = 1;
}
for (; i<len; i++) {
if (!fpdigit[(int) buf[i]]) {
break;
}
}
if (i == len) { /* only floating point digits */
*answer = atof( buf );
return RETURN_SUCCESS;
} else { /* must evaluate an expression */
ier = s_scanner(buf, &result);
if( !ier ) {
*answer = result;
return RETURN_SUCCESS;
} else {
*answer = 0;
return RETURN_FAILURE;
}
}
}
/*
* xv_evalexpri - take a text field and pass it to the parser if it needs to
* evaluated, else use atoi().
* place the integer result in answer
* if an error, return False, else True
*/
Boolean xv_evalexpri(Widget w, int *answer )
{
char *s;
static char *buf = NULL;
int i, len, ier = 0;
double result;
buf = copy_string(buf, s = XmTextGetString(w));
XtFree(s);
if (!(len = strlen( buf ) )) { /* check for zero length */
*answer = 0;
return RETURN_FAILURE;
}
/* first character may be a sign */
if (!fpdigit[(int) buf[0]] && buf[0] != '-' && buf[0] != '+') {
i = len +1;
} else {
i = 1;
}
for (; i<len; i++) {
if (!fpdigit[(int) buf[i]]) {
break;
}
}
if (i == len) { /* only floating point digits */
*answer = atoi(buf);
return RETURN_SUCCESS;
} else { /* must evaluate an expression */
ier = s_scanner(buf, &result);
if( !ier ) {
*answer = (int)result;
return RETURN_SUCCESS;
} else {
*answer = 0;
return RETURN_FAILURE;
}
}
}
void xv_setstr(Widget w, char *s)
{
if (w != NULL) {
XmTextSetString(w, s ? s : "");
}
}
/*
* generic unmanage popup routine, used elswhere
*/
void destroy_dialog(Widget w, XtPointer client_data, XtPointer call_data)
{
XtUnmanageChild((Widget) client_data);
}
/*
* same for AddButtonCB
*/
void destroy_dialog_cb(void *data)
{
XtUnmanageChild((Widget) data);
}
/* if user tried to close from WM */
static void wm_exit_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
bailout();
}
/*
* handle the close item on the WM menu
*/
void handle_close(Widget w)
{
Atom WM_DELETE_WINDOW;
XtVaSetValues(w, XmNdeleteResponse, XmDO_NOTHING, NULL);
WM_DELETE_WINDOW = XmInternAtom(disp, "WM_DELETE_WINDOW", False);
XmAddProtocolCallback(w,
XM_WM_PROTOCOL_ATOM(w), WM_DELETE_WINDOW,
(w == app_shell) ? wm_exit_cb : destroy_dialog, w);
savewidget(w);
}
/*
* Manage and raise
*/
void RaiseWindow(Widget w)
{
XtManageChild(w);
XMapRaised(XtDisplay(w), XtWindow(w));
}
static Widget *savewidgets = NULL;
static int nsavedwidgets = 0;
void savewidget(Widget w)
{
int i;
for (i = 0; i < nsavedwidgets; i++) {
if (w == savewidgets[i]) {
return;
}
}
savewidgets = xrealloc(savewidgets, (nsavedwidgets + 1)*sizeof(Widget));
savewidgets[nsavedwidgets] = w;
nsavedwidgets++;
}
void deletewidget(Widget w)
{
int i;
for (i = 0; i < nsavedwidgets; i++) {
if (w == savewidgets[i]) {
nsavedwidgets--;
for (; i < nsavedwidgets; i++) {
savewidgets[i] = savewidgets[i + 1];
}
savewidgets = xrealloc(savewidgets, nsavedwidgets*sizeof(Widget));
XtDestroyWidget(w);
return;
}
}
}
void DefineDialogCursor(Cursor c)
{
int i;
for (i = 0; i < nsavedwidgets; i++) {
XDefineCursor(disp, XtWindow(savewidgets[i]), c);
}
XFlush(disp);
}
void UndefineDialogCursor()
{
int i;
for (i = 0; i < nsavedwidgets; i++) {
XUndefineCursor(disp, XtWindow(savewidgets[i]));
}
XFlush(disp);
}
Widget CreateCommandButtonsNoDefault(Widget parent, int n, Widget * buts, char **l)
{
int i;
Widget form;
Dimension h;
form = XtVaCreateWidget("form", xmFormWidgetClass, parent,
XmNfractionBase, n,
NULL);
for (i = 0; i < n; i++) {
buts[i] = XtVaCreateManagedWidget(l[i],
xmPushButtonWidgetClass, form,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, i,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, i + 1,
XmNleftOffset, (i == 0) ? 2 : 0,
XmNrightOffset, 3,
XmNtopOffset, 2,
XmNbottomOffset, 3,
NULL);
}
XtManageChild(form);
XtVaGetValues(buts[0], XmNheight, &h, NULL);
XtVaSetValues(form, XmNpaneMaximum, h, XmNpaneMinimum, h, NULL);
return form;
}
Widget CreateCommandButtons(Widget parent, int n, Widget * buts, char **l)
{
int i;
Widget form;
Dimension h;
form = XtVaCreateWidget("form", xmFormWidgetClass, parent,
XmNfractionBase, n,
NULL);
for (i = 0; i < n; i++) {
buts[i] = XtVaCreateManagedWidget(l[i],
xmPushButtonWidgetClass, form,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, i,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, i + 1,
XmNdefaultButtonShadowThickness, 1,
XmNshowAsDefault, (i == 0) ? True : False,
NULL);
}
XtManageChild(form);
XtVaGetValues(buts[0], XmNheight, &h, NULL);
XtVaSetValues(form, XmNpaneMaximum, h, XmNpaneMinimum, h, NULL);
return form;
}
static SetChoiceItem *plist = NULL;
static int nplist = 0;
SetChoiceItem CreateSetSelector(Widget parent,
char *label,
int type,
int ff,
int gtype,
int stype)
{
Arg args[3];
Widget rc2, lab;
SetChoiceItem sel;
rc2 = XtVaCreateWidget("rc", xmRowColumnWidgetClass, parent,
XmNorientation, XmVERTICAL, NULL);
lab = XmCreateLabel(rc2, label, NULL, 0);
XtManageChild(lab);
XtSetArg(args[0], XmNlistSizePolicy, XmRESIZE_IF_POSSIBLE);
XtSetArg(args[1], XmNvisibleItemCount, 6);
sel.list = XmCreateScrolledList(rc2, "list", args, 2);
if (stype == SELECTION_TYPE_MULTIPLE) { /* multiple select */
XtVaSetValues(sel.list,
XmNselectionPolicy, XmEXTENDED_SELECT,
NULL);
} else { /* single select */
XtVaSetValues(sel.list,
XmNselectionPolicy, XmSINGLE_SELECT,
NULL);
}
sel.type = type;
sel.gno = gtype;
XtManageChild(sel.list);
sel.indx = save_set_list(sel);
update_set_list(gtype == GRAPH_SELECT_CURRENT ? get_cg():sel.gno, sel);
XtManageChild(rc2);
return sel;
}
int GetSelectedSet(SetChoiceItem l)
{
int retval = SET_SELECT_ERROR;
int *pos_list;
int pos_cnt, cnt;
char buf[256];
if (XmListGetSelectedPos(l.list, &pos_list, &pos_cnt)) {
XmString *s, cs;
char *cstr;
XtVaGetValues(l.list,
XmNselectedItemCount, &cnt,
XmNselectedItems, &s,
NULL);
cs = XmStringCopy(*s);
if ((cstr = GetStringSimple(cs))) {
strcpy(buf, cstr);
if (strcmp(buf, "New set") == 0) {
retval = SET_SELECT_NEXT;
} else if (strcmp(buf, "All sets") == 0) {
retval = SET_SELECT_ALL;
} else if (strcmp(buf, "Nearest set") == 0) {
retval = SET_SELECT_NEAREST;
} else {
sscanf(buf, "S%d", &retval);
}
XtFree(cstr);
}
XmStringFree(cs);
}
return retval;
}
/*
* if the set selection type is multiple, then get a
* list of sets, returns the number of selected sets.
*/
int GetSelectedSets(SetChoiceItem l, int **sets)
{
int i;
int cnt = SET_SELECT_ERROR, retval = SET_SELECT_ERROR;
int *ptr;
int *pos_list;
int pos_cnt, gno;
if (XmListGetSelectedPos(l.list, &pos_list, &pos_cnt)) {
char buf[256];
char *cstr;
XmString *s, cs;
XtVaGetValues(l.list,
XmNselectedItemCount, &cnt,
XmNselectedItems, &s,
NULL);
*sets = xmalloc(cnt * SIZEOF_INT);
ptr = *sets;
for (i = 0; i < cnt; i++) {
cs = XmStringCopy(s[i]);
if ((cstr = GetStringSimple(cs))) {
strcpy(buf, cstr);
if (strcmp(buf, "New set") == 0) {
retval = SET_SELECT_NEXT;
return retval;
} else if (strcmp(buf, "All sets") == 0) {
int j, nsets = 0;
retval = SET_SELECT_ALL;
if (l.gno == GRAPH_SELECT_CURRENT) {
gno = get_cg();
} else {
gno = l.gno;
}
retval = nactive(gno);
*sets = xrealloc(*sets, retval * SIZEOF_INT);
ptr = *sets;
for (j = 0; j < number_of_sets(gno); j++) {
if (is_set_active(gno, j)) {
ptr[nsets] = j;
nsets++;
}
}
if (nsets != retval) {
errwin("Nsets != reval, can't happen!");
}
return retval;
} else {
sscanf(buf, "S%d", &retval);
}
ptr[i] = retval;
XtFree(cstr);
}
XmStringFree(cs);
}
}
return cnt;
}
int save_set_list(SetChoiceItem l)
{
nplist++;
plist = xrealloc(plist, nplist*sizeof(SetChoiceItem));
plist[nplist - 1] = l;
return nplist - 1;
}
void update_save_set_list( SetChoiceItem l, int newgr )
{
plist[l.indx] = l;
update_set_list( newgr, plist[l.indx] );
}
void update_set_list(int gno, SetChoiceItem l)
{
int i, cnt, scnt=0;
char buf[1024];
XmString *xms;
XmListDeleteAllItems(l.list);
for (i = 0; i < number_of_sets(gno); i++) {
if (is_set_active(gno, i)) {
scnt++;
}
}
switch (l.type) { /* TODO */
case SET_SELECT_ACTIVE:
xms = xmalloc(sizeof(XmString) * scnt);
cnt = 0;
break;
case SET_SELECT_ALL:
xms = xmalloc(sizeof(XmString) * (scnt + 1));
xms[0] = XmStringCreateLocalized("All sets");
cnt = 1;
break;
case SET_SELECT_NEXT:
xms = xmalloc(sizeof(XmString) * (scnt + 1));
xms[0] = XmStringCreateLocalized("New set");
cnt = 1;
break;
case SET_SELECT_NEAREST:
xms = xmalloc(sizeof(XmString) * (scnt + 1));
xms[0] = XmStringCreateLocalized("Nearest set");
cnt = 1;
break;
default:
xms = xmalloc(sizeof(XmString) * scnt);
cnt = 0;
break;
}
for (i = 0; i < number_of_sets(gno); i++) {
if (is_set_active(gno, i)) {
sprintf(buf, "S%d (N=%d, %s)", i, getsetlength(gno, i), getcomment(gno, i));
xms[cnt] = XmStringCreateLocalized(buf);
cnt++;
}
}
XmListAddItemsUnselected(l.list, xms, cnt, 0);
/* automatically highlight if only 1 selection */
if (scnt == 1) {
XmListSelectItem(l.list, xms[cnt-1], True);
}
for (i = 0; i < cnt; i++) {
XmStringFree(xms[i]);
}
xfree(xms);
}
void update_set_lists(int gno)
{
int i;
if (gno == GRAPH_SELECT_CURRENT) {
update_set_selectors(get_cg());
update_ss_editors(get_cg());
} else {
update_set_selectors(gno);
update_ss_editors(gno);
}
if (inwin) {
for (i = 0; i < nplist; i++) {
if (plist[i].gno == gno ||
(gno == get_cg() && plist[i].gno == GRAPH_SELECT_CURRENT)) {
update_set_list(gno, plist[i]);
}
}
}
}
Widget CreateSeparator(Widget parent)
{
Widget sep;
sep = XmCreateSeparator(parent, "sep", NULL, 0);
XtManageChild(sep);
return sep;
}
Widget CreateMenuBar(Widget parent)
{
Widget menubar;
menubar = XmCreateMenuBar(parent, "menuBar", NULL, 0);
return menubar;
}
Widget CreateMenu(Widget parent, char *label, char mnemonic, int help)
{
Widget menupane, cascade;
XmString str;
char *name, ms[2];
name = label_to_resname(label, "Menu");
menupane = XmCreatePulldownMenu(parent, name, NULL, 0);
xfree(name);
ms[0] = mnemonic;
ms[1] = '\0';
str = XmStringCreateLocalized(label);
cascade = XtVaCreateManagedWidget("cascade",
xmCascadeButtonGadgetClass, parent,
XmNsubMenuId, menupane,
XmNlabelString, str,
XmNmnemonic, XStringToKeysym(ms),
NULL);
XmStringFree(str);
if (help) {
XtVaSetValues(parent, XmNmenuHelpWidget, cascade, NULL);
CreateMenuButton(menupane, "On context", 'x',
ContextHelpCB, NULL);
CreateSeparator(menupane);
}
return menupane;
}
Widget CreateMenuButton(Widget parent, char *label, char mnemonic,
Button_CBProc cb, void *data)
{
Widget button;
XmString str;
char *name, ms[2];
ms[0] = mnemonic;
ms[1] = '\0';
str = XmStringCreateLocalized(label);
name = label_to_resname(label, "Button");
button = XtVaCreateManagedWidget(name,
xmPushButtonWidgetClass, parent,
XmNlabelString, str,
XmNmnemonic, XStringToKeysym(ms),
NULL);
xfree(name);
XmStringFree(str);
AddButtonCB(button, cb, data);
return button;
}
Widget CreateMenuCloseButton(Widget parent, Widget form)
{
Widget wbut;
XmString str;
wbut = CreateMenuButton(parent,
"Close", 'C', destroy_dialog_cb, XtParent(form));
str = XmStringCreateLocalized("Esc");
XtVaSetValues(wbut, XmNacceleratorText, str, NULL);
XmStringFree(str);
XtVaSetValues(form, XmNcancelButton, wbut, NULL);
return wbut;
}
Widget CreateMenuHelpButton(Widget parent, char *label, char mnemonic,
Widget form, char *ha)
{
Widget wbut;
wbut = CreateMenuButton(parent, label, mnemonic, HelpCB, ha);
AddHelpCB(form, ha);
return wbut;
}
Widget CreateMenuToggle(Widget parent, char *label, char mnemonic,
TB_CBProc cb, void *data)
{
Widget button;
XmString str;
char *name, ms[2];
ms[0] = mnemonic;
ms[1] = '\0';
str = XmStringCreateLocalized(label);
name = label_to_resname(label, NULL);
button = XtVaCreateManagedWidget(name,
xmToggleButtonWidgetClass, parent,
XmNlabelString, str,
XmNmnemonic, XStringToKeysym(ms),
XmNvisibleWhenOff, True,
XmNindicatorOn, True,
NULL);
xfree(name);
XmStringFree(str);
if (cb) {
AddToggleButtonCB(button, cb, data);
}
return button;
}
Widget CreateMenuLabel(Widget parent, char *name)
{
Widget lab;
lab = XmCreateLabel(parent, name, NULL, 0);
XtManageChild(lab);
return lab;
}
static void help_int_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
HelpCB(client_data);
}
void AddHelpCB(Widget w, char *ha)
{
if (XtHasCallbacks(w, XmNhelpCallback) == XtCallbackHasSome) {
/* allow only one help callback */
XtRemoveAllCallbacks(w, XmNhelpCallback);
}
XtAddCallback(w, XmNhelpCallback, help_int_cb, (XtPointer) ha);
}
void ContextHelpCB(void *data)
{
Widget whelp;
Cursor cursor;
int ok = FALSE;
cursor = XCreateFontCursor(disp, XC_question_arrow);
whelp = XmTrackingLocate(app_shell, cursor, False);
while (whelp != NULL) {
if (XtHasCallbacks(whelp, XmNhelpCallback) == XtCallbackHasSome) {
XtCallCallbacks(whelp, XmNhelpCallback, NULL);
ok = TRUE;
break;
} else {
whelp = GetParent(whelp);
}
}
if (!ok) {
HelpCB(NULL);
}
XFreeCursor(disp, cursor);
}
static int yesno_retval = 0;
static Boolean keep_grab = True;
void yesnoCB(Widget w, XtPointer client_data, XtPointer call_data)
{
XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;
int why = cbs->reason;
keep_grab = False;
XtRemoveGrab(XtParent(w));
XtUnmanageChild(w);
switch (why) {
case XmCR_OK:
yesno_retval = 1;
/* process ok action */
break;
case XmCR_CANCEL:
yesno_retval = 0;
/* process cancel action */
break;
}
}
static void update_yesno(Widget w, char *msg, char *ha)
{
Widget hb;
XmString str;
if (msg != NULL) {
str = XmStringCreateLocalized(msg);
} else {
str = XmStringCreateLocalized("Warning");
}
XtVaSetValues(w, XmNmessageString, str, NULL);
XmStringFree(str);
hb = XtNameToWidget(w, "Help");
if (ha) {
AddButtonCB(hb, HelpCB, ha);
XtSetSensitive(hb, True);
} else {
XtSetSensitive(hb, False);
}
}
int yesnowin(char *msg, char *s1, char *s2, char *help_anchor)
{
static Widget yesno_popup = NULL;
XEvent event;
keep_grab = True;
if (yesno_popup == NULL) {
yesno_popup = XmCreateErrorDialog(app_shell, "warndlg", NULL, 0);
XtAddCallback(yesno_popup, XmNokCallback, yesnoCB, NULL);
XtAddCallback(yesno_popup, XmNcancelCallback, yesnoCB, NULL);
}
update_yesno(yesno_popup, msg, help_anchor);
RaiseWindow(yesno_popup);
XtAddGrab(XtParent(yesno_popup), True, False);
while (keep_grab || XtAppPending(app_con)) {
XtAppNextEvent(app_con, &event);
XtDispatchEvent(&event);
}
return yesno_retval;
}
Widget CreateAACButtons(Widget parent, Widget form, Button_CBProc aac_cb)
{
Widget w;
Widget aacbut[3];
static char *aaclab[3] = {"Apply", "Accept", "Close"};
w = CreateCommandButtons(parent, 3, aacbut, aaclab);
AddButtonCB(aacbut[0], aac_cb, (void *) AAC_APPLY);
AddButtonCB(aacbut[1], aac_cb, (void *) AAC_ACCEPT);
AddButtonCB(aacbut[2], aac_cb, (void *) AAC_CLOSE);
if (form != NULL) {
XtVaSetValues(form, XmNcancelButton, aacbut[2], NULL);
}
return w;
}
void SetLabel(Widget w, char *s)
{
XmString str;
str = XmStringCreateLocalized(s);
XtVaSetValues(w, XmNlabelString, str, NULL);
XmStringFree(str);
}
void SetFixedFont(Widget w)
{
XFontStruct *f;
XmFontList xmf;
f = XLoadQueryFont(disp, "fixed");
xmf = XmFontListCreate(f, charset);
if (xmf == NULL) {
errmsg("Can't load font \"fixed\"");
return;
} else {
XtVaSetValues(w, XmNfontList, xmf, NULL);
XmFontListFree(xmf);
}
}
char *GetStringSimple(XmString xms)
{
char *s;
if (XmStringGetLtoR(xms, charset, &s)) {
return s;
} else {
return NULL;
}
}
extern int ReqUpdateColorSel;
void update_all(void)
{
int gno = get_cg();
if (!inwin) {
return;
}
update_set_lists(gno);
update_set_selectors(ALL_GRAPHS);
update_ss_editors(ALL_GRAPHS);
if (ReqUpdateColorSel == TRUE) {
update_color_selectors();
ReqUpdateColorSel = FALSE;
}
update_ticks(gno);
update_props_items();
update_hotlinks();
update_prune_frame();
update_locator_items(gno);
set_stack_message();
set_left_footer(NULL);
}
void update_all_cb(void *data)
{
update_all();
}
syntax highlighted by Code2HTML, v. 0.9.1