"Fossies" - the Fresh Open Source Software Archive

Member "grace-5.1.25/src/motifutils.c" (14 Feb 2015, 110412 Bytes) of package /linux/misc/grace-5.1.25.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "motifutils.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.1.24_vs_5.1.25.

    1 /*
    2  * Grace - GRaphing, Advanced Computation and Exploration of data
    3  * 
    4  * Home page: http://plasma-gate.weizmann.ac.il/Grace/
    5  * 
    6  * Copyright (c) 1991-1995 Paul J Turner, Portland, OR
    7  * Copyright (c) 1996-2003 Grace Development Team
    8  * 
    9  * Maintained by Evgeny Stambulchik
   10  * 
   11  * 
   12  *                           All Rights Reserved
   13  * 
   14  *    This program is free software; you can redistribute it and/or modify
   15  *    it under the terms of the GNU General Public License as published by
   16  *    the Free Software Foundation; either version 2 of the License, or
   17  *    (at your option) any later version.
   18  * 
   19  *    This program is distributed in the hope that it will be useful,
   20  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
   21  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   22  *    GNU General Public License for more details.
   23  * 
   24  *    You should have received a copy of the GNU General Public License
   25  *    along with this program; if not, write to the Free Software
   26  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   27  */
   28 
   29 /*
   30  *
   31  * utilities for Motif
   32  *
   33  */
   34 
   35 #include <config.h>
   36 #include <cmath.h>
   37 
   38 #include <stdlib.h>
   39 #include <ctype.h>
   40 #include <stdarg.h>
   41 
   42 #include <X11/X.h>
   43 #include <X11/Xatom.h>
   44 #include <X11/cursorfont.h>
   45 
   46 #include <Xm/Xm.h>
   47 #include <Xm/Protocols.h>
   48 #include <Xm/BulletinB.h>
   49 #include <Xm/MessageB.h>
   50 #include <Xm/DialogS.h>
   51 #include <Xm/FileSB.h>
   52 #include <Xm/Frame.h>
   53 #include <Xm/Form.h>
   54 #include <Xm/Scale.h>
   55 #include <Xm/Label.h>
   56 #include <Xm/LabelG.h>
   57 #include <Xm/List.h>
   58 #include <Xm/PushB.h>
   59 #include <Xm/CascadeBG.h>
   60 #include <Xm/RowColumn.h>
   61 #include <Xm/Separator.h>
   62 #include <Xm/Text.h>
   63 #include <Xm/ToggleB.h>
   64 #include <Xm/ArrowBG.h>
   65 
   66 #ifdef WITH_EDITRES
   67 #  include <X11/Xmu/Editres.h>
   68 #endif
   69 
   70 #if XmVersion < 2000
   71 #  define XmStringConcatAndFree(a, b) XmStringConcat(a, b); XmStringFree(a); XmStringFree(b)
   72 #endif
   73 
   74 #include "Tab.h"
   75 #include "motifinc.h"
   76 
   77 #include "defines.h"
   78 #include "globals.h"
   79 #include "draw.h"
   80 #include "patterns.h"
   81 #include "jbitmaps.h"
   82 #include "t1fonts.h"
   83 #include "graphs.h"
   84 #include "utils.h"
   85 #include "events.h"
   86 #include "parser.h"
   87 #include "protos.h"
   88 
   89 static XmStringCharSet charset = XmFONTLIST_DEFAULT_TAG;
   90 
   91 /* lookup table to determine if character is a floating point digit 
   92  * only allowable char's [0-9.eE]
   93  */
   94 unsigned char fpdigit[256] = {  
   95                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   96                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   97                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
   98                   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
   99                   0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  100                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  101                   0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  102                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  103                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  104                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  105                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  106                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  107                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  108                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  109                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  110                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  111 
  112 
  113 extern Display *disp;
  114 extern Window root;
  115 extern int depth;
  116 
  117 extern XtAppContext app_con;
  118 
  119 extern unsigned long xvlibcolors[];
  120 
  121 
  122 static OptionItem *color_option_items = NULL;
  123 static int ncolor_option_items = 0;
  124 static OptionStructure **color_selectors = NULL;
  125 static int ncolor_selectors = 0;
  126 
  127 static char *label_to_resname(const char *s, const char *suffix)
  128 {
  129     char *retval, *rs;
  130     int capitalize = FALSE;
  131     
  132     retval = copy_string(NULL, s);
  133     rs = retval;
  134     while (*s) {
  135         if (isalnum(*s)) {
  136             if (capitalize == TRUE) {
  137                 *rs = toupper(*s);
  138                 capitalize = FALSE;
  139             } else {
  140                 *rs = tolower(*s);
  141             }
  142             rs++;
  143         } else {
  144             capitalize = TRUE;
  145         }
  146         s++;
  147     }
  148     *rs = '\0';
  149     if (suffix != NULL) {
  150         retval = concat_strings(retval, suffix);
  151     }
  152     return retval;
  153 }
  154 
  155 
  156 void ManageChild(Widget w)
  157 {
  158     XtManageChild(w);
  159 }
  160 
  161 void UnmanageChild(Widget w)
  162 {
  163     XtUnmanageChild(w);
  164 }
  165 
  166 void SetSensitive(Widget w, int onoff)
  167 {
  168     XtSetSensitive(w, onoff ? True : False);
  169 }
  170 
  171 Widget GetParent(Widget w)
  172 {
  173     if (w) {
  174         return (XtParent(w));
  175     } else {
  176         errmsg("Internal error: GetParent() called with NULL widget");
  177         return NULL;
  178     }
  179 }
  180 
  181 void RegisterEditRes(Widget shell)
  182 {
  183 #ifdef WITH_EDITRES    
  184     XtAddEventHandler(shell, (EventMask) 0, True, _XEditResCheckMessages, NULL);
  185 #endif
  186 }
  187 
  188 void SetDimensions(Widget w, unsigned int width, unsigned int height)
  189 {
  190     XtVaSetValues(w,
  191         XmNwidth, (Dimension) width,
  192         XmNheight, (Dimension) height,
  193         NULL);
  194 }
  195 
  196 void GetDimensions(Widget w, unsigned int *width, unsigned int *height)
  197 {
  198     Dimension ww, wh;
  199 
  200     XtVaGetValues(w,
  201         XmNwidth, &ww,
  202         XmNheight, &wh,
  203         NULL);
  204 
  205     *width  = (unsigned int) ww;
  206     *height = (unsigned int) wh;
  207 }
  208 
  209 #define MAX_PULLDOWN_LENGTH 30
  210 
  211 OptionStructure *CreateOptionChoice(Widget parent, char *labelstr, int ncols,
  212                                                 int nchoices, OptionItem *items)
  213 {
  214     Arg args[2];
  215     XmString str;
  216     OptionStructure *retval;
  217 
  218     retval = xmalloc(sizeof(OptionStructure));
  219 
  220     XtSetArg(args[0], XmNpacking, XmPACK_COLUMN);
  221     retval->pulldown = XmCreatePulldownMenu(parent, "pulldownMenu", args, 1);
  222 
  223     retval->ncols = ncols;
  224     
  225     retval->nchoices = 0;
  226     retval->options = NULL;
  227     UpdateOptionChoice(retval, nchoices, items);
  228 
  229     str = XmStringCreateLocalized(labelstr);
  230     XtSetArg(args[0], XmNlabelString, str);
  231     XtSetArg(args[1], XmNsubMenuId, retval->pulldown);
  232 
  233     retval->menu = XmCreateOptionMenu(parent, "optionMenu", args, 2);
  234 
  235     XmStringFree(str);
  236 
  237     XtManageChild(retval->menu);
  238     
  239     return retval;
  240 }
  241 
  242 void UpdateOptionChoice(OptionStructure *optp, int nchoices, OptionItem *items)
  243 {
  244     int i, nold, ncols, nw;
  245     Widget *wlist;
  246     
  247     nold = optp->nchoices;
  248 
  249     if (optp->ncols == 0) {
  250         ncols = 1;
  251     } else {
  252         ncols = optp->ncols;
  253     }
  254     
  255     /* Don't create too tall pulldowns */
  256     if (nchoices > MAX_PULLDOWN_LENGTH*ncols) {
  257         ncols = (nchoices + MAX_PULLDOWN_LENGTH - 1)/MAX_PULLDOWN_LENGTH;
  258     }
  259     
  260     XtVaSetValues(optp->pulldown, XmNnumColumns, ncols, NULL);
  261 
  262     nw = nold - nchoices;
  263     if (nw > 0) {
  264         /* Unmanage extra items before destroying to speed the things up */
  265         wlist = xmalloc(nw*sizeof(Widget));
  266         for (i = nchoices; i < nold; i++) {
  267             wlist[i - nchoices] = optp->options[i].widget;
  268         }
  269         XtUnmanageChildren(wlist, nw);
  270         xfree(wlist);
  271         
  272         for (i = nchoices; i < nold; i++) {
  273             XtDestroyWidget(optp->options[i].widget);
  274         }
  275     }
  276 
  277     optp->options = xrealloc(optp->options, nchoices*sizeof(OptionWidgetItem));
  278     optp->nchoices = nchoices;
  279 
  280     for (i = nold; i < nchoices; i++) {
  281         optp->options[i].widget = 
  282                   XmCreatePushButton(optp->pulldown, "button", NULL, 0);
  283     }
  284     
  285     for (i = 0; i < nchoices; i++) {
  286     optp->options[i].value = items[i].value;
  287     if (items[i].label != NULL) {
  288             XmString str, ostr;
  289             XtVaGetValues(optp->options[i].widget, XmNlabelString, &ostr, NULL);
  290             str = XmStringCreateLocalized(items[i].label);
  291             if (XmStringCompare(str, ostr) != True) {
  292                 XtVaSetValues(optp->options[i].widget, XmNlabelString, str, NULL);
  293             }
  294             XmStringFree(str);
  295         }
  296     }
  297     
  298     nw = nchoices - nold;
  299     if (nw > 0) {
  300         wlist = xmalloc(nw*sizeof(Widget));
  301         for (i = nold; i < nchoices; i++) {
  302             wlist[i - nold] = optp->options[i].widget;
  303         }
  304         XtManageChildren(wlist, nw);
  305         xfree(wlist);
  306     }
  307 }
  308 
  309 OptionStructure *CreateBitmapOptionChoice(Widget parent, char *labelstr, int ncols,
  310                 int nchoices, int width, int height, BitmapOptionItem *items)
  311 {
  312     int i;
  313     XmString str;
  314     OptionStructure *retval;
  315     Pixel fg, bg;
  316     Pixmap ptmp;
  317 
  318     retval = xmalloc(sizeof(OptionStructure));
  319     if (retval == NULL) {
  320         errmsg("Malloc error in CreateBitmapOptionChoice()");
  321     }
  322     retval->nchoices = nchoices;
  323     retval->options = xmalloc(nchoices*sizeof(OptionWidgetItem));
  324     if (retval->options == NULL) {
  325         errmsg("Malloc error in CreateBitmapOptionChoice()");
  326         XCFREE(retval);
  327         return retval;
  328     }
  329 
  330 
  331     retval->pulldown = XmCreatePulldownMenu(parent, "pulldownMenu", NULL, 0);
  332     XtVaSetValues(retval->pulldown, 
  333                   XmNentryAlignment, XmALIGNMENT_CENTER,
  334                   NULL);
  335 
  336     if (ncols > 0) {
  337         XtVaSetValues(retval->pulldown,
  338                       XmNpacking, XmPACK_COLUMN,
  339                       XmNnumColumns, ncols,
  340                       NULL);
  341     }
  342     
  343     XtVaGetValues(retval->pulldown,
  344                   XmNforeground, &fg,
  345                   XmNbackground, &bg,
  346                   NULL);
  347     
  348     for (i = 0; i < nchoices; i++) {
  349     retval->options[i].value = items[i].value;
  350         if (items[i].bitmap != NULL) {
  351             ptmp = XCreatePixmapFromBitmapData(disp, root, 
  352                                     (char *) items[i].bitmap, width, height,
  353                                     fg, bg, depth);
  354             retval->options[i].widget = 
  355                 XtVaCreateWidget("pixButton", xmPushButtonWidgetClass,
  356                                  retval->pulldown,
  357                              XmNlabelType, XmPIXMAP,
  358                              XmNlabelPixmap, ptmp,
  359                              NULL);
  360         } else {
  361         retval->options[i].widget = 
  362                   XmCreatePushButton(retval->pulldown, "None", NULL, 0);
  363         }
  364                                 
  365     }
  366     for (i = 0; i < nchoices; i++) {
  367         XtManageChild(retval->options[i].widget);
  368     }
  369 
  370     retval->menu = XmCreateOptionMenu(parent, "optionMenu", NULL, 0);
  371     str = XmStringCreateLocalized(labelstr);
  372     XtVaSetValues(retval->menu,
  373           XmNlabelString, str,
  374           XmNsubMenuId, retval->pulldown,
  375           NULL);
  376     XmStringFree(str);
  377     XtManageChild(retval->menu);
  378     
  379     return retval;
  380 }
  381 
  382 
  383 void SetOptionChoice(OptionStructure *opt, int value)
  384 {
  385     int i;
  386     Arg a;
  387     
  388     if (opt->options == NULL || opt->nchoices <= 0) {
  389         return;
  390     }
  391     
  392     for (i = 0; i < opt->nchoices; i++) {
  393         if (opt->options[i].value == value) {
  394             XtSetArg(a, XmNmenuHistory, opt->options[i].widget);
  395             XtSetValues(opt->menu, &a, 1);
  396             return;
  397         }
  398     }
  399 }
  400 
  401 int GetOptionChoice(OptionStructure *opt)
  402 {
  403     Arg a;
  404     Widget warg;
  405     int i;
  406 
  407     if (opt->options == NULL || opt->nchoices <= 0) {
  408         errmsg("Internal error in GetOptionChoice()");
  409         return 0;
  410     }
  411 
  412     XtSetArg(a, XmNmenuHistory, &warg);
  413     XtGetValues(opt->menu, &a, 1);
  414 
  415     for (i = 0; i < opt->nchoices; i++) {
  416         if (opt->options[i].widget == warg) {
  417             return(opt->options[i].value);
  418         }
  419     }
  420     errmsg("Internal error in GetOptionChoice()");
  421     return 0;
  422 }
  423 
  424 typedef struct {
  425     OptionStructure *opt;
  426     void (*cbproc)();
  427     void *anydata;
  428 } OC_CBdata;
  429 
  430 static void oc_int_cb_proc(Widget w, XtPointer client_data, XtPointer call_data)
  431 {
  432     int value;
  433     
  434     OC_CBdata *cbdata = (OC_CBdata *) client_data;
  435 
  436     value = GetOptionChoice(cbdata->opt);
  437     cbdata->cbproc(value, cbdata->anydata);
  438 }
  439 
  440 void AddOptionChoiceCB(OptionStructure *opt, OC_CBProc cbproc, void *anydata)
  441 {
  442     OC_CBdata *cbdata;
  443     int i;
  444     
  445     cbdata = xmalloc(sizeof(OC_CBdata));
  446     
  447     cbdata->opt = opt;
  448     cbdata->cbproc = cbproc;
  449     cbdata->anydata = anydata;
  450     for (i = 0; i < opt->nchoices; i++) {
  451         XtAddCallback(opt->options[i].widget, XmNactivateCallback, 
  452                                     oc_int_cb_proc, (XtPointer) cbdata);
  453     }
  454 }
  455 
  456 
  457 static char list_translation_table[] = "\
  458     Ctrl<Key>A: list_selectall_action()\n\
  459     Ctrl<Key>U: list_unselectall_action()\n\
  460     Ctrl<Key>I: list_invertselection_action()";
  461 
  462 ListStructure *CreateListChoice(Widget parent, char *labelstr, int type,
  463                                 int nvisible, int nchoices, OptionItem *items)
  464 {
  465     Arg args[4];
  466     Widget lab;
  467     ListStructure *retval;
  468 
  469     retval = xmalloc(sizeof(ListStructure));
  470     retval->rc = XmCreateRowColumn(parent, "rcList", NULL, 0);
  471     AddHelpCB(retval->rc, "doc/UsersGuide.html#list-selector");
  472 
  473     lab = XmCreateLabel(retval->rc, labelstr, NULL, 0);
  474     XtManageChild(lab);
  475     
  476     XtSetArg(args[0], XmNlistSizePolicy, XmCONSTANT);
  477     XtSetArg(args[1], XmNscrollBarDisplayPolicy, XmSTATIC);
  478     if (type == LIST_TYPE_SINGLE) {
  479         XtSetArg(args[2], XmNselectionPolicy, XmSINGLE_SELECT);
  480     } else {
  481         XtSetArg(args[2], XmNselectionPolicy, XmEXTENDED_SELECT);
  482     }
  483     XtSetArg(args[3], XmNvisibleItemCount, nvisible);
  484     retval->list = XmCreateScrolledList(retval->rc, "listList", args, 4);
  485     retval->values = NULL;
  486 
  487     XtOverrideTranslations(retval->list, 
  488                              XtParseTranslationTable(list_translation_table));
  489     
  490     UpdateListChoice(retval, nchoices, items);
  491 
  492     XtManageChild(retval->list);
  493     
  494     XtManageChild(retval->rc);
  495     
  496     return retval;
  497 }
  498 
  499 void UpdateListChoice(ListStructure *listp, int nchoices, OptionItem *items)
  500 {
  501     int i, nsel;
  502     int *selvalues;
  503     XmString str;
  504     
  505     if (listp == NULL) {
  506         return;
  507     }
  508     
  509     nsel = GetListChoices(listp, &selvalues);
  510 
  511     listp->nchoices = nchoices;
  512     listp->values = xrealloc(listp->values, nchoices*SIZEOF_INT);
  513     for (i = 0; i < nchoices; i++) {
  514         listp->values[i] = items[i].value;
  515     }
  516     
  517     XmListDeleteAllItems(listp->list);
  518     for (i = 0; i < nchoices; i++) {
  519     str = XmStringCreateLocalized(items[i].label);
  520         XmListAddItemUnselected(listp->list, str, 0);
  521         XmStringFree(str);
  522     }
  523     SelectListChoices(listp, nsel, selvalues);
  524     if (nsel > 0) {
  525         xfree(selvalues);
  526     }
  527 }
  528 
  529 int SelectListChoice(ListStructure *listp, int choice)
  530 {
  531     int top, visible;
  532     int i = 0;
  533     
  534     while (i < listp->nchoices && listp->values[i] != choice) {
  535         i++;
  536     }
  537     if (i < listp->nchoices) {
  538         i++;
  539         XmListDeselectAllItems(listp->list);
  540         XmListSelectPos(listp->list, i, True);
  541         XtVaGetValues(listp->list, XmNtopItemPosition, &top,
  542                                  XmNvisibleItemCount, &visible,
  543                                  NULL);
  544         if (i < top) {
  545             XmListSetPos(listp->list, i);
  546         } else if (i >= top + visible) {
  547             XmListSetBottomPos(listp->list, i);
  548         }
  549         
  550         return RETURN_SUCCESS;
  551     } else {
  552         return RETURN_FAILURE;
  553     }
  554 }
  555 
  556 void SelectListChoices(ListStructure *listp, int nchoices, int *choices)
  557 {
  558     int i = 0, j;
  559     unsigned char selection_type_save;
  560     int bottom, visible;
  561     
  562     XtVaGetValues(listp->list, XmNselectionPolicy, &selection_type_save, NULL);
  563     XtVaSetValues(listp->list, XmNselectionPolicy, XmMULTIPLE_SELECT, NULL);
  564                              
  565     XmListDeselectAllItems(listp->list);
  566     for (j = 0; j < nchoices; j++) {
  567         i = 0;
  568         while (i < listp->nchoices && listp->values[i] != choices[j]) {
  569             i++;
  570         }
  571         if (i < listp->nchoices) {
  572             i++;
  573             XmListSelectPos(listp->list, i, True);
  574         }
  575     }
  576     
  577     if (nchoices > 0) {
  578         /* Rewind list so the last choice is always visible */
  579         XtVaGetValues(listp->list, XmNtopItemPosition, &bottom,
  580                                  XmNvisibleItemCount, &visible,
  581                                  NULL);
  582         if (i > bottom) {
  583             XmListSetBottomPos(listp->list, i);
  584         } else if (i <= bottom - visible) {
  585             XmListSetPos(listp->list, i);
  586         }
  587     }
  588 
  589     XtVaSetValues(listp->list, XmNselectionPolicy, selection_type_save, NULL);
  590 }
  591 
  592 int GetListChoices(ListStructure *listp, int **values)
  593 {
  594     int i, n;
  595     
  596     if (XmListGetSelectedPos(listp->list, values, &n) != True) {
  597         return 0;
  598     }
  599     
  600     for (i = 0; i < n; i++) {
  601         (*values)[i] = listp->values[(*values)[i] - 1];
  602     }
  603     
  604     return n;
  605 }
  606 
  607 int GetSingleListChoice(ListStructure *listp, int *value)
  608 {
  609     int n, *values, retval;
  610  
  611     n = GetListChoices(listp, &values);
  612     if (n == 1) {
  613         *value = values[0];
  614         retval = RETURN_SUCCESS;
  615     } else {
  616         retval = RETURN_FAILURE;
  617     }
  618     if (n > 0) {
  619         xfree(values);
  620     }
  621     return retval;
  622 }
  623 
  624 typedef struct {
  625     ListStructure *listp;
  626     void (*cbproc)();
  627     void *anydata;
  628 } List_CBdata;
  629 
  630 static void list_int_cb_proc(Widget w, XtPointer client_data, XtPointer call_data)
  631 {
  632     int n, *values;
  633     List_CBdata *cbdata = (List_CBdata *) client_data;
  634  
  635     n = GetListChoices(cbdata->listp, &values);
  636     
  637     cbdata->cbproc(n, values, cbdata->anydata);
  638 
  639     if (n > 0) {
  640         xfree(values);
  641     }
  642 }
  643 
  644 void AddListChoiceCB(ListStructure *listp, List_CBProc cbproc, void *anydata)
  645 {
  646     List_CBdata *cbdata;
  647     
  648     cbdata = xmalloc(sizeof(List_CBdata));
  649     cbdata->listp = listp;
  650     cbdata->cbproc = (List_CBProc) cbproc;
  651     cbdata->anydata = anydata;
  652     XtAddCallback(listp->list,
  653         XmNsingleSelectionCallback,   list_int_cb_proc, (XtPointer) cbdata);
  654     XtAddCallback(listp->list,
  655         XmNmultipleSelectionCallback, list_int_cb_proc, (XtPointer) cbdata);
  656     XtAddCallback(listp->list,
  657         XmNextendedSelectionCallback, list_int_cb_proc, (XtPointer) cbdata);
  658 }
  659 
  660 
  661 static void spin_arrow_cb(Widget w, XtPointer client_data, XtPointer call_data)
  662 {
  663     SpinStructure *spinp;
  664     double value, incr;
  665     
  666     spinp = (SpinStructure *) client_data;
  667     value = GetSpinChoice(spinp);
  668     incr = spinp->incr;
  669     
  670     if (w == spinp->arrow_up) {
  671         incr =  spinp->incr;
  672     } else if (w == spinp->arrow_down) {
  673         incr = -spinp->incr;
  674     } else {
  675         errmsg("Wrong call to spin_arrow_cb()");
  676         return;
  677     }
  678     value += incr;
  679     SetSpinChoice(spinp, value);
  680 }
  681 
  682 SpinStructure *CreateSpinChoice(Widget parent, char *s, int len,
  683                         int type, double min, double max, double incr)
  684 {
  685     SpinStructure *retval;
  686     Widget fr, form;
  687     XmString str;
  688     
  689     if (min >= max) {
  690         errmsg("min >= max in CreateSpinChoice()!");
  691         return NULL;
  692     }
  693     
  694     retval = xmalloc(sizeof(SpinStructure));
  695     
  696     retval->type = type;
  697     retval->min = min;
  698     retval->max = max;
  699     retval->incr = incr;
  700     
  701     retval->rc = XtVaCreateWidget("rc", xmRowColumnWidgetClass, parent,
  702         XmNorientation, XmHORIZONTAL,
  703         NULL);
  704     str = XmStringCreateLocalized(s);
  705     XtVaCreateManagedWidget("label", xmLabelWidgetClass, retval->rc,
  706     XmNlabelString, str,
  707     NULL);
  708     XmStringFree(str);
  709     fr = XtVaCreateWidget("fr", xmFrameWidgetClass, retval->rc,
  710         XmNshadowType, XmSHADOW_ETCHED_OUT,
  711         NULL);
  712     form = XtVaCreateWidget("form", xmFormWidgetClass, fr,
  713         NULL);
  714     retval->text = XtVaCreateWidget("text", xmTextWidgetClass, form,
  715     XmNtraversalOn, True,
  716     XmNcolumns, len,
  717     NULL);
  718     retval->arrow_up = XtVaCreateWidget("form", xmArrowButtonGadgetClass, form,
  719         XmNarrowDirection, XmARROW_UP,
  720         NULL);
  721     XtAddCallback(retval->arrow_up, XmNactivateCallback,
  722         spin_arrow_cb, (XtPointer) retval);
  723     retval->arrow_down = XtVaCreateWidget("form", xmArrowButtonGadgetClass, form,
  724         XmNarrowDirection, XmARROW_DOWN,
  725         NULL);
  726     XtAddCallback(retval->arrow_down, XmNactivateCallback,
  727         spin_arrow_cb, (XtPointer) retval);
  728     XtVaSetValues(retval->text,
  729         XmNtopAttachment, XmATTACH_FORM,
  730         XmNleftAttachment, XmATTACH_FORM,
  731         XmNbottomAttachment, XmATTACH_FORM,
  732         XmNrightAttachment, XmATTACH_NONE,
  733         NULL);
  734     XtVaSetValues(retval->arrow_down,
  735         XmNtopAttachment, XmATTACH_FORM,
  736         XmNbottomAttachment, XmATTACH_FORM,
  737         XmNleftAttachment, XmATTACH_WIDGET,
  738         XmNleftWidget, retval->text,
  739         XmNrightAttachment, XmATTACH_NONE,
  740         NULL);
  741     XtVaSetValues(retval->arrow_up,
  742         XmNtopAttachment, XmATTACH_FORM,
  743         XmNbottomAttachment, XmATTACH_FORM,
  744         XmNrightAttachment, XmATTACH_FORM,
  745         XmNleftAttachment, XmATTACH_WIDGET,
  746         XmNleftWidget, retval->arrow_down,
  747         NULL);
  748     
  749     XtManageChild(retval->text);
  750     XtManageChild(retval->arrow_up);
  751     XtManageChild(retval->arrow_down);
  752     XtManageChild(form);
  753     XtManageChild(fr);
  754     XtManageChild(retval->rc);
  755     
  756     return retval;
  757 }
  758 
  759 void SetSpinChoice(SpinStructure *spinp, double value)
  760 {
  761     char buf[64];
  762     
  763     if (value < spinp->min) {
  764         XBell(disp, 50);
  765         value = spinp->min;
  766     } else if (value > spinp->max) {
  767         XBell(disp, 50);
  768         value = spinp->max;
  769     }
  770     
  771     if (spinp->type == SPIN_TYPE_FLOAT) {
  772         sprintf(buf, "%g", value);
  773     } else {
  774         sprintf(buf, "%d", (int) rint(value));
  775     }
  776     XmTextSetString(spinp->text, buf);
  777 }
  778 
  779 double GetSpinChoice(SpinStructure *spinp)
  780 {
  781     double retval;
  782     
  783     xv_evalexpr(spinp->text, &retval);
  784     if (retval < spinp->min) {
  785         errmsg("Input value below min limit in GetSpinChoice()");
  786         retval = spinp->min;
  787         SetSpinChoice(spinp, retval);
  788     } else if (retval > spinp->max) {
  789         errmsg("Input value above max limit in GetSpinChoice()");
  790         retval = spinp->max;
  791         SetSpinChoice(spinp, retval);
  792     }
  793     
  794     if (spinp->type == SPIN_TYPE_INT) {
  795         return rint(retval);
  796     } else {
  797         return retval;
  798     }
  799 }
  800 
  801 
  802 TextStructure *CreateTextInput(Widget parent, char *s)
  803 {
  804     TextStructure *retval;
  805     XmString str;
  806     
  807     retval = xmalloc(sizeof(TextStructure));
  808     retval->form = XtVaCreateWidget("form", xmFormWidgetClass, parent, NULL);
  809 
  810     str = XmStringCreateLocalized(s);
  811     retval->label = XtVaCreateManagedWidget("label", 
  812         xmLabelWidgetClass, retval->form,
  813         XmNlabelString, str,
  814         XmNtopAttachment, XmATTACH_FORM,
  815         XmNbottomAttachment, XmATTACH_FORM,
  816         XmNleftAttachment, XmATTACH_FORM,
  817         XmNrightAttachment, XmATTACH_NONE,
  818         NULL);
  819     XmStringFree(str);
  820 
  821     retval->text = XtVaCreateManagedWidget("cstext",
  822         xmTextWidgetClass, retval->form,
  823         XmNtraversalOn, True,
  824         XmNtopAttachment, XmATTACH_FORM,
  825         XmNbottomAttachment, XmATTACH_FORM,
  826         XmNleftAttachment, XmATTACH_WIDGET,
  827         XmNleftWidget, retval->label,
  828         XmNrightAttachment, XmATTACH_FORM,
  829         NULL);
  830 
  831     XtManageChild(retval->form);
  832 
  833     return retval;
  834 }
  835 
  836 void cstext_edit_action(Widget w, XEvent *e, String *par, Cardinal *npar)
  837 {
  838     create_fonttool(w);
  839 }
  840 
  841 static char cstext_translation_table[] = "\
  842     Ctrl<Key>E: cstext_edit_action()";
  843 
  844 TextStructure *CreateCSText(Widget parent, char *s)
  845 {
  846     TextStructure *retval;
  847 
  848     retval = CreateTextInput(parent, s);
  849     XtOverrideTranslations(retval->text, 
  850         XtParseTranslationTable(cstext_translation_table));
  851         
  852     return retval;
  853 }
  854 
  855 char *GetTextString(TextStructure *cst)
  856 {
  857     static char *buf = NULL;
  858     char *s;
  859     
  860     s = XmTextGetString(cst->text);
  861     buf = copy_string(buf, s);
  862     XtFree(s);
  863     
  864     return buf;
  865 }
  866 
  867 void SetTextString(TextStructure *cst, char *s)
  868 {
  869     XmTextSetString(cst->text, s ? s : "");
  870 }
  871 
  872 typedef struct {
  873     void (*cbproc)();
  874     void *anydata;
  875 } Text_CBdata;
  876 
  877 static void text_int_cb_proc(Widget w, XtPointer client_data, XtPointer call_data)
  878 {
  879     Text_CBdata *cbdata = (Text_CBdata *) client_data;
  880     cbdata->cbproc(cbdata->anydata);
  881 }
  882 
  883 void AddTextInputCB(TextStructure *cst, Text_CBProc cbproc, void *data)
  884 {
  885     Text_CBdata *cbdata;
  886     
  887     cbdata = xmalloc(sizeof(Text_CBdata));
  888     cbdata->anydata = data;
  889     cbdata->cbproc = cbproc;
  890     
  891     XtAddCallback(cst->text,
  892         XmNactivateCallback, text_int_cb_proc, (XtPointer) cbdata);
  893 }
  894 
  895 int GetTextCursorPos(TextStructure *cst)
  896 {
  897     return XmTextGetInsertionPosition(cst->text);
  898 }
  899 
  900 void TextInsert(TextStructure *cst, int pos, char *s)
  901 {
  902     XmTextInsert(cst->text, pos, s);
  903 }
  904 
  905 
  906 typedef struct {
  907     void (*cbproc)();
  908     void *anydata;
  909 } Button_CBdata;
  910 
  911 Widget CreateButton(Widget parent, char *label)
  912 {
  913     Widget button;
  914     XmString xmstr;
  915     
  916     xmstr = XmStringCreateLocalized(label);
  917     button = XtVaCreateManagedWidget("button",
  918         xmPushButtonWidgetClass, parent, 
  919         XmNalignment, XmALIGNMENT_CENTER,
  920         XmNlabelString, xmstr,
  921 /*
  922  *         XmNmarginLeft, 5,
  923  *         XmNmarginRight, 5,
  924  *         XmNmarginTop, 3,
  925  *         XmNmarginBottom, 2,
  926  */
  927         NULL);
  928     XmStringFree(xmstr);
  929 
  930     return button;
  931 }
  932 
  933 Widget CreateBitmapButton(Widget parent,
  934     int width, int height, const unsigned char *bits)
  935 {
  936     Widget button;
  937     Pixmap pm;
  938     Pixel fg, bg;
  939 
  940     button = XtVaCreateManagedWidget("button",
  941         xmPushButtonWidgetClass, parent, 
  942     XmNlabelType, XmPIXMAP,
  943         NULL);
  944     
  945 /*
  946  * We need to get right fore- and background colors for pixmap.
  947  */    
  948     XtVaGetValues(button,
  949           XmNforeground, &fg,
  950           XmNbackground, &bg,
  951           NULL);
  952     pm = XCreatePixmapFromBitmapData(disp,
  953         root, (char *) bits, width, height, fg, bg, depth);
  954     XtVaSetValues(button, XmNlabelPixmap, pm, NULL);
  955 
  956     return button;
  957 }
  958 
  959 static void button_int_cb_proc(Widget w, XtPointer client_data, XtPointer call_data)
  960 {
  961     Button_CBdata *cbdata = (Button_CBdata *) client_data;
  962     cbdata->cbproc(cbdata->anydata);
  963 }
  964 
  965 void AddButtonCB(Widget button, Button_CBProc cbproc, void *data)
  966 {
  967     Button_CBdata *cbdata;
  968     
  969     cbdata = xmalloc(sizeof(Button_CBdata));
  970     cbdata->anydata = data;
  971     cbdata->cbproc = cbproc;
  972     XtAddCallback(button,
  973         XmNactivateCallback, button_int_cb_proc, (XtPointer) cbdata);
  974 }
  975 
  976 static void fsb_setcwd_cb(void *data)
  977 {
  978     char *bufp;
  979     XmString directory;
  980     Widget fsb = (Widget) data;
  981     
  982     XtVaGetValues(fsb, XmNdirectory, &directory, NULL);
  983     bufp = GetStringSimple(directory);
  984     XmStringFree(directory);
  985     if (bufp != NULL) {
  986         set_workingdir(bufp);
  987         XtFree(bufp);
  988     }
  989 }
  990 
  991 #define FSB_CWD     0
  992 #define FSB_HOME    1
  993 #define FSB_ROOT    2
  994 #define FSB_CYGDRV  3
  995 
  996 static void fsb_cd_cb(int value, void *data)
  997 {
  998     char *bufp;
  999     XmString dir, pattern, dirmask;
 1000     Widget FSB = (Widget) data;
 1001     
 1002     switch (value) {
 1003     case FSB_CWD:
 1004         bufp = get_workingdir();
 1005         break;
 1006     case FSB_HOME:
 1007     bufp = get_userhome();
 1008         break;
 1009     case FSB_ROOT:
 1010         bufp = "/";
 1011         break;
 1012     case FSB_CYGDRV:
 1013         bufp = "/cygdrive/";
 1014         break;
 1015     default:
 1016         return;
 1017     }
 1018     
 1019     XtVaGetValues(FSB, XmNpattern, &pattern, NULL);
 1020     
 1021     dir = XmStringCreateLocalized(bufp);
 1022     dirmask = XmStringConcatAndFree(dir, pattern);
 1023 
 1024     XmFileSelectionDoSearch(FSB, dirmask);
 1025     XmStringFree(dirmask);
 1026 }
 1027 
 1028 static OptionItem fsb_items[] = {
 1029     {FSB_CWD,  "Cwd"},
 1030     {FSB_HOME, "Home"},
 1031     {FSB_ROOT, "/"}
 1032 #ifdef __CYGWIN__
 1033     ,{FSB_CYGDRV, "My Computer"}
 1034 #endif
 1035 };
 1036 
 1037 #define FSB_ITEMS_NUM   sizeof(fsb_items)/sizeof(OptionItem)
 1038 
 1039 #if XmVersion >= 2000    
 1040 static void show_hidden_cb(int onoff, void *data)
 1041 {
 1042     FSBStructure *fsb = (FSBStructure *) data;
 1043     XtVaSetValues(fsb->FSB, XmNfileFilterStyle,
 1044         onoff ? XmFILTER_NONE:XmFILTER_HIDDEN_FILES, NULL);
 1045 }
 1046 #endif
 1047 
 1048 FSBStructure *CreateFileSelectionBox(Widget parent, char *s)
 1049 {
 1050     FSBStructure *retval;
 1051     OptionStructure *opt;
 1052     Widget fr, form, button;
 1053     XmString xmstr;
 1054     char *bufp, *resname;
 1055     
 1056     retval = xmalloc(sizeof(FSBStructure));
 1057     resname = label_to_resname(s, "FSB");
 1058     retval->FSB = XmCreateFileSelectionDialog(parent, resname, NULL, 0);
 1059     xfree(resname);
 1060     retval->dialog = XtParent(retval->FSB);
 1061     handle_close(retval->dialog);
 1062     bufp = copy_string(NULL, "Grace: ");
 1063     bufp = concat_strings(bufp, s);
 1064     XtVaSetValues(retval->dialog, XmNtitle, bufp, NULL);
 1065     xfree(bufp);
 1066     
 1067     xmstr = XmStringCreateLocalized(get_workingdir());
 1068     XtVaSetValues(retval->FSB, XmNdirectory, xmstr, NULL);
 1069     XmStringFree(xmstr);
 1070     
 1071     XtAddCallback(retval->FSB,
 1072         XmNcancelCallback, destroy_dialog, retval->dialog);
 1073     AddHelpCB(retval->FSB, "doc/UsersGuide.html#FS-dialog");
 1074     
 1075     retval->rc = XmCreateRowColumn(retval->FSB, "rc", NULL, 0);
 1076 #if XmVersion >= 2000    
 1077     button = CreateToggleButton(retval->rc, "Show hidden files");
 1078     AddToggleButtonCB(button, show_hidden_cb, retval);
 1079     XtVaSetValues(retval->FSB, XmNfileFilterStyle, XmFILTER_HIDDEN_FILES, NULL);
 1080 #endif
 1081     fr = CreateFrame(retval->rc, NULL);
 1082     form = XtVaCreateWidget("form", xmFormWidgetClass, fr, NULL);
 1083     opt = CreateOptionChoice(form, "Chdir to:", 1, FSB_ITEMS_NUM, fsb_items);
 1084     AddOptionChoiceCB(opt, fsb_cd_cb, (void *) retval->FSB);
 1085     button = CreateButton(form, "Set as cwd");
 1086     AddButtonCB(button, fsb_setcwd_cb, (void *) retval->FSB);
 1087 
 1088     XtVaSetValues(opt->menu,
 1089         XmNleftAttachment, XmATTACH_FORM,
 1090         XmNtopAttachment, XmATTACH_FORM,
 1091         XmNbottomAttachment, XmATTACH_FORM,
 1092         XmNrightAttachment, XmATTACH_NONE,
 1093         NULL);
 1094     XtVaSetValues(button,
 1095         XmNleftAttachment, XmATTACH_NONE,
 1096         XmNtopAttachment, XmATTACH_FORM,
 1097         XmNbottomAttachment, XmATTACH_FORM,
 1098         XmNrightAttachment, XmATTACH_FORM,
 1099         NULL);
 1100     XtManageChild(form);
 1101 
 1102     XtManageChild(retval->rc);
 1103         
 1104     return retval;
 1105 }
 1106 
 1107 typedef struct {
 1108     FSBStructure *fsb;
 1109     int (*cbproc)();
 1110     void *anydata;
 1111 } FSB_CBdata;
 1112 
 1113 static void fsb_int_cb_proc(Widget w, XtPointer client_data, XtPointer call_data)
 1114 {
 1115     char *s;
 1116     int ok;
 1117     
 1118     FSB_CBdata *cbdata = (FSB_CBdata *) client_data;
 1119     XmFileSelectionBoxCallbackStruct *cbs =
 1120         (XmFileSelectionBoxCallbackStruct *) call_data;
 1121 
 1122     s = GetStringSimple(cbs->value);
 1123     if (s == NULL) {
 1124     errmsg("Error converting XmString to char string");
 1125     return;
 1126     }
 1127 
 1128     set_wait_cursor();
 1129 
 1130     ok = cbdata->cbproc(s, cbdata->anydata);
 1131     XtFree(s);
 1132     if (ok) {
 1133         XtUnmanageChild(cbdata->fsb->dialog);
 1134     }
 1135     unset_wait_cursor();
 1136 }
 1137 
 1138 void AddFileSelectionBoxCB(FSBStructure *fsb, FSB_CBProc cbproc, void *anydata)
 1139 {
 1140     FSB_CBdata *cbdata;
 1141     
 1142     cbdata = xmalloc(sizeof(FSB_CBdata));
 1143     cbdata->fsb = fsb;
 1144     cbdata->cbproc = (FSB_CBProc) cbproc;
 1145     cbdata->anydata = anydata;
 1146     XtAddCallback(fsb->FSB,
 1147         XmNokCallback, fsb_int_cb_proc, (XtPointer) cbdata);
 1148 }
 1149 
 1150 void SetFileSelectionBoxPattern(FSBStructure *fsb, char *pattern)
 1151 {
 1152     XmString xmstr;
 1153     
 1154     if (pattern != NULL) {
 1155         xmstr = XmStringCreateLocalized(pattern);
 1156         XtVaSetValues(fsb->FSB, XmNpattern, xmstr, NULL);
 1157         XmStringFree(xmstr);
 1158     }
 1159 }
 1160 
 1161 Widget CreateLabel(Widget parent, char *s)
 1162 {
 1163     Widget label;
 1164     
 1165     label = XtVaCreateManagedWidget(s,
 1166         xmLabelWidgetClass, parent,
 1167         XmNalignment, XmALIGNMENT_BEGINNING,
 1168         XmNrecomputeSize, True,
 1169         NULL);
 1170     return label;
 1171 }
 1172 
 1173 void AlignLabel(Widget w, int alignment)
 1174 {
 1175     unsigned char xm_alignment;
 1176     
 1177     switch(alignment) {
 1178     case ALIGN_BEGINNING:
 1179         xm_alignment = XmALIGNMENT_BEGINNING;
 1180         break;
 1181     case ALIGN_CENTER:
 1182         xm_alignment = XmALIGNMENT_CENTER;
 1183         break;
 1184     case ALIGN_END:
 1185         xm_alignment = XmALIGNMENT_END;
 1186         break;
 1187     default:
 1188         errmsg("Internal error in AlignLabel()");
 1189         return;
 1190         break;
 1191     }
 1192     XtVaSetValues(w,
 1193         XmNalignment, xm_alignment,
 1194         NULL);
 1195 }
 1196 
 1197 static OptionItem *font_option_items;
 1198 static OptionItem *settype_option_items;
 1199 static BitmapOptionItem *pattern_option_items;
 1200 static BitmapOptionItem *lines_option_items;
 1201 
 1202 #define LINES_BM_HEIGHT 15
 1203 #define LINES_BM_WIDTH  64
 1204 
 1205 int init_option_menus(void) {
 1206     int i, j, k, l, n;
 1207     
 1208     n = number_of_fonts();
 1209     font_option_items = xmalloc(n*sizeof(OptionItem));
 1210     if (font_option_items == NULL) {
 1211         errmsg("Malloc error in init_option_menus()");
 1212         return RETURN_FAILURE;
 1213     }
 1214     for (i = 0; i < n; i++) {
 1215         font_option_items[i].value = i;
 1216         font_option_items[i].label = get_fontalias(i);
 1217     }
 1218     
 1219     n = number_of_patterns();
 1220     pattern_option_items = xmalloc(n*sizeof(BitmapOptionItem));
 1221     if (pattern_option_items == NULL) {
 1222         errmsg("Malloc error in init_option_menus()");
 1223         xfree(font_option_items);
 1224         return RETURN_FAILURE;
 1225     }
 1226     for (i = 0; i < n; i++) {
 1227         pattern_option_items[i].value = i;
 1228         if (i == 0) {
 1229             pattern_option_items[i].bitmap = NULL;
 1230         } else {
 1231             pattern_option_items[i].bitmap = pat_bits[i];
 1232         }
 1233     }
 1234     
 1235     n = number_of_linestyles();
 1236     lines_option_items = xmalloc(n*sizeof(BitmapOptionItem));
 1237     if (lines_option_items == NULL) {
 1238         errmsg("Malloc error in init_option_menus()");
 1239         xfree(pattern_option_items);
 1240         xfree(font_option_items);
 1241         return RETURN_FAILURE;
 1242     }
 1243     for (i = 0; i < n; i++) {
 1244         lines_option_items[i].value = i;
 1245         if (i == 0) {
 1246             lines_option_items[i].bitmap = NULL;
 1247             continue;
 1248         }
 1249         
 1250         lines_option_items[i].bitmap = 
 1251               xcalloc(LINES_BM_HEIGHT*LINES_BM_WIDTH/8/SIZEOF_CHAR, SIZEOF_CHAR);
 1252         
 1253         k = LINES_BM_WIDTH*(LINES_BM_HEIGHT/2);
 1254         while (k < LINES_BM_WIDTH*(LINES_BM_HEIGHT/2 + 1)) {
 1255             for (j = 0; j < dash_array_length[i]; j++) {
 1256                 for (l = 0; l < dash_array[i][j]; l++) {
 1257                     if (k < LINES_BM_WIDTH*(LINES_BM_HEIGHT/2 + 1)) {
 1258                         if (j % 2 == 0) { 
 1259                             /* black */
 1260                             lines_option_items[i].bitmap[k/8] |= 1 << k % 8;
 1261                         }
 1262                         k++;
 1263                     }
 1264                 }
 1265             }
 1266         }
 1267     }
 1268 
 1269     settype_option_items = xmalloc(NUMBER_OF_SETTYPES*sizeof(OptionItem));
 1270     if (settype_option_items == NULL) {
 1271         errmsg("Malloc error in init_option_menus()");
 1272         return RETURN_FAILURE;
 1273     }
 1274     for (i = 0; i < NUMBER_OF_SETTYPES; i++) {
 1275         settype_option_items[i].value = i;
 1276         settype_option_items[i].label = copy_string(NULL, set_types(i));
 1277         lowtoupper(settype_option_items[i].label);
 1278     }
 1279 
 1280     return RETURN_SUCCESS;
 1281 }
 1282 
 1283 OptionStructure *CreateFontChoice(Widget parent, char *s)
 1284 {
 1285     return (CreateOptionChoice(parent,
 1286         s, 0, number_of_fonts(), font_option_items));
 1287 }
 1288 
 1289 OptionStructure *CreatePatternChoice(Widget parent, char *s)
 1290 {
 1291     return (CreateBitmapOptionChoice(parent, s, 4, number_of_patterns(), 
 1292                                      16, 16, pattern_option_items));
 1293 }
 1294 
 1295 OptionStructure *CreateLineStyleChoice(Widget parent, char *s)
 1296 {
 1297     return (CreateBitmapOptionChoice(parent, s, 0, number_of_linestyles(), 
 1298                         LINES_BM_WIDTH, LINES_BM_HEIGHT, lines_option_items));
 1299 }
 1300 
 1301 OptionStructure *CreateSetTypeChoice(Widget parent, char *s)
 1302 {
 1303     return (CreateOptionChoice(parent,
 1304         s, 0, NUMBER_OF_SETTYPES, settype_option_items));
 1305 }
 1306 
 1307 static BitmapOptionItem just_option_items[12] =
 1308 {
 1309     {JUST_LEFT  |JUST_BLINE , j_lm_o_bits},
 1310     {JUST_CENTER|JUST_BLINE , j_cm_o_bits},
 1311     {JUST_RIGHT |JUST_BLINE , j_rm_o_bits},
 1312     {JUST_LEFT  |JUST_BOTTOM, j_lb_b_bits},
 1313     {JUST_CENTER|JUST_BOTTOM, j_cb_b_bits},
 1314     {JUST_RIGHT |JUST_BOTTOM, j_rb_b_bits},
 1315     {JUST_LEFT  |JUST_MIDDLE, j_lm_b_bits},
 1316     {JUST_CENTER|JUST_MIDDLE, j_cm_b_bits},
 1317     {JUST_RIGHT |JUST_MIDDLE, j_rm_b_bits},
 1318     {JUST_LEFT  |JUST_TOP   , j_lt_b_bits},
 1319     {JUST_CENTER|JUST_TOP   , j_ct_b_bits},
 1320     {JUST_RIGHT |JUST_TOP   , j_rt_b_bits}
 1321 };
 1322 
 1323 OptionStructure *CreateJustChoice(Widget parent, char *s)
 1324 {
 1325     return (CreateBitmapOptionChoice(parent, s, 4,
 1326         12, JBITMAP_WIDTH, JBITMAP_HEIGHT, just_option_items));
 1327 }
 1328 
 1329 RestrictionStructure *CreateRestrictionChoice(Widget parent, char *s)
 1330 {
 1331     RestrictionStructure *retval;
 1332     Widget rc;
 1333     OptionItem restr_items[7];
 1334 
 1335     restr_items[0].value = RESTRICT_NONE;
 1336     restr_items[0].label = "None";
 1337     restr_items[1].value = RESTRICT_REG0;
 1338     restr_items[1].label = "Region 0";
 1339     restr_items[2].value = RESTRICT_REG1;
 1340     restr_items[2].label = "Region 1";
 1341     restr_items[3].value = RESTRICT_REG2;
 1342     restr_items[3].label = "Region 2";
 1343     restr_items[4].value = RESTRICT_REG3;
 1344     restr_items[4].label = "Region 3";
 1345     restr_items[5].value = RESTRICT_REG4;
 1346     restr_items[5].label = "Region 4";
 1347     restr_items[6].value = RESTRICT_WORLD;
 1348     restr_items[6].label = "Inside graph";
 1349 
 1350     retval = xmalloc(sizeof(RestrictionStructure));
 1351 
 1352     retval->frame = CreateFrame(parent, s);
 1353     rc = XtVaCreateWidget("rc",
 1354         xmRowColumnWidgetClass, retval->frame,
 1355         XmNorientation, XmHORIZONTAL,
 1356         NULL);
 1357 
 1358     retval->r_sel = CreateOptionChoice(rc,
 1359         "Restriction:", 1, 7, restr_items);
 1360     retval->negate = CreateToggleButton(rc, "Negated");
 1361     XtManageChild(rc);
 1362 
 1363     return retval;
 1364 }
 1365 
 1366 
 1367 static OptionItem *graph_select_items = NULL;
 1368 static int ngraph_select_items = 0;
 1369 static ListStructure **graph_selectors = NULL;
 1370 static int ngraph_selectors = 0;
 1371 
 1372 void graph_select_cb(Widget list, XtPointer client_data, XtPointer call_data)
 1373 {
 1374     XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
 1375     ListStructure *plist = (ListStructure *) client_data;
 1376     int gno;
 1377     
 1378     gno = plist->values[cbs->item_position - 1];
 1379     switch_current_graph(gno);
 1380 }
 1381 
 1382 void update_graph_selectors(void)
 1383 {
 1384     int i, new_n = number_of_graphs();
 1385     char buf[64];
 1386     OptionItem *p;
 1387     
 1388     for (i = 0; i < ngraph_select_items; i++) {
 1389         xfree(graph_select_items[i].label);
 1390     }
 1391     p = xrealloc(graph_select_items, new_n*sizeof(OptionItem));
 1392     if (p == NULL && new_n != 0) {
 1393         ngraph_select_items = 0;
 1394         return;
 1395     } else {
 1396         graph_select_items = p;
 1397     }
 1398 
 1399     for (i = 0; i < new_n; i++) {
 1400         graph_select_items[i].value = i;
 1401         sprintf(buf, "(%c) G%d (%d sets)",
 1402             is_graph_hidden(i) ? '-':'+', i, number_of_sets(i));
 1403         graph_select_items[i].label = copy_string(NULL, buf);
 1404     }
 1405     ngraph_select_items = new_n;
 1406     
 1407     for (i = 0; i < ngraph_selectors; i++) {
 1408         UpdateListChoice(graph_selectors[i],
 1409             ngraph_select_items, graph_select_items);
 1410     }
 1411 }
 1412 
 1413 typedef struct {
 1414     Widget popup;
 1415     Widget label_item;
 1416     Widget focus_item;
 1417     Widget hide_item;
 1418     Widget show_item;
 1419     Widget duplicate_item;
 1420     Widget kill_item;
 1421     Widget copy12_item;
 1422     Widget copy21_item;
 1423     Widget move12_item;
 1424     Widget move21_item;
 1425     Widget swap_item;
 1426 } GraphPopupMenu;
 1427 
 1428 typedef enum {
 1429     GraphMenuFocusCB,
 1430     GraphMenuHideCB,
 1431     GraphMenuShowCB,
 1432     GraphMenuDuplicateCB,
 1433     GraphMenuKillCB,
 1434     GraphMenuCopy12CB,
 1435     GraphMenuCopy21CB,
 1436     GraphMenuMove12CB,
 1437     GraphMenuMove21CB,
 1438     GraphMenuSwapCB,
 1439     GraphMenuNewCB
 1440 } GraphMenuCBtype;
 1441 
 1442 void graph_menu_cb(ListStructure *listp, GraphMenuCBtype type)
 1443 {
 1444     int err = FALSE;
 1445     int i, n, *values;
 1446     char buf[32];
 1447 
 1448     n = GetListChoices(listp, &values);
 1449     
 1450     switch (type) {
 1451     case GraphMenuFocusCB:
 1452         if (n == 1) {
 1453             switch_current_graph(values[0]);
 1454         } else {
 1455             err = TRUE;
 1456         }
 1457         break;
 1458     case GraphMenuHideCB:
 1459         if (n > 0) {
 1460             for (i = 0; i < n; i++) {
 1461                 set_graph_hidden(values[i], TRUE);
 1462             }
 1463         } else {
 1464             err = TRUE;
 1465         }
 1466         break;
 1467     case GraphMenuShowCB:
 1468         if (n > 0) {
 1469             for (i = 0; i < n; i++) {
 1470                 set_graph_hidden(values[i], FALSE);
 1471             }
 1472         } else {
 1473             err = TRUE;
 1474         }
 1475         break;
 1476     case GraphMenuDuplicateCB:
 1477         if (n > 0) {
 1478             for (i = 0; i < n; i++) {
 1479                 duplicate_graph(values[i]);
 1480             }
 1481         } else {
 1482             err = TRUE;
 1483         }
 1484         break;
 1485     case GraphMenuKillCB:
 1486         if (n > 0) {
 1487             if (yesno("Kill selected graph(s)?", NULL, NULL, NULL)) {
 1488                 for (i = n - 1; i >= 0; i--) {
 1489                     kill_graph(values[i]);
 1490                 }
 1491             }
 1492         } else {
 1493             err = TRUE;
 1494         }
 1495         break;
 1496     case GraphMenuCopy12CB:
 1497         if (n == 2) {
 1498             sprintf(buf, "Overwrite G%d?", values[1]);
 1499             if (yesno(buf, NULL, NULL, NULL)) {
 1500                 copy_graph(values[0], values[1]);
 1501             }
 1502         } else {
 1503             err = TRUE;
 1504         }
 1505         break;
 1506     case GraphMenuCopy21CB:
 1507         if (n == 2) {
 1508             sprintf(buf, "Overwrite G%d?", values[0]);
 1509             if (yesno(buf, NULL, NULL, NULL)) {
 1510                 copy_graph(values[1], values[0]);
 1511             }
 1512         } else {
 1513             err = TRUE;
 1514         }
 1515         break;
 1516     case GraphMenuMove12CB:
 1517         if (n == 2) {
 1518             sprintf(buf, "Replace G%d?", values[1]);
 1519             if (yesno(buf, NULL, NULL, NULL)) {
 1520                 move_graph(values[0], values[1]);
 1521             }
 1522         } else {
 1523             err = TRUE;
 1524         }
 1525         break;
 1526     case GraphMenuMove21CB:
 1527         if (n == 2) {
 1528             sprintf(buf, "Replace G%d?", values[0]);
 1529             if (yesno(buf, NULL, NULL, NULL)) {
 1530                 move_graph(values[1], values[0]);
 1531             }
 1532         } else {
 1533             err = TRUE;
 1534         }
 1535         break;
 1536     case GraphMenuSwapCB:
 1537         if (n == 2) {
 1538             swap_graph(values[0], values[1]);
 1539         } else {
 1540             err = TRUE;
 1541         }
 1542         break;
 1543     case GraphMenuNewCB:
 1544         set_graph_active(number_of_graphs());
 1545         break;
 1546     default:
 1547         err = TRUE;
 1548         break;
 1549     }
 1550 
 1551     if (n > 0) {
 1552         xfree(values);
 1553     }
 1554 
 1555     if (err == FALSE) {
 1556         update_all();
 1557         xdrawgraph();
 1558     }
 1559 }
 1560 
 1561 void switch_focus_proc(void *data)
 1562 {
 1563     graph_menu_cb((ListStructure *) data, GraphMenuFocusCB);
 1564 }
 1565 
 1566 void hide_graph_proc(void *data)
 1567 {
 1568     graph_menu_cb((ListStructure *) data, GraphMenuHideCB);
 1569 }
 1570 
 1571 void show_graph_proc(void *data)
 1572 {
 1573     graph_menu_cb((ListStructure *) data, GraphMenuShowCB);
 1574 }
 1575 
 1576 void duplicate_graph_proc(void *data)
 1577 {
 1578     graph_menu_cb((ListStructure *) data, GraphMenuDuplicateCB);
 1579 }
 1580 
 1581 void kill_graph_proc(void *data)
 1582 {
 1583     graph_menu_cb((ListStructure *) data, GraphMenuKillCB);
 1584 }
 1585 
 1586 void copy12_graph_proc(void *data)
 1587 {
 1588     graph_menu_cb((ListStructure *) data, GraphMenuCopy12CB);
 1589 }
 1590 
 1591 void copy21_graph_proc(void *data)
 1592 {
 1593     graph_menu_cb((ListStructure *) data, GraphMenuCopy21CB);
 1594 }
 1595 
 1596 void move12_graph_proc(void *data)
 1597 {
 1598     graph_menu_cb((ListStructure *) data, GraphMenuMove12CB);
 1599 }
 1600 
 1601 void move21_graph_proc(void *data)
 1602 {
 1603     graph_menu_cb((ListStructure *) data, GraphMenuMove21CB);
 1604 }
 1605 
 1606 void swap_graph_proc(void *data)
 1607 {
 1608     graph_menu_cb((ListStructure *) data, GraphMenuSwapCB);
 1609 }
 1610 
 1611 void create_new_graph_proc(void *data)
 1612 {
 1613     graph_menu_cb((ListStructure *) data, GraphMenuNewCB);
 1614 }
 1615 
 1616 GraphPopupMenu *CreateGraphPopupEntries(ListStructure *listp)
 1617 {
 1618     GraphPopupMenu *graph_popup_menu;
 1619     Widget popup;
 1620     
 1621     graph_popup_menu = xmalloc(sizeof(GraphPopupMenu));
 1622 
 1623     popup = XmCreatePopupMenu(listp->list, "graphPopupMenu", NULL, 0);
 1624 #if XmVersion >= 2000    
 1625     XtVaSetValues(popup, XmNpopupEnabled, XmPOPUP_DISABLED, NULL);
 1626 #else
 1627     XtVaSetValues(popup, XmNpopupEnabled, False, NULL);
 1628 #endif
 1629     graph_popup_menu->popup = popup;
 1630     
 1631     graph_popup_menu->label_item = CreateMenuLabel(popup, "Selection:");
 1632     CreateMenuSeparator(popup);
 1633     graph_popup_menu->focus_item = CreateMenuButton(popup, "Focus to", 'F',
 1634         switch_focus_proc, (void *) listp);
 1635     CreateMenuSeparator(popup);
 1636     graph_popup_menu->hide_item = CreateMenuButton(popup, "Hide", 'H',
 1637         hide_graph_proc, (void *) listp);
 1638     graph_popup_menu->show_item = CreateMenuButton(popup, "Show", 'S',
 1639         show_graph_proc, (void *) listp);
 1640     graph_popup_menu->duplicate_item = CreateMenuButton(popup,"Duplicate", 'D',
 1641         duplicate_graph_proc, (void *) listp);
 1642     graph_popup_menu->kill_item = CreateMenuButton(popup, "Kill", 'K',
 1643         kill_graph_proc, (void *) listp);
 1644     CreateMenuSeparator(popup);
 1645     graph_popup_menu->copy12_item = CreateMenuButton(popup, "Copy 1 to 2", '\0',
 1646         copy12_graph_proc, (void *) listp);
 1647     graph_popup_menu->copy21_item = CreateMenuButton(popup, "Copy 2 to 1", '\0',
 1648         copy21_graph_proc, (void *) listp);
 1649     graph_popup_menu->move12_item = CreateMenuButton(popup, "Move 1 to 2", '\0',
 1650         move12_graph_proc, (void *) listp);
 1651     graph_popup_menu->move21_item = CreateMenuButton(popup, "Move 2 to 1", '\0',
 1652         move21_graph_proc, (void *) listp);
 1653     graph_popup_menu->swap_item = CreateMenuButton(popup, "Swap", 'w',
 1654         swap_graph_proc, (void *) listp);
 1655     CreateMenuSeparator(popup);
 1656     CreateMenuButton(popup, "Create new", 'C',
 1657         create_new_graph_proc, (void *) listp);
 1658 
 1659     return graph_popup_menu;
 1660 }
 1661 
 1662 void graph_popup(Widget parent, ListStructure *listp, XButtonPressedEvent *event)
 1663 {
 1664     int i, n;
 1665     int *values;
 1666     char buf[64];
 1667     Widget popup;
 1668     GraphPopupMenu* graph_popup_menu;
 1669     
 1670     if (event->button != 3) {
 1671         return;
 1672     }
 1673     
 1674     graph_popup_menu = (GraphPopupMenu*) listp->anydata;
 1675     popup = graph_popup_menu->popup;
 1676     
 1677     n = GetListChoices(listp, &values);
 1678     if (n > 0) {
 1679         sprintf(buf, "G%d", values[0]);
 1680         for (i = 1; i < n; i++) {
 1681             if (strlen(buf) > 30) {
 1682                 strcat(buf, "...");
 1683                 break;
 1684             }
 1685             sprintf(buf, "%s, G%d", buf, values[i]);
 1686         }
 1687     } else {
 1688         strcpy(buf, "None"); 
 1689     }
 1690     
 1691     SetLabel(graph_popup_menu->label_item, buf);
 1692     
 1693     if (n == 0) {
 1694         XtSetSensitive(graph_popup_menu->hide_item, False);
 1695         XtSetSensitive(graph_popup_menu->show_item, False);
 1696         XtSetSensitive(graph_popup_menu->duplicate_item, False);
 1697         XtSetSensitive(graph_popup_menu->kill_item, False);
 1698     } else {
 1699         XtSetSensitive(graph_popup_menu->hide_item, True);
 1700         XtSetSensitive(graph_popup_menu->show_item, True);
 1701         XtSetSensitive(graph_popup_menu->duplicate_item, True);
 1702         XtSetSensitive(graph_popup_menu->kill_item, True);
 1703     }
 1704     if (n == 1) {
 1705         XtSetSensitive(graph_popup_menu->focus_item, True);
 1706     } else {
 1707         XtSetSensitive(graph_popup_menu->focus_item, False);
 1708     }
 1709     if (n == 2) {
 1710         sprintf(buf, "Copy G%d to G%d", values[0], values[1]);
 1711         SetLabel(graph_popup_menu->copy12_item, buf);
 1712         XtManageChild(graph_popup_menu->copy12_item);
 1713         sprintf(buf, "Copy G%d to G%d", values[1], values[0]);
 1714         SetLabel(graph_popup_menu->copy21_item, buf);
 1715         XtManageChild(graph_popup_menu->copy21_item);
 1716         sprintf(buf, "Move G%d to G%d", values[0], values[1]);
 1717         SetLabel(graph_popup_menu->move12_item, buf);
 1718         XtManageChild(graph_popup_menu->move12_item);
 1719         sprintf(buf, "Move G%d to G%d", values[1], values[0]);
 1720         SetLabel(graph_popup_menu->move21_item, buf);
 1721         XtManageChild(graph_popup_menu->move21_item);
 1722         XtSetSensitive(graph_popup_menu->swap_item, True);
 1723     } else {
 1724         XtUnmanageChild(graph_popup_menu->copy12_item);
 1725         XtUnmanageChild(graph_popup_menu->copy21_item);
 1726         XtUnmanageChild(graph_popup_menu->move12_item);
 1727         XtUnmanageChild(graph_popup_menu->move21_item);
 1728         XtSetSensitive(graph_popup_menu->swap_item, False);
 1729     }
 1730     
 1731     if (n > 0) {
 1732         xfree(values);
 1733     }
 1734     XmMenuPosition(popup, event);
 1735     XtManageChild(popup);
 1736 }
 1737 
 1738 static void list_selectall(Widget list)
 1739 {
 1740     int i, n;
 1741     unsigned char selection_type_save;
 1742     
 1743     XtVaGetValues(list,
 1744                   XmNselectionPolicy, &selection_type_save,
 1745                   XmNitemCount, &n,
 1746                   NULL);
 1747     if (selection_type_save == XmSINGLE_SELECT) {
 1748         XBell(disp, 50);
 1749         return;
 1750     }
 1751     
 1752     XtVaSetValues(list, XmNselectionPolicy, XmMULTIPLE_SELECT, NULL);
 1753                              
 1754     XmListDeselectAllItems(list);
 1755     for (i = 1; i <= n; i++) {
 1756         XmListSelectPos(list, i, False);
 1757     }
 1758     
 1759     XtVaSetValues(list, XmNselectionPolicy, selection_type_save, NULL);
 1760 }
 1761 
 1762 void list_selectall_action(Widget w, XEvent *e, String *par, Cardinal *npar)
 1763 {
 1764     list_selectall(w);
 1765 }
 1766 
 1767 static void list_selectall_cb(void *data)
 1768 {
 1769     ListStructure *listp = (ListStructure *) data;
 1770     list_selectall(listp->list);
 1771 }
 1772 
 1773 static void list_unselectall(Widget list)
 1774 {
 1775     XmListDeselectAllItems(list);
 1776 }
 1777 
 1778 void list_unselectall_action(Widget w, XEvent *e, String *par, Cardinal *npar)
 1779 {
 1780     list_unselectall(w);
 1781 }
 1782 
 1783 static void list_unselectall_cb(void *data)
 1784 {
 1785     ListStructure *listp = (ListStructure *) data;
 1786     list_unselectall(listp->list);
 1787 }
 1788 
 1789 static void list_invertselection(Widget list)
 1790 {
 1791     int i, n;
 1792     unsigned char selection_type_save;
 1793     
 1794     XtVaGetValues(list,
 1795         XmNselectionPolicy, &selection_type_save,
 1796         XmNitemCount, &n,
 1797         NULL);
 1798     if (selection_type_save == XmSINGLE_SELECT) {
 1799         XBell(disp, 50);
 1800         return;
 1801     }
 1802     
 1803     XtVaSetValues(list, XmNselectionPolicy, XmMULTIPLE_SELECT, NULL);
 1804     for (i = 0; i < n; i++) {
 1805         XmListSelectPos(list, i, False);
 1806     }
 1807     XtVaSetValues(list, XmNselectionPolicy, selection_type_save, NULL);
 1808 }
 1809 
 1810 static void list_invertselection_cb(void *data)
 1811 {
 1812     ListStructure *listp = (ListStructure *) data;
 1813     list_invertselection(listp->list);
 1814 }
 1815 
 1816 void list_invertselection_action(Widget w, XEvent *e, String *par,
 1817                  Cardinal *npar)
 1818 {
 1819     list_invertselection(w);
 1820 }
 1821 
 1822 void set_graph_selectors(int gno)
 1823 {
 1824     int i;
 1825     
 1826     for (i = 0; i < ngraph_selectors; i++) {
 1827         SelectListChoice(graph_selectors[i], gno);
 1828     }
 1829 }
 1830 
 1831 ListStructure *CreateGraphChoice(Widget parent, char *labelstr, int type)
 1832 {
 1833     ListStructure *retvalp;
 1834     int nvisible;
 1835         
 1836     ngraph_selectors++;
 1837     graph_selectors = xrealloc(graph_selectors, 
 1838                                     ngraph_selectors*sizeof(ListStructure *));
 1839 
 1840     nvisible = (type == LIST_TYPE_SINGLE) ? 2 : 4; 
 1841     retvalp = CreateListChoice(parent, labelstr, type, nvisible,
 1842                                ngraph_select_items, graph_select_items);
 1843     if (retvalp == NULL) {
 1844         return NULL;
 1845     }
 1846     AddHelpCB(retvalp->rc, "doc/UsersGuide.html#graph-selector");
 1847     graph_selectors[ngraph_selectors - 1] = retvalp;
 1848     
 1849     XtAddCallback(retvalp->list, XmNdefaultActionCallback,
 1850                                graph_select_cb, retvalp);
 1851     retvalp->anydata = CreateGraphPopupEntries(retvalp);
 1852     
 1853     XtAddEventHandler(retvalp->list, ButtonPressMask, False, 
 1854                             (XtEventHandler) graph_popup, retvalp);
 1855 
 1856     if (ngraph_select_items == 0) {
 1857         update_graph_selectors();
 1858     } else {
 1859         UpdateListChoice(retvalp, ngraph_select_items, graph_select_items);
 1860     }
 1861     
 1862     SelectListChoice(retvalp, get_cg());
 1863     
 1864     return retvalp;
 1865 }
 1866 
 1867 /* Set selectors */
 1868 static ListStructure **set_selectors = NULL;
 1869 static int nset_selectors = 0;
 1870 
 1871 void UpdateSetChoice(ListStructure *listp, int gno)
 1872 {
 1873     int i, j, n = number_of_sets(gno);
 1874     char buf[64];
 1875     OptionItem *set_select_items;
 1876     SetChoiceData *sdata;
 1877     
 1878     sdata = (SetChoiceData *) listp->anydata;
 1879     sdata->gno = gno;
 1880     
 1881     if (n <= 0) {
 1882         UpdateListChoice(listp, 0, NULL);
 1883         return;
 1884     }
 1885     
 1886     set_select_items = xmalloc(n*sizeof(OptionItem));
 1887     if (set_select_items == NULL) {
 1888         return;
 1889     }
 1890     
 1891     for (i = 0, j = 0; i < n; i++) {
 1892         if ((sdata->show_nodata == TRUE || is_set_active(gno, i) == TRUE) &&
 1893             (sdata->show_hidden == TRUE || is_set_hidden(gno, i) != TRUE )) {
 1894             set_select_items[j].value = i;
 1895             sprintf(buf, "(%c) G%d.S%d[%d][%d]",
 1896                 is_set_hidden(gno, i) ? '-':'+',
 1897                 gno, i, dataset_cols(gno, i), getsetlength(gno, i));
 1898             set_select_items[j].label = copy_string(NULL, buf);
 1899             if (sdata->view_comments == TRUE) {
 1900                 set_select_items[j].label =
 1901                     concat_strings(set_select_items[j].label, " \"");
 1902                 set_select_items[j].label =
 1903                     concat_strings(set_select_items[j].label,
 1904                     getcomment(gno, i));
 1905                 set_select_items[j].label =
 1906                     concat_strings(set_select_items[j].label, "\"");
 1907             }
 1908             j++;
 1909         }
 1910     }
 1911     UpdateListChoice(listp, j, set_select_items);
 1912     
 1913     xfree(set_select_items);
 1914 }
 1915 
 1916 void update_set_selectors(int gno)
 1917 {
 1918     int i, cg;
 1919     SetChoiceData *sdata;
 1920     
 1921     cg = get_cg();
 1922     update_graph_selectors();
 1923     for (i = 0; i < nset_selectors; i++) {
 1924         sdata = (SetChoiceData *) set_selectors[i]->anydata;
 1925         if (sdata->standalone == TRUE && (gno == cg || gno == ALL_GRAPHS)) {
 1926             UpdateSetChoice(set_selectors[i], cg);
 1927         } else if (sdata->standalone == FALSE && sdata->gno == gno) {
 1928             UpdateSetChoice(set_selectors[i], gno);
 1929         }
 1930     }
 1931 }
 1932 
 1933 void set_menu_cb(ListStructure *listp, SetMenuCBtype type)
 1934 {
 1935     SetChoiceData *sdata;
 1936     int err = FALSE;
 1937     int gno;
 1938     int i, n, setno, *values;
 1939     char buf[32];
 1940 
 1941     n = GetListChoices(listp, &values);
 1942     sdata = (SetChoiceData *) listp->anydata;
 1943     gno = sdata->gno;
 1944     
 1945     switch (type) {
 1946     case SetMenuHideCB:
 1947         if (n > 0) {
 1948             for (i = 0; i < n; i++) {
 1949                 set_set_hidden(gno, values[i], TRUE);
 1950             }
 1951         } else {
 1952             err = TRUE;
 1953         }
 1954         break;
 1955     case SetMenuShowCB:
 1956         if (n > 0) {
 1957             for (i = 0; i < n; i++) {
 1958                 set_set_hidden(gno, values[i], FALSE);
 1959             }
 1960         } else {
 1961             err = TRUE;
 1962         }
 1963         break;
 1964     case SetMenuBringfCB:
 1965         if (n == 1) {
 1966             pushset(gno, values[0], PUSH_SET_TOFRONT);
 1967         } else {
 1968             err = TRUE;
 1969         }
 1970         break;
 1971     case SetMenuSendbCB:
 1972         if (n == 1) {
 1973             pushset(gno, values[0], PUSH_SET_TOBACK);
 1974         } else {
 1975             err = TRUE;
 1976         }
 1977         break;
 1978     case SetMenuDuplicateCB:
 1979         if (n > 0) {
 1980             for (i = 0; i < n; i++) {
 1981                 setno = nextset(gno);
 1982                 do_copyset(gno, values[i], gno, setno);
 1983             }
 1984         } else {
 1985             err = TRUE;
 1986         }
 1987         break;
 1988     case SetMenuKillCB:
 1989         if (n > 0) {
 1990             if (yesno("Kill selected set(s)?", NULL, NULL, NULL)) {
 1991                 for (i = 0; i < n; i++) {
 1992                     killset(gno, values[i]);
 1993                 }
 1994             }
 1995         } else {
 1996             err = TRUE;
 1997         }
 1998         break;
 1999     case SetMenuKillDCB:
 2000         if (n > 0) {
 2001             if (yesno("Kill data in selected set(s)?", NULL, NULL, NULL)) {
 2002                 for (i = 0; i < n; i++) {
 2003                     killsetdata(gno, values[i]);
 2004                     setcomment(gno, values[i], "");
 2005                 }
 2006             }
 2007         } else {
 2008             err = TRUE;
 2009         }
 2010         break;
 2011     case SetMenuCopy12CB:
 2012         if (n == 2) {
 2013             sprintf(buf, "Overwrite S%d?", values[1]);
 2014             if (yesno(buf, NULL, NULL, NULL)) {
 2015                 do_copyset(gno, values[0], gno, values[1]);
 2016             }
 2017         } else {
 2018             err = TRUE;
 2019         }
 2020         break;
 2021     case SetMenuCopy21CB:
 2022         if (n == 2) {
 2023             sprintf(buf, "Overwrite S%d?", values[0]);
 2024             if (yesno(buf, NULL, NULL, NULL)) {
 2025                 do_copyset(gno, values[1], gno, values[0]);
 2026             }
 2027         } else {
 2028             err = TRUE;
 2029         }
 2030         break;
 2031     case SetMenuMove12CB:
 2032         if (n == 2) {
 2033             sprintf(buf, "Replace S%d?", values[1]);
 2034             if (yesno(buf, NULL, NULL, NULL)) {
 2035                 moveset(gno, values[0], gno, values[1]);
 2036             }
 2037         } else {
 2038             err = TRUE;
 2039         }
 2040         break;
 2041     case SetMenuMove21CB:
 2042         if (n == 2) {
 2043             sprintf(buf, "Replace S%d?", values[0]);
 2044             if (yesno(buf, NULL, NULL, NULL)) {
 2045                 moveset(gno, values[1], gno, values[0]);
 2046             }
 2047         } else {
 2048             err = TRUE;
 2049         }
 2050         break;
 2051     case SetMenuSwapCB:
 2052         if (n == 2) {
 2053             swapset(gno, values[0], gno, values[1]);
 2054         } else {
 2055             err = TRUE;
 2056         }
 2057         break;
 2058     case SetMenuNewFCB:
 2059             create_leval_frame((void *) gno);
 2060         break;
 2061     case SetMenuNewSCB:
 2062             if ((setno = nextset(gno)) != -1) {
 2063                 setcomment(gno, setno, "Editor");
 2064                 set_set_hidden(gno, setno, FALSE);
 2065                 create_ss_frame(gno, setno);
 2066             } else {
 2067                 err = TRUE;
 2068             }
 2069         break;
 2070     case SetMenuNewECB:
 2071             if ((setno = nextset(gno)) != -1) {
 2072                 setcomment(gno, setno, "Editor");
 2073                 set_set_hidden(gno, setno, FALSE);
 2074                 do_ext_editor(gno, setno);
 2075             } else {
 2076                 err = TRUE;
 2077             }
 2078         break;
 2079     case SetMenuNewBCB:
 2080             create_eblock_frame(gno);
 2081         break;
 2082     case SetMenuEditSCB:
 2083         if (n == 1) {
 2084             create_ss_frame(gno, values[0]);
 2085         } else {
 2086             err = TRUE;
 2087         }
 2088         break;
 2089     case SetMenuEditECB:
 2090         if (n == 1) {
 2091             do_ext_editor(gno, values[0]);
 2092         } else {
 2093             err = TRUE;
 2094         }
 2095         break;
 2096     case SetMenuPackCB:
 2097         packsets(gno);
 2098         break;
 2099     default:
 2100         err = TRUE;
 2101         break;
 2102     }
 2103 
 2104     if (n > 0) {
 2105         xfree(values);
 2106     }
 2107 
 2108     if (err == FALSE) {
 2109         update_all();
 2110         xdrawgraph();
 2111     }
 2112 }
 2113 
 2114 
 2115 void hide_set_proc(void *data)
 2116 {
 2117     set_menu_cb((ListStructure *) data, SetMenuHideCB);
 2118 }
 2119 
 2120 void show_set_proc(void *data)
 2121 {
 2122     set_menu_cb((ListStructure *) data, SetMenuShowCB);
 2123 }
 2124 
 2125 void bringf_set_proc(void *data)
 2126 {
 2127     set_menu_cb((ListStructure *) data, SetMenuBringfCB);
 2128 }
 2129 
 2130 void sendb_set_proc(void *data)
 2131 {
 2132     set_menu_cb((ListStructure *) data, SetMenuSendbCB);
 2133 }
 2134 
 2135 void duplicate_set_proc(void *data)
 2136 {
 2137     set_menu_cb((ListStructure *) data, SetMenuDuplicateCB);
 2138 }
 2139 
 2140 void kill_set_proc(void *data)
 2141 {
 2142     set_menu_cb((ListStructure *) data, SetMenuKillCB);
 2143 }
 2144 
 2145 void killd_set_proc(void *data)
 2146 {
 2147     set_menu_cb((ListStructure *) data, SetMenuKillDCB);
 2148 }
 2149 
 2150 void copy12_set_proc(void *data)
 2151 {
 2152     set_menu_cb((ListStructure *) data, SetMenuCopy12CB);
 2153 }
 2154 
 2155 void copy21_set_proc(void *data)
 2156 {
 2157     set_menu_cb((ListStructure *) data, SetMenuCopy21CB);
 2158 }
 2159 
 2160 void move12_set_proc(void *data)
 2161 {
 2162     set_menu_cb((ListStructure *) data, SetMenuMove12CB);
 2163 }
 2164 
 2165 void move21_set_proc(void *data)
 2166 {
 2167     set_menu_cb((ListStructure *) data, SetMenuMove21CB);
 2168 }
 2169 
 2170 void swap_set_proc(void *data)
 2171 {
 2172     set_menu_cb((ListStructure *) data, SetMenuSwapCB);
 2173 }
 2174 
 2175 void newF_set_proc(void *data)
 2176 {
 2177     set_menu_cb((ListStructure *) data, SetMenuNewFCB);
 2178 }
 2179 
 2180 void newS_set_proc(void *data)
 2181 {
 2182     set_menu_cb((ListStructure *) data, SetMenuNewSCB);
 2183 }
 2184 
 2185 void newE_set_proc(void *data)
 2186 {
 2187     set_menu_cb((ListStructure *) data, SetMenuNewECB);
 2188 }
 2189 
 2190 void newB_set_proc(void *data)
 2191 {
 2192     set_menu_cb((ListStructure *) data, SetMenuNewBCB);
 2193 }
 2194 
 2195 void editS_set_proc(void *data)
 2196 {
 2197     set_menu_cb((ListStructure *) data, SetMenuEditSCB);
 2198 }
 2199 
 2200 void editE_set_proc(void *data)
 2201 {
 2202     set_menu_cb((ListStructure *) data, SetMenuEditECB);
 2203 }
 2204 
 2205 void pack_set_proc(void *data)
 2206 {
 2207     set_menu_cb((ListStructure *) data, SetMenuPackCB);
 2208 }
 2209 
 2210 void shownd_set_proc(int onoff, void *data)
 2211 {
 2212     ListStructure *listp = (ListStructure *) data;
 2213     SetChoiceData *sdata = (SetChoiceData *) listp->anydata;
 2214     
 2215     sdata->show_nodata = onoff;
 2216     UpdateSetChoice(listp, sdata->gno);
 2217 }
 2218 
 2219 void showh_set_proc(int onoff, void *data)
 2220 {
 2221     ListStructure *listp = (ListStructure *) data;
 2222     SetChoiceData *sdata = (SetChoiceData *) listp->anydata;
 2223     
 2224     sdata->show_hidden = onoff;
 2225     UpdateSetChoice(listp, sdata->gno);
 2226 }
 2227 
 2228 void view_comments_set_proc(int onoff, void *data)
 2229 {
 2230     ListStructure *listp = (ListStructure *) data;
 2231     SetChoiceData *sdata = (SetChoiceData *) listp->anydata;
 2232     
 2233     sdata->view_comments = onoff;
 2234     UpdateSetChoice(listp, sdata->gno);
 2235 }
 2236 
 2237 void update_set_proc(void *data)
 2238 {
 2239     ListStructure *listp = (ListStructure *) data;
 2240     SetChoiceData *sdata = (SetChoiceData *) listp->anydata;
 2241     
 2242     UpdateSetChoice(listp, sdata->gno);
 2243 }
 2244 
 2245 SetPopupMenu *CreateSetPopupEntries(ListStructure *listp)
 2246 {
 2247     SetPopupMenu *set_popup_menu;
 2248     Widget popup, submenupane;
 2249     
 2250     set_popup_menu = xmalloc(sizeof(SetPopupMenu));
 2251     popup = XmCreatePopupMenu(listp->list, "setPopupMenu", NULL, 0);
 2252 #if XmVersion >= 2000    
 2253     XtVaSetValues(popup, XmNpopupEnabled, XmPOPUP_DISABLED, NULL);
 2254 #else
 2255     XtVaSetValues(popup, XmNpopupEnabled, False, NULL);
 2256 #endif
 2257     set_popup_menu->popup = popup;
 2258     
 2259     set_popup_menu->label_item = CreateMenuLabel(popup, "Selection:");
 2260 
 2261     CreateMenuSeparator(popup);
 2262 
 2263     set_popup_menu->hide_item = CreateMenuButton(popup, "Hide", '\0',
 2264         hide_set_proc, (void *) listp);
 2265     set_popup_menu->show_item = CreateMenuButton(popup, "Show", '\0',
 2266         show_set_proc, (void *) listp);
 2267     set_popup_menu->bringf_item = CreateMenuButton(popup, "Bring to front", '\0',
 2268         bringf_set_proc, (void *) listp);
 2269     set_popup_menu->sendb_item = CreateMenuButton(popup, "Send to back", '\0',
 2270         sendb_set_proc, (void *) listp);
 2271     CreateMenuSeparator(popup);
 2272     set_popup_menu->duplicate_item = CreateMenuButton(popup, "Duplicate", '\0',
 2273         duplicate_set_proc, (void *) listp);
 2274     set_popup_menu->kill_item = CreateMenuButton(popup, "Kill", '\0',
 2275         kill_set_proc, (void *) listp);
 2276     set_popup_menu->killd_item = CreateMenuButton(popup, "Kill data", '\0',
 2277         killd_set_proc, (void *) listp);
 2278     CreateMenuSeparator(popup);
 2279     set_popup_menu->copy12_item = CreateMenuButton(popup, "Copy 1 to 2", '\0',
 2280         copy12_set_proc, (void *) listp);
 2281     set_popup_menu->copy21_item = CreateMenuButton(popup, "Copy 2 to 1", '\0',
 2282         copy21_set_proc, (void *) listp);
 2283     set_popup_menu->move12_item = CreateMenuButton(popup, "Move 1 to 2", '\0',
 2284         move12_set_proc, (void *) listp);
 2285     set_popup_menu->move21_item = CreateMenuButton(popup, "Move 2 to 1", '\0',
 2286         move21_set_proc, (void *) listp);
 2287     set_popup_menu->swap_item = CreateMenuButton(popup, "Swap", '\0',
 2288         swap_set_proc, (void *) listp);
 2289     CreateMenuSeparator(popup);
 2290     set_popup_menu->edit_item = CreateMenu(popup, "Edit", 'E', FALSE);
 2291     CreateMenuButton(set_popup_menu->edit_item, "In spreadsheet", '\0',
 2292         editS_set_proc, (void *) listp);
 2293     CreateMenuButton(set_popup_menu->edit_item, "In text editor", '\0',
 2294         editE_set_proc, (void *) listp);
 2295     submenupane = CreateMenu(popup, "Create new", '\0', FALSE);
 2296     CreateMenuButton(submenupane, "By formula", '\0',
 2297         newF_set_proc, (void *) listp);
 2298     CreateMenuButton(submenupane, "In spreadsheet", '\0',
 2299         newS_set_proc, (void *) listp);
 2300     CreateMenuButton(submenupane, "In text editor", '\0',
 2301         newE_set_proc, (void *) listp);
 2302     CreateMenuButton(submenupane, "From block data", '\0',
 2303         newB_set_proc, (void *) listp);
 2304 
 2305     CreateMenuSeparator(popup);
 2306 
 2307     CreateMenuButton(popup, "Pack all sets", '\0',
 2308         pack_set_proc, (void *) listp);
 2309 
 2310     CreateMenuSeparator(popup);
 2311 
 2312     submenupane = CreateMenu(popup, "Selector operations", 'o', FALSE);
 2313     CreateMenuToggle(submenupane,
 2314         "View set comments", '\0', view_comments_set_proc, (void *) listp);
 2315     CreateMenuSeparator(submenupane);
 2316     set_popup_menu->shownd_item = CreateMenuToggle(submenupane,
 2317         "Show data-less", '\0', shownd_set_proc, (void *) listp);
 2318     set_popup_menu->showh_item = CreateMenuToggle(submenupane,
 2319         "Show hidden", '\0', showh_set_proc, (void *) listp);
 2320     CreateMenuSeparator(submenupane);
 2321     CreateMenuButton(submenupane, "Select all", '\0',
 2322         list_selectall_cb, (void *) listp);
 2323     CreateMenuButton(submenupane, "Unselect all", '\0',
 2324         list_unselectall_cb, (void *) listp);
 2325     CreateMenuButton(submenupane, "Invert selection", '\0',
 2326         list_invertselection_cb, (void *) listp);
 2327     CreateMenuSeparator(submenupane);
 2328     CreateMenuButton(submenupane, "Update", '\0',
 2329         update_set_proc, (void *) listp);
 2330 
 2331     return set_popup_menu;
 2332 }
 2333 
 2334 void set_popup(Widget parent, ListStructure *listp, XButtonPressedEvent *event)
 2335 {
 2336     SetChoiceData *sdata;
 2337     int i, n;
 2338     int *values;
 2339     char buf[64];
 2340     Widget popup;
 2341     SetPopupMenu* set_popup_menu;
 2342     
 2343     if (event->button != 3) {
 2344         return;
 2345     }
 2346     
 2347     sdata = (SetChoiceData *) listp->anydata;
 2348     set_popup_menu = sdata->menu;
 2349     popup = set_popup_menu->popup;
 2350     
 2351     n = GetListChoices(listp, &values);
 2352     if (n > 0) {
 2353         sprintf(buf, "S%d", values[0]);
 2354         for (i = 1; i < n; i++) {
 2355             if (strlen(buf) > 30) {
 2356                 strcat(buf, "...");
 2357                 break;
 2358             }
 2359             sprintf(buf, "%s, S%d", buf, values[i]);
 2360         }
 2361     } else {
 2362         strcpy(buf, "None"); 
 2363     }
 2364     
 2365     SetLabel(set_popup_menu->label_item, buf);
 2366     
 2367     SetToggleButtonState(set_popup_menu->shownd_item, sdata->show_nodata);
 2368     SetToggleButtonState(set_popup_menu->showh_item, sdata->show_hidden);
 2369     
 2370     if (n == 0) {
 2371         XtSetSensitive(set_popup_menu->hide_item, False);
 2372         XtSetSensitive(set_popup_menu->show_item, False);
 2373         XtSetSensitive(set_popup_menu->duplicate_item, False);
 2374         XtSetSensitive(set_popup_menu->kill_item, False);
 2375         XtSetSensitive(set_popup_menu->killd_item, False);
 2376     } else {
 2377         XtSetSensitive(set_popup_menu->hide_item, True);
 2378         XtSetSensitive(set_popup_menu->show_item, True);
 2379         XtSetSensitive(set_popup_menu->duplicate_item, True);
 2380         XtSetSensitive(set_popup_menu->kill_item, True);
 2381         XtSetSensitive(set_popup_menu->killd_item, True);
 2382     }
 2383     if (n == 1) {
 2384         XtSetSensitive(set_popup_menu->bringf_item, True);
 2385         XtSetSensitive(set_popup_menu->sendb_item, True);
 2386         XtSetSensitive(set_popup_menu->edit_item, True);
 2387     } else {
 2388         XtSetSensitive(set_popup_menu->bringf_item, False);
 2389         XtSetSensitive(set_popup_menu->sendb_item, False);
 2390         XtSetSensitive(set_popup_menu->edit_item, False);
 2391     }
 2392     if (n == 2) {
 2393         sprintf(buf, "Copy S%d to S%d", values[0], values[1]);
 2394         SetLabel(set_popup_menu->copy12_item, buf);
 2395         XtManageChild(set_popup_menu->copy12_item);
 2396         sprintf(buf, "Copy S%d to S%d", values[1], values[0]);
 2397         SetLabel(set_popup_menu->copy21_item, buf);
 2398         XtManageChild(set_popup_menu->copy21_item);
 2399         sprintf(buf, "Move S%d to S%d", values[0], values[1]);
 2400         SetLabel(set_popup_menu->move12_item, buf);
 2401         XtManageChild(set_popup_menu->move12_item);
 2402         sprintf(buf, "Move S%d to S%d", values[1], values[0]);
 2403         SetLabel(set_popup_menu->move21_item, buf);
 2404         XtManageChild(set_popup_menu->move21_item);
 2405         XtSetSensitive(set_popup_menu->swap_item, True);
 2406     } else {
 2407         XtUnmanageChild(set_popup_menu->copy12_item);
 2408         XtUnmanageChild(set_popup_menu->copy21_item);
 2409         XtUnmanageChild(set_popup_menu->move12_item);
 2410         XtUnmanageChild(set_popup_menu->move21_item);
 2411         XtSetSensitive(set_popup_menu->swap_item, False);
 2412     }
 2413     
 2414     if (n > 0) {
 2415         xfree(values);
 2416     }
 2417     XmMenuPosition(popup, event);
 2418     XtManageChild(popup);
 2419 }
 2420 
 2421 static void ss_edit_cb(Widget list, XtPointer client_data, XtPointer call_data)
 2422 {
 2423     XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
 2424     ListStructure *plist = (ListStructure *) client_data;
 2425     SetChoiceData *sdata = (SetChoiceData *) plist->anydata;
 2426     int gno, setno;
 2427     
 2428     gno = sdata->gno;
 2429     setno = plist->values[cbs->item_position - 1];
 2430     create_ss_frame(gno, setno);
 2431 }
 2432 
 2433 
 2434 ListStructure *CreateSetChoice(Widget parent, char *labelstr, 
 2435                                         int type, int standalone)
 2436 {
 2437     ListStructure *retvalp;
 2438     SetChoiceData *sdata;
 2439     int nvisible;
 2440 
 2441     nvisible = (type == LIST_TYPE_SINGLE) ? 4 : 8; 
 2442     retvalp = CreateListChoice(parent, labelstr, type, nvisible, 0, NULL);
 2443     if (retvalp == NULL) {
 2444         return NULL;
 2445     }
 2446     AddHelpCB(retvalp->rc, "doc/UsersGuide.html#set-selector");
 2447 
 2448     sdata = xmalloc(sizeof(SetChoiceData));
 2449     if (sdata == NULL) {
 2450         XCFREE(retvalp);
 2451         return NULL;
 2452     }
 2453     
 2454     sdata->standalone = standalone;
 2455     sdata->view_comments = FALSE;
 2456     sdata->show_hidden = TRUE;
 2457     sdata->show_nodata = FALSE;
 2458     sdata->menu = CreateSetPopupEntries(retvalp);
 2459     XtAddEventHandler(retvalp->list, ButtonPressMask, False, 
 2460                             (XtEventHandler) set_popup, retvalp);
 2461     
 2462     XtAddCallback(retvalp->list, XmNdefaultActionCallback, ss_edit_cb, retvalp);
 2463     
 2464     retvalp->anydata = sdata;
 2465     
 2466     if (standalone == TRUE) {
 2467         UpdateSetChoice(retvalp, get_cg());
 2468     }
 2469 
 2470     nset_selectors++;
 2471     set_selectors = xrealloc(set_selectors, 
 2472                                 nset_selectors*sizeof(ListStructure *));
 2473     set_selectors[nset_selectors - 1] = retvalp;
 2474     
 2475     return retvalp;
 2476 }
 2477 
 2478 static void update_sets_cb(int n, int *values, void *data)
 2479 {
 2480     int gno;
 2481     ListStructure *set_listp = (ListStructure *) data;
 2482     
 2483     if (n == 1) {
 2484         gno = values[0];
 2485     } else {
 2486         gno = -1;
 2487     }
 2488     UpdateSetChoice(set_listp, gno);
 2489 }
 2490 
 2491 GraphSetStructure *CreateGraphSetSelector(Widget parent, char *s, int sel_type)
 2492 {
 2493     GraphSetStructure *retval;
 2494     Widget rc;
 2495 
 2496     retval = xmalloc(sizeof(GraphSetStructure));
 2497     retval->frame = CreateFrame(parent, s);
 2498     rc = XtVaCreateWidget("rc", xmRowColumnWidgetClass, retval->frame, NULL);
 2499     retval->graph_sel = CreateGraphChoice(rc, "Graph:", LIST_TYPE_SINGLE);
 2500     retval->set_sel = CreateSetChoice(rc, "Set:", sel_type, FALSE);
 2501     AddListChoiceCB(retval->graph_sel,
 2502         update_sets_cb, (void *) retval->set_sel);
 2503     UpdateSetChoice(retval->set_sel, get_cg());
 2504     XtManageChild(rc);
 2505 
 2506     return retval;
 2507 }
 2508 
 2509 SrcDestStructure *CreateSrcDestSelector(Widget parent, int sel_type)
 2510 {
 2511     SrcDestStructure *retval;
 2512 
 2513     retval = xmalloc(sizeof(SrcDestStructure));
 2514 
 2515     retval->form = XtVaCreateWidget("form",
 2516         xmFormWidgetClass, parent,
 2517         XmNfractionBase, 2,
 2518         NULL);
 2519     retval->src  = CreateGraphSetSelector(retval->form, "Source", sel_type);
 2520     retval->dest = CreateGraphSetSelector(retval->form, "Destination", sel_type);
 2521     XtVaSetValues(retval->src->frame,
 2522         XmNtopAttachment, XmATTACH_FORM,
 2523         XmNbottomAttachment, XmATTACH_FORM,
 2524         XmNleftAttachment, XmATTACH_FORM,
 2525         XmNrightAttachment, XmATTACH_POSITION,
 2526         XmNrightPosition, 1,
 2527         NULL);
 2528 
 2529     XtVaSetValues(retval->dest->frame,
 2530         XmNtopAttachment, XmATTACH_FORM,
 2531         XmNbottomAttachment, XmATTACH_FORM,
 2532         XmNleftAttachment, XmATTACH_POSITION,
 2533         XmNleftPosition, 1,
 2534         XmNrightAttachment, XmATTACH_FORM,
 2535         NULL);
 2536 
 2537     XtManageChild(retval->form);
 2538 
 2539     return retval;
 2540 }
 2541 
 2542 
 2543 void paint_color_selector(OptionStructure *optp)
 2544 {
 2545     int i, color;
 2546     long bg, fg;
 2547     
 2548     for (i = 0; i < ncolor_option_items; i++) {
 2549         color = color_option_items[i].value;
 2550         bg = xvlibcolors[color];
 2551     if ((get_colorintensity(color) < 0.5 && is_video_reversed() == FALSE) ||
 2552             (get_colorintensity(color) > 0.5 && is_video_reversed() == TRUE )) {
 2553         fg = xvlibcolors[0];
 2554     } else {
 2555         fg = xvlibcolors[1];
 2556     }
 2557     XtVaSetValues(optp->options[i].widget, 
 2558             XmNbackground, bg,
 2559             XmNforeground, fg,
 2560             NULL);
 2561     }
 2562 }
 2563 
 2564 void update_color_selectors(void)
 2565 {
 2566     int i, j;
 2567     CMap_entry *pcmap;
 2568     
 2569     for (i = 0, j = 0; i < number_of_colors(); i++) {
 2570         pcmap = get_cmap_entry(i);
 2571         if (pcmap != NULL && pcmap->ctype == COLOR_MAIN) {
 2572             j++;
 2573         }
 2574     }
 2575     ncolor_option_items = j;
 2576 
 2577     color_option_items = xrealloc(color_option_items,
 2578                                     ncolor_option_items*sizeof(OptionItem));
 2579     for (i = 0, j = 0; i < number_of_colors(); i++) {
 2580         pcmap = get_cmap_entry(i);
 2581         if (pcmap != NULL && pcmap->ctype == COLOR_MAIN) {
 2582             color_option_items[j].value = i;
 2583             color_option_items[j].label = get_colorname(i);
 2584             j++;
 2585         }
 2586     }
 2587     
 2588     for (i = 0; i < ncolor_selectors; i++) {
 2589         UpdateOptionChoice(color_selectors[i], 
 2590                             ncolor_option_items, color_option_items);
 2591         paint_color_selector(color_selectors[i]);
 2592     }
 2593     
 2594 }
 2595 
 2596 OptionStructure *CreateColorChoice(Widget parent, char *s)
 2597 {
 2598     OptionStructure *retvalp = NULL;
 2599 
 2600     ncolor_selectors++;
 2601     color_selectors = xrealloc(color_selectors, 
 2602                                     ncolor_selectors*sizeof(OptionStructure *));
 2603     if (color_selectors == NULL) {
 2604         errmsg("Malloc failed in CreateColorChoice()");
 2605         return retvalp;
 2606     }
 2607     
 2608     retvalp = CreateOptionChoice(parent, s, 4, 
 2609                                 ncolor_option_items, color_option_items);
 2610 
 2611     color_selectors[ncolor_selectors - 1] = retvalp;
 2612     
 2613     paint_color_selector(retvalp);
 2614     
 2615     return retvalp;
 2616 }
 2617 
 2618 SpinStructure *CreateLineWidthChoice(Widget parent, char *s)
 2619 {
 2620     return CreateSpinChoice(parent, s, 3, SPIN_TYPE_FLOAT, 0.0, MAX_LINEWIDTH, 0.5);
 2621 }
 2622 
 2623 
 2624 
 2625 Widget *CreatePanelChoice(Widget parent, char *labelstr, int nchoices,...)
 2626 {
 2627     va_list var;
 2628     int i = 0;
 2629     XmString str;
 2630     char *s;
 2631     Widget *retval;
 2632 
 2633     nchoices--;
 2634 
 2635     retval = (Widget *) XtMalloc((nchoices + 2) * sizeof(Widget));
 2636 
 2637     retval[1] = XmCreatePulldownMenu(parent, "pulldown", NULL, 0);
 2638     
 2639     va_start(var, nchoices);
 2640     i = 0;
 2641     while ((s = va_arg(var, char *)) != NULL) {
 2642     retval[i + 2] = XmCreatePushButton(retval[1], s, NULL, 0);
 2643     i++;
 2644     }
 2645     if (i != nchoices) {
 2646     errmsg("Incorrect number of selections in CreatePanelChoice()");
 2647     }
 2648     va_end(var);
 2649 
 2650     XtManageChildren(retval + 2, nchoices);
 2651 
 2652     retval[0] = XmCreateOptionMenu(parent, "optionmenu", NULL, 0);
 2653     str = XmStringCreateLocalized(labelstr);
 2654     XtVaSetValues(retval[0],
 2655           XmNlabelString, str,
 2656           XmNsubMenuId, retval[1],
 2657           NULL);
 2658     XmStringFree(str);
 2659     XtManageChild(retval[0]);
 2660 
 2661     return retval;
 2662 }
 2663 
 2664 
 2665 void SetChoice(Widget * w, int value)
 2666 {
 2667     Arg a;
 2668     Cardinal nchoices;
 2669 
 2670     if (w == (Widget *) NULL) {
 2671     errwin("Internal error, SetChoice: Attempt to set NULL Widget");
 2672     return;
 2673     }
 2674     
 2675     XtSetArg(a, XmNnumChildren, &nchoices);
 2676     XtGetValues(w[1], &a, 1);
 2677     
 2678     if (value >= nchoices) {
 2679     errwin("Value not found in SetChoice()");
 2680     return;
 2681     }
 2682     XtSetArg(a, XmNmenuHistory, w[value + 2]);
 2683     XtSetValues(w[0], &a, 1);
 2684 }
 2685 
 2686 int GetChoice(Widget * w)
 2687 {
 2688     Arg a;
 2689     Widget warg;
 2690     int i;
 2691 
 2692     if (w == NULL) {
 2693     errwin("Internal error, GetChoice called with NULL argument");
 2694     return 0;
 2695     }
 2696     XtSetArg(a, XmNmenuHistory, &warg);
 2697     XtGetValues(w[0], &a, 1);
 2698     i = 0;
 2699     while (w[i + 2] != warg) {
 2700     if (w[i + 2] == NULL) {
 2701         errwin("Internal error, GetChoice: Found NULL in Widget list");
 2702         return 0;
 2703     }
 2704     i++;
 2705     }
 2706     return i;
 2707 }
 2708 
 2709 static OptionItem fmt_option_items[32] =
 2710 {
 2711     {FORMAT_DECIMAL,        "Decimal"             },
 2712     {FORMAT_EXPONENTIAL,    "Exponential"         },
 2713     {FORMAT_GENERAL,        "General"             },
 2714     {FORMAT_POWER,          "Power"               },
 2715     {FORMAT_SCIENTIFIC,     "Scientific"          },
 2716     {FORMAT_ENGINEERING,    "Engineering"         },
 2717     {FORMAT_COMPUTING,      "Computing (K,M,G,...)"},
 2718     {FORMAT_DDMMYY,         "DD-MM-YY"            },
 2719     {FORMAT_MMDDYY,         "MM-DD-YY"            },
 2720     {FORMAT_YYMMDD,         "YY-MM-DD"            },
 2721     {FORMAT_MMYY,           "MM-YY"               },
 2722     {FORMAT_MMDD,           "MM-DD"               },
 2723     {FORMAT_MONTHDAY,       "Month-DD"            },
 2724     {FORMAT_DAYMONTH,       "DD-Month"            },
 2725     {FORMAT_MONTHS,         "Month (abrev.)"      },
 2726     {FORMAT_MONTHSY,        "Month (abrev.)-YY"   },
 2727     {FORMAT_MONTHL,         "Month"               },
 2728     {FORMAT_DAYOFWEEKS,     "Day of week (abrev.)"},
 2729     {FORMAT_DAYOFWEEKL,     "Day of week"         },
 2730     {FORMAT_DAYOFYEAR,      "Day of year"         },
 2731     {FORMAT_HMS,            "HH:MM:SS"            },
 2732     {FORMAT_MMDDHMS,        "MM-DD HH:MM:SS"      },
 2733     {FORMAT_MMDDYYHMS,      "MM-DD-YY HH:MM:SS"   },
 2734     {FORMAT_YYMMDDHMS,      "YY-MM-DD HH:MM:SS"   },
 2735     {FORMAT_DEGREESLON,     "Degrees (lon)"       },
 2736     {FORMAT_DEGREESMMLON,   "DD MM' (lon)"        },
 2737     {FORMAT_DEGREESMMSSLON, "DD MM' SS.s\" (lon)" },
 2738     {FORMAT_MMSSLON,        "MM' SS.s\" (lon)"    },
 2739     {FORMAT_DEGREESLAT,     "Degrees (lat)"       },
 2740     {FORMAT_DEGREESMMLAT,   "DD MM' (lat)"        },
 2741     {FORMAT_DEGREESMMSSLAT, "DD MM' SS.s\" (lat)" },
 2742     {FORMAT_MMSSLAT,        "MM' SS.s\" (lat)"    }
 2743 };
 2744 
 2745 OptionStructure *CreateFormatChoice(Widget parent, char *s)
 2746 {
 2747     OptionStructure *retval;
 2748     
 2749     retval = CreateOptionChoice(parent, s, 4, 31, fmt_option_items);
 2750     
 2751     return(retval);
 2752 }
 2753 
 2754 static OptionItem as_option_items[4] = 
 2755 {
 2756     {AUTOSCALE_NONE, "None"},
 2757     {AUTOSCALE_X,    "X"},
 2758     {AUTOSCALE_Y,    "Y"},
 2759     {AUTOSCALE_XY,   "XY"}
 2760 };
 2761 
 2762 OptionStructure *CreateASChoice(Widget parent, char *s)
 2763 {
 2764     OptionStructure *retval;
 2765     
 2766     retval = CreateOptionChoice(parent, s, 1, 4, as_option_items);
 2767     /* As init value, use this */
 2768     SetOptionChoice(retval, autoscale_onread);
 2769     
 2770     return(retval);
 2771 }
 2772 
 2773 Widget *CreatePrecisionChoice(Widget parent, char *s)
 2774 {
 2775     Widget *w;
 2776     
 2777     w = CreatePanelChoice(parent, s,
 2778                           11,
 2779                           "0", "1", "2", "3", "4",
 2780                           "5", "6", "7", "8", "9",
 2781                           NULL);
 2782 
 2783     return(w);
 2784 }
 2785     
 2786 
 2787 Widget CreateScale(Widget parent, char *s, int min, int max, int delta)
 2788 {
 2789     Widget w;
 2790     XmString str;
 2791 
 2792     str = XmStringCreateLocalized(s);
 2793     
 2794     w = XtVaCreateManagedWidget("scroll",
 2795         xmScaleWidgetClass, parent,
 2796     XmNtitleString, str,
 2797     XmNminimum, min,
 2798     XmNmaximum, max,
 2799         XmNscaleMultiple, delta,
 2800     XmNvalue, 0,
 2801     XmNshowValue, True,
 2802     XmNprocessingDirection, XmMAX_ON_RIGHT,
 2803     XmNorientation, XmHORIZONTAL,
 2804 #if XmVersion >= 2000    
 2805     XmNsliderMark, XmROUND_MARK,
 2806 #endif
 2807     NULL);
 2808 
 2809     XmStringFree(str);
 2810     
 2811     return w;
 2812 }
 2813 
 2814 void SetScaleValue(Widget w, int value)
 2815 {
 2816     XtVaSetValues(w, XmNvalue, value, NULL);
 2817 }
 2818 
 2819 int GetScaleValue(Widget w)
 2820 {
 2821     int value;
 2822     XtVaGetValues(w, XmNvalue, &value, NULL);
 2823     return value;
 2824 }
 2825 
 2826 void SetScaleWidth(Widget w, int width)
 2827 {
 2828     XtVaSetValues(w, XmNscaleWidth, (Dimension) width, NULL);
 2829 }
 2830 
 2831 Widget CreateAngleChoice(Widget parent, char *s)
 2832 {
 2833     return CreateScale(parent, s, 0, 360, 10);
 2834 }
 2835 
 2836 int GetAngleChoice(Widget w)
 2837 {
 2838     return GetScaleValue(w);
 2839 }
 2840 
 2841 void SetAngleChoice(Widget w, int angle)
 2842 {
 2843     SetScaleValue(w, angle);
 2844 }
 2845 
 2846 Widget CreateCharSizeChoice(Widget parent, char *s)
 2847 {
 2848     return CreateScale(parent, s, 0, 1000, 25);
 2849 }
 2850 
 2851 double GetCharSizeChoice(Widget w)
 2852 {
 2853     return ((double) GetScaleValue(w)/100);
 2854 }
 2855 
 2856 void SetCharSizeChoice(Widget w, double size)
 2857 {
 2858     int value = (int) rint(size*100);
 2859     SetScaleValue(w, value);
 2860 }
 2861 
 2862 
 2863 Widget CreateToggleButton(Widget parent, char *s)
 2864 {
 2865     return (XtVaCreateManagedWidget(s, xmToggleButtonWidgetClass, parent, NULL));
 2866 }
 2867 
 2868 int GetToggleButtonState(Widget w)
 2869 {
 2870     return (XmToggleButtonGetState(w));
 2871 }
 2872 
 2873 void SetToggleButtonState(Widget w, int value)
 2874 {
 2875     if (w == NULL) {
 2876         return;
 2877     }
 2878     XmToggleButtonSetState(w, value ? True:False, False);
 2879     
 2880     return;
 2881 }
 2882 
 2883 typedef struct {
 2884     void (*cbproc)();
 2885     void *anydata;
 2886 } TB_CBdata;
 2887 
 2888 static void tb_int_cb_proc(Widget w, XtPointer client_data, XtPointer call_data)
 2889 {
 2890     int onoff;
 2891     
 2892     TB_CBdata *cbdata = (TB_CBdata *) client_data;
 2893 
 2894     onoff = GetToggleButtonState(w);
 2895     cbdata->cbproc(onoff, cbdata->anydata);
 2896 }
 2897 
 2898 void AddToggleButtonCB(Widget w, TB_CBProc cbproc, void *anydata)
 2899 {
 2900     TB_CBdata *cbdata;
 2901     
 2902     cbdata = xmalloc(sizeof(TB_CBdata));
 2903     
 2904     cbdata->cbproc = cbproc;
 2905     cbdata->anydata = anydata;
 2906     XtAddCallback(w,
 2907         XmNvalueChangedCallback, tb_int_cb_proc, (XtPointer) cbdata);
 2908 }
 2909 
 2910 Widget CreateDialogForm(Widget parent, char *s)
 2911 {
 2912     Widget dialog, w;
 2913     char *bufp;
 2914     int standalone;
 2915     
 2916     if (parent == NULL) {
 2917         standalone = TRUE;
 2918         parent = XtAppCreateShell("XMgrace", "XMgrace",
 2919             topLevelShellWidgetClass, disp,
 2920             NULL, 0);
 2921     } else {
 2922         standalone = FALSE;
 2923     }
 2924     bufp = label_to_resname(s, "Dialog");
 2925     dialog = XmCreateDialogShell(parent, bufp, NULL, 0);
 2926     xfree(bufp);
 2927     
 2928     if (standalone) {
 2929         RegisterEditRes(dialog);
 2930     }
 2931     
 2932     handle_close(dialog);
 2933 
 2934     bufp = copy_string(NULL, "Grace: ");
 2935     bufp = concat_strings(bufp, s);
 2936     XtVaSetValues(dialog,
 2937         XmNtitle, bufp,
 2938         NULL);
 2939     xfree(bufp);
 2940 
 2941     w = XmCreateForm(dialog, "form", NULL, 0);
 2942     
 2943     return w;
 2944 }
 2945 
 2946 void SetDialogFormResizable(Widget form, int onoff)
 2947 {
 2948     XtVaSetValues(form,
 2949         XmNresizePolicy, onoff ? XmRESIZE_ANY:XmRESIZE_NONE,
 2950         NULL);
 2951     XtVaSetValues(XtParent(form),
 2952         XmNallowShellResize, onoff ? True:False,
 2953         NULL);
 2954 }
 2955 
 2956 void AddDialogFormChild(Widget form, Widget child)
 2957 {
 2958     Widget last_widget;
 2959     
 2960     XtVaGetValues(form, XmNuserData, &last_widget, NULL);
 2961     if (last_widget) {
 2962         XtVaSetValues(child,
 2963             XmNtopAttachment, XmATTACH_WIDGET,
 2964             XmNtopWidget, last_widget,
 2965             NULL);
 2966         XtVaSetValues(last_widget,
 2967             XmNbottomAttachment, XmATTACH_NONE,
 2968             NULL);
 2969     } else {
 2970         XtVaSetValues(child,
 2971             XmNtopAttachment, XmATTACH_FORM,
 2972             NULL);
 2973     }
 2974     XtVaSetValues(child,
 2975         XmNleftAttachment, XmATTACH_FORM,
 2976         XmNrightAttachment, XmATTACH_FORM,
 2977         XmNbottomAttachment, XmATTACH_FORM,
 2978         NULL);
 2979     XtVaSetValues(form,
 2980         XmNuserData, child,
 2981         NULL);
 2982 }
 2983 
 2984 typedef struct {
 2985     Widget form;
 2986     int close;
 2987     int (*cbproc)();
 2988     void *anydata;
 2989 } AACDialog_CBdata;
 2990 
 2991 void aacdialog_int_cb_proc(void *data)
 2992 {
 2993     AACDialog_CBdata *cbdata;
 2994     int retval;
 2995     
 2996     set_wait_cursor();
 2997 
 2998     cbdata = (AACDialog_CBdata *) data;
 2999     
 3000     retval = cbdata->cbproc(cbdata->anydata);
 3001 
 3002     if (cbdata->close && retval == RETURN_SUCCESS) {
 3003         XtUnmanageChild(XtParent(cbdata->form));
 3004     }
 3005     
 3006     unset_wait_cursor();
 3007 }
 3008 
 3009 void CreateAACDialog(Widget form,
 3010     Widget container, AACDialog_CBProc cbproc, void *data)
 3011 {
 3012     Widget fr, aacbut[3];
 3013     AACDialog_CBdata *cbdata_accept, *cbdata_apply;
 3014     char *aaclab[3] = {"Apply", "Accept", "Close"};
 3015 
 3016     fr = CreateFrame(form, NULL);
 3017     XtVaSetValues(fr,
 3018         XmNtopAttachment, XmATTACH_NONE,
 3019         XmNleftAttachment, XmATTACH_FORM,
 3020         XmNrightAttachment, XmATTACH_FORM,
 3021         XmNbottomAttachment, XmATTACH_FORM,
 3022         NULL);
 3023     CreateCommandButtons(fr, 3, aacbut, aaclab);
 3024 
 3025     AddDialogFormChild(form, container);
 3026     XtVaSetValues(container,
 3027         XmNbottomAttachment, XmATTACH_WIDGET,
 3028         XmNbottomWidget, fr,
 3029         NULL);
 3030     
 3031     XtVaSetValues(form, XmNcancelButton, aacbut[2], NULL);
 3032     
 3033     cbdata_accept = xmalloc(sizeof(AACDialog_CBdata));
 3034     cbdata_accept->form    = form;
 3035     cbdata_accept->anydata = data;
 3036     cbdata_accept->cbproc  = cbproc;
 3037     cbdata_accept->close   = TRUE;
 3038 
 3039     cbdata_apply  = xmalloc(sizeof(AACDialog_CBdata));
 3040     cbdata_apply->form     = form;
 3041     cbdata_apply->anydata  = data;
 3042     cbdata_apply->cbproc   = cbproc;
 3043     cbdata_apply->close    = FALSE;
 3044 
 3045     AddButtonCB(aacbut[0], aacdialog_int_cb_proc, cbdata_apply);
 3046     AddButtonCB(aacbut[1], aacdialog_int_cb_proc, cbdata_accept);
 3047     AddButtonCB(aacbut[2], destroy_dialog_cb, XtParent(form));
 3048     
 3049     XtManageChild(container);
 3050     XtManageChild(form);
 3051 }
 3052 
 3053 TransformStructure *CreateTransformDialogForm(Widget parent,
 3054     char *s, int sel_type)
 3055 {
 3056     TransformStructure *retval;
 3057     
 3058     retval = xmalloc(sizeof(TransformStructure));
 3059     
 3060     retval->form = CreateDialogForm(parent, s);
 3061     
 3062     retval->srcdest = CreateSrcDestSelector(retval->form, sel_type);
 3063     AddDialogFormChild(retval->form, retval->srcdest->form);
 3064 
 3065 /*
 3066  *     retval->restr = CreateRestrictionChoice(retval->form, "Source data filtering");
 3067  *     AddDialogFormChild(retval->form, retval->restr->frame);
 3068  */
 3069     
 3070     return retval;
 3071 }
 3072 
 3073 int GetTransformDialogSettings(TransformStructure *tdialog, int exclusive,
 3074         int *gsrc, int *gdest,
 3075         int *nssrc, int **svaluessrc, int *nsdest, int **svaluesdest)
 3076 {
 3077     int gsrc_ok, gdest_ok;
 3078     
 3079     gsrc_ok = GetSingleListChoice(tdialog->srcdest->src->graph_sel, gsrc);
 3080     gdest_ok = GetSingleListChoice(tdialog->srcdest->dest->graph_sel, gdest);
 3081     if (gsrc_ok == RETURN_FAILURE || gdest_ok == RETURN_FAILURE) {
 3082         errmsg("Please select single source and destination graphs");
 3083     return RETURN_FAILURE;
 3084     }
 3085     
 3086     *nssrc = GetListChoices(tdialog->srcdest->src->set_sel, svaluessrc);
 3087     if (*nssrc == 0) {
 3088         errmsg("No source sets selected");
 3089     return RETURN_FAILURE;
 3090     }    
 3091     *nsdest = GetListChoices(tdialog->srcdest->dest->set_sel, svaluesdest);
 3092     if (*nsdest != 0 && *nssrc != *nsdest) {
 3093         errmsg("Different number of source and destination sets");
 3094         xfree(*svaluessrc);
 3095         xfree(*svaluesdest);
 3096     return RETURN_FAILURE;
 3097     }
 3098     
 3099     /* check for mutually exclusive selections */
 3100     if (exclusive && *gsrc == *gdest && *nsdest != 0) {
 3101         int i;
 3102         for (i = 0; i < *nssrc; i++) {
 3103             if ((*svaluessrc)[i] == (*svaluesdest)[i]) {
 3104                 xfree(*svaluessrc);
 3105                 xfree(*svaluesdest);
 3106                 errmsg("Source and destination set(s) are not mutually exclusive");
 3107             return RETURN_FAILURE;
 3108             }
 3109         }
 3110     }
 3111     
 3112     return RETURN_SUCCESS;
 3113 }
 3114 
 3115 Widget CreateVContainer(Widget parent)
 3116 {
 3117     Widget rc;
 3118     
 3119     rc = XmCreateRowColumn(parent, "VContainer", NULL, 0);
 3120     XtManageChild(rc);
 3121     
 3122     return rc;
 3123 }
 3124 
 3125 Widget CreateHContainer(Widget parent)
 3126 {
 3127     Widget rc;
 3128     
 3129     rc = XmCreateRowColumn(parent, "HContainer", NULL, 0);
 3130     XtVaSetValues(rc, XmNorientation, XmHORIZONTAL, NULL);
 3131     XtManageChild(rc);
 3132     
 3133     return rc;
 3134 }
 3135 
 3136 
 3137 Widget CreateFrame(Widget parent, char *s)
 3138 {
 3139     Widget fr;
 3140     
 3141     fr = XtVaCreateManagedWidget("frame", xmFrameWidgetClass, parent, NULL);
 3142     if (s != NULL) {
 3143         XtVaCreateManagedWidget(s, xmLabelGadgetClass, fr,
 3144                 XmNchildType, XmFRAME_TITLE_CHILD,
 3145                 NULL);
 3146     }
 3147     
 3148     return (fr);   
 3149 }
 3150 
 3151 
 3152 typedef struct {
 3153     int ncols;
 3154     int nrows;
 3155 } GridData;
 3156 
 3157 Widget CreateGrid(Widget parent, int ncols, int nrows)
 3158 {
 3159     Widget w;
 3160     int nfractions;
 3161     GridData *gd;
 3162     
 3163     if (ncols <= 0 || nrows <= 0) {
 3164         errmsg("Wrong call to CreateGrid()");
 3165         ncols = 1;
 3166         nrows = 1;
 3167     }
 3168     
 3169     nfractions = 0;
 3170     do {
 3171         nfractions++;
 3172     } while (nfractions % ncols || nfractions % nrows);
 3173     
 3174     gd = xmalloc(sizeof(GridData));
 3175     gd->ncols = ncols;
 3176     gd->nrows = nrows;
 3177     
 3178     w = XmCreateForm(parent, "grid_form", NULL, 0);
 3179     XtVaSetValues(w,
 3180         XmNfractionBase, nfractions,
 3181         XmNuserData, gd,
 3182         NULL);
 3183 
 3184     XtManageChild(w);
 3185     return w;
 3186 }
 3187 
 3188 void PlaceGridChild(Widget grid, Widget w, int col, int row)
 3189 {
 3190     int nfractions, w1, h1;
 3191     GridData *gd;
 3192     
 3193     XtVaGetValues(grid,
 3194         XmNfractionBase, &nfractions,
 3195         XmNuserData, &gd,
 3196         NULL);
 3197     
 3198     if (gd == NULL) {
 3199         errmsg("PlaceGridChild() called with a non-grid widget");
 3200         return;
 3201     }
 3202     if (col < 0 || col >= gd->ncols) {
 3203         errmsg("PlaceGridChild() called with wrong `col' argument");
 3204         return;
 3205     }
 3206     if (row < 0 || row >= gd->nrows) {
 3207         errmsg("PlaceGridChild() called with wrong `row' argument");
 3208         return;
 3209     }
 3210     
 3211     w1 = nfractions/gd->ncols;
 3212     h1 = nfractions/gd->nrows;
 3213     
 3214     XtVaSetValues(w,
 3215         XmNleftAttachment  , XmATTACH_POSITION,
 3216         XmNleftPosition    , col*w1           ,
 3217         XmNrightAttachment , XmATTACH_POSITION,
 3218         XmNrightPosition   , (col + 1)*w1     ,
 3219         XmNtopAttachment   , XmATTACH_POSITION,
 3220         XmNtopPosition     , row*h1           ,
 3221         XmNbottomAttachment, XmATTACH_POSITION,
 3222         XmNbottomPosition  , (row + 1)*h1     ,
 3223         NULL);
 3224 }
 3225 
 3226 
 3227 Widget CreateTab(Widget parent)
 3228 {
 3229     Widget tab;
 3230     
 3231     tab = XtVaCreateManagedWidget("tab", xmTabWidgetClass, parent, NULL);
 3232     
 3233     return (tab);
 3234 }
 3235 
 3236 Widget CreateTabPage(Widget parent, char *s)
 3237 {
 3238     Widget w;
 3239     XmString str;
 3240     
 3241     w = XmCreateRowColumn(parent, "tabPage", NULL, 0);
 3242     str = XmStringCreateLocalized(s);
 3243     XtVaSetValues(w, XmNtabLabel, str, NULL);
 3244     XmStringFree(str);
 3245     XtManageChild(w);
 3246     
 3247     return (w);
 3248 }
 3249 
 3250 void SelectTabPage(Widget tab, Widget w)
 3251 {
 3252     XmTabSetTabWidget(tab, w, True);
 3253 }
 3254 
 3255 Widget CreateTextItem2(Widget parent, int len, char *s)
 3256 {
 3257     Widget w;
 3258     Widget rc;
 3259     XmString str;
 3260     rc = XmCreateRowColumn(parent, "rc", NULL, 0);
 3261     XtVaSetValues(rc, XmNorientation, XmHORIZONTAL, NULL);
 3262     str = XmStringCreateLocalized(s);
 3263     XtVaCreateManagedWidget("label", xmLabelWidgetClass, rc,
 3264                 XmNlabelString, str,
 3265                 NULL);
 3266     XmStringFree(str);
 3267     w = XtVaCreateManagedWidget("text", xmTextWidgetClass, rc,
 3268                 XmNtraversalOn, True,
 3269                 XmNcolumns, len,
 3270                 NULL);
 3271     XtManageChild(rc);
 3272     return w;
 3273 }
 3274 
 3275 Widget CreateTextItem4(Widget parent, int len, char *label)
 3276 {
 3277     Widget retval;
 3278     XtVaCreateManagedWidget(label, xmLabelWidgetClass, parent, NULL);
 3279     retval = XtVaCreateManagedWidget("text",
 3280         xmTextWidgetClass, parent,
 3281         XmNcolumns, len,
 3282         NULL);
 3283     return retval;
 3284 }
 3285 
 3286 
 3287 /* 
 3288  * create a multiline editable window
 3289  * parent = parent widget
 3290  * hgt    = number of lines in edit window
 3291  * s      = label for window
 3292  * 
 3293  * returns the edit window widget
 3294  */
 3295 Widget CreateScrollTextItem2(Widget parent, int hgt, char *s)
 3296 {
 3297     Widget w, form, label;
 3298     XmString str;
 3299     Arg args[4];
 3300     int ac;
 3301     
 3302     form = XmCreateForm(parent, "form", NULL, 0);
 3303 
 3304     str = XmStringCreateLocalized(s);
 3305     label = XtVaCreateManagedWidget("label",
 3306         xmLabelWidgetClass, form,
 3307     XmNlabelString, str,
 3308     XmNtopAttachment, XmATTACH_FORM,
 3309     XmNleftAttachment, XmATTACH_FORM,
 3310     XmNrightAttachment, XmATTACH_FORM,
 3311     NULL);
 3312     XmStringFree(str);
 3313 
 3314     ac = 0;
 3315     if (hgt > 0) {
 3316         XtSetArg(args[ac], XmNrows, hgt); ac++;
 3317     }
 3318     XtSetArg(args[ac], XmNeditMode, XmMULTI_LINE_EDIT); ac++;
 3319     XtSetArg(args[ac], XmNwordWrap, True); ac++;
 3320     XtSetArg(args[ac], XmNvisualPolicy, XmVARIABLE); ac++;
 3321     w = XmCreateScrolledText(form, "text", args, ac);
 3322     XtVaSetValues(XtParent(w),
 3323     XmNtopAttachment, XmATTACH_WIDGET,
 3324         XmNtopWidget, label,
 3325     XmNleftAttachment, XmATTACH_FORM,
 3326     XmNrightAttachment, XmATTACH_FORM,
 3327     XmNbottomAttachment, XmATTACH_FORM,
 3328     NULL);
 3329     XtManageChild(w);
 3330     
 3331     XtManageChild(form);
 3332     return w;
 3333 }
 3334 
 3335 
 3336 char *xv_getstr(Widget w)
 3337 /* 
 3338  * return the string from a text widget
 3339  *
 3340  * NB - newlines are converted to spaces
 3341  */
 3342 {
 3343     char *s;
 3344     int i;
 3345     static char buf[MAX_STRING_LENGTH];
 3346 
 3347     strncpy(buf, s = XmTextGetString(w), MAX_STRING_LENGTH - 1);
 3348     XtFree(s);
 3349     
 3350     i=strlen(buf);
 3351     for (i--; i >= 0; i--) {
 3352         if (buf[i] == '\n') {
 3353             buf[i] = ' ';
 3354         }
 3355     }
 3356     return buf;
 3357 }
 3358 
 3359 
 3360 /*
 3361  * xv_evalexpr - take a text field and pass it to the parser if it needs to
 3362  * evaluated, else use atof().
 3363  * place the double result in answer
 3364  * if an error, return False, else True
 3365  */
 3366 Boolean xv_evalexpr(Widget w, double *answer )
 3367 {
 3368     char *s;
 3369     static char *buf = NULL;
 3370     int i, len, ier = 0;
 3371     double result;
 3372     
 3373     buf = copy_string(buf, s = XmTextGetString(w));
 3374     XtFree(s);
 3375 
 3376     if (!(len = strlen( buf ) )) { /* check for zero length */
 3377         *answer = 0;
 3378         return RETURN_FAILURE;
 3379     }
 3380     /* first character may be a sign */
 3381     if (!fpdigit[(int) buf[0]] && buf[0] != '-' && buf[0] != '+') {
 3382         i = len +1;
 3383     } else {
 3384         i = 1;
 3385     }
 3386 
 3387     for (; i<len; i++) {
 3388         if (!fpdigit[(int) buf[i]]) {
 3389             break;
 3390         }
 3391     }
 3392 
 3393     if (i == len) {         /* only floating point digits */
 3394         *answer = atof( buf );
 3395         return RETURN_SUCCESS;
 3396     } else {                /* must evaluate an expression */
 3397         ier = s_scanner(buf, &result);
 3398         if( !ier ) {
 3399             *answer = result;
 3400             return RETURN_SUCCESS;
 3401         } else {
 3402             *answer = 0;
 3403             return RETURN_FAILURE;
 3404         }
 3405     }
 3406 }
 3407 
 3408 /*
 3409  * xv_evalexpri - take a text field and pass it to the parser if it needs to
 3410  * evaluated, else use atoi().
 3411  * place the integer result in answer
 3412  * if an error, return False, else True
 3413  */
 3414 Boolean xv_evalexpri(Widget w, int *answer )
 3415 {
 3416     char *s;
 3417     static char *buf = NULL;
 3418     int i, len, ier = 0;
 3419     double result;
 3420     
 3421     buf = copy_string(buf, s = XmTextGetString(w));
 3422     XtFree(s);
 3423 
 3424     if (!(len = strlen( buf ) )) { /* check for zero length */
 3425         *answer = 0;
 3426         return RETURN_FAILURE;
 3427     }
 3428     /* first character may be a sign */
 3429     if (!fpdigit[(int) buf[0]] && buf[0] != '-' && buf[0] != '+') {
 3430         i = len +1;
 3431     } else {
 3432         i = 1;
 3433     }
 3434     
 3435     for (; i<len; i++) {
 3436         if (!fpdigit[(int) buf[i]]) {
 3437             break;
 3438         }
 3439     }
 3440 
 3441     if (i == len) {             /* only floating point digits */
 3442         *answer = atoi(buf);
 3443         return RETURN_SUCCESS;
 3444     } else {                    /* must evaluate an expression */
 3445         ier = s_scanner(buf, &result);
 3446         if( !ier ) {
 3447             *answer = (int)result;
 3448             return RETURN_SUCCESS;
 3449         } else {
 3450             *answer = 0;
 3451             return RETURN_FAILURE;
 3452         }
 3453     }
 3454 }
 3455 
 3456 
 3457 void xv_setstr(Widget w, char *s)
 3458 {
 3459     if (w != NULL) {
 3460         XmTextSetString(w, s ? s : "");
 3461     }
 3462 }
 3463 
 3464 /*
 3465  * generic unmanage popup routine, used elswhere
 3466  */
 3467 void destroy_dialog(Widget w, XtPointer client_data, XtPointer call_data)
 3468 {
 3469     XtUnmanageChild((Widget) client_data);
 3470 }
 3471 
 3472 /*
 3473  * same for AddButtonCB
 3474  */
 3475 void destroy_dialog_cb(void *data)
 3476 {
 3477     XtUnmanageChild((Widget) data);
 3478 }
 3479 
 3480 /* if user tried to close from WM */
 3481 static void wm_exit_cb(Widget w, XtPointer client_data, XtPointer call_data)
 3482 {
 3483     bailout();
 3484 }
 3485 
 3486 /*
 3487  * handle the close item on the WM menu
 3488  */
 3489 void handle_close(Widget w)
 3490 {
 3491     Atom WM_DELETE_WINDOW;
 3492     
 3493     XtVaSetValues(w, XmNdeleteResponse, XmDO_NOTHING, NULL);
 3494     WM_DELETE_WINDOW = XmInternAtom(disp, "WM_DELETE_WINDOW", False);
 3495     XmAddProtocolCallback(w,
 3496         XM_WM_PROTOCOL_ATOM(w), WM_DELETE_WINDOW,
 3497         (w == app_shell) ? wm_exit_cb : destroy_dialog, w);
 3498     
 3499     savewidget(w);
 3500 }
 3501 
 3502 /*
 3503  * Manage and raise
 3504  */
 3505 void RaiseWindow(Widget w)
 3506 {
 3507     XtManageChild(w);
 3508     XMapRaised(XtDisplay(w), XtWindow(w));
 3509 }
 3510 
 3511 
 3512 static Widget *savewidgets = NULL;
 3513 static int nsavedwidgets = 0;
 3514 
 3515 void savewidget(Widget w)
 3516 {
 3517     int i;
 3518     
 3519     for (i = 0; i < nsavedwidgets; i++) {
 3520         if (w == savewidgets[i]) {
 3521             return;
 3522         }
 3523     }
 3524     
 3525     savewidgets = xrealloc(savewidgets, (nsavedwidgets + 1)*sizeof(Widget));
 3526     savewidgets[nsavedwidgets] = w;
 3527     nsavedwidgets++;
 3528 }
 3529 
 3530 void deletewidget(Widget w)
 3531 {
 3532     int i;
 3533     
 3534     for (i = 0; i < nsavedwidgets; i++) {
 3535         if (w == savewidgets[i]) {
 3536             nsavedwidgets--;
 3537             for (; i <  nsavedwidgets; i++) {
 3538                 savewidgets[i] = savewidgets[i + 1];
 3539             }
 3540             savewidgets = xrealloc(savewidgets, nsavedwidgets*sizeof(Widget));
 3541             XtDestroyWidget(w);
 3542             return;
 3543         }
 3544     }
 3545     
 3546 }
 3547 
 3548 void DefineDialogCursor(Cursor c)
 3549 {
 3550     int i;
 3551     
 3552     for (i = 0; i < nsavedwidgets; i++) {
 3553     XDefineCursor(disp, XtWindow(savewidgets[i]), c);
 3554     }
 3555     XFlush(disp);
 3556 }
 3557 
 3558 void UndefineDialogCursor()
 3559 {
 3560     int i;
 3561     
 3562     for (i = 0; i < nsavedwidgets; i++) {
 3563     XUndefineCursor(disp, XtWindow(savewidgets[i]));
 3564     }
 3565     XFlush(disp);
 3566 }
 3567 
 3568 Widget CreateCommandButtonsNoDefault(Widget parent, int n, Widget * buts, char **l)
 3569 {
 3570     int i;
 3571     Widget form;
 3572     Dimension h;
 3573 
 3574     form = XtVaCreateWidget("form", xmFormWidgetClass, parent,
 3575                 XmNfractionBase, n,
 3576                 NULL);
 3577 
 3578     for (i = 0; i < n; i++) {
 3579     buts[i] = XtVaCreateManagedWidget(l[i],
 3580                       xmPushButtonWidgetClass, form,
 3581                       XmNtopAttachment, XmATTACH_FORM,
 3582                       XmNbottomAttachment, XmATTACH_FORM,
 3583                       XmNleftAttachment, XmATTACH_POSITION,
 3584                       XmNleftPosition, i,
 3585                       XmNrightAttachment, XmATTACH_POSITION,
 3586                       XmNrightPosition, i + 1,
 3587                       XmNleftOffset, (i == 0) ? 2 : 0,
 3588                       XmNrightOffset, 3,
 3589                       XmNtopOffset, 2,
 3590                       XmNbottomOffset, 3,
 3591                       NULL);
 3592     }
 3593     XtManageChild(form);
 3594     XtVaGetValues(buts[0], XmNheight, &h, NULL);
 3595     XtVaSetValues(form, XmNpaneMaximum, h, XmNpaneMinimum, h, NULL);
 3596     
 3597     return form;
 3598 }
 3599 
 3600 Widget CreateCommandButtons(Widget parent, int n, Widget * buts, char **l)
 3601 {
 3602     int i;
 3603     Widget form;
 3604     Dimension h;
 3605 
 3606     form = XtVaCreateWidget("form", xmFormWidgetClass, parent,
 3607                 XmNfractionBase, n,
 3608                 NULL);
 3609 
 3610     for (i = 0; i < n; i++) {
 3611     buts[i] = XtVaCreateManagedWidget(l[i],
 3612                       xmPushButtonWidgetClass, form,
 3613                       XmNtopAttachment, XmATTACH_FORM,
 3614                       XmNbottomAttachment, XmATTACH_FORM,
 3615                       XmNleftAttachment, XmATTACH_POSITION,
 3616                       XmNleftPosition, i,
 3617                       XmNrightAttachment, XmATTACH_POSITION,
 3618                       XmNrightPosition, i + 1,
 3619                       XmNdefaultButtonShadowThickness, 1,
 3620                       XmNshowAsDefault, (i == 0) ? True : False,
 3621                       NULL);
 3622     }
 3623     XtManageChild(form);
 3624     XtVaGetValues(buts[0], XmNheight, &h, NULL);
 3625     XtVaSetValues(form, XmNpaneMaximum, h, XmNpaneMinimum, h, NULL);
 3626     
 3627     return form;
 3628 }
 3629 
 3630 
 3631 
 3632 static SetChoiceItem *plist = NULL;
 3633 static int nplist = 0;
 3634 
 3635 SetChoiceItem CreateSetSelector(Widget parent,
 3636                 char *label,
 3637                 int type,
 3638                 int ff,
 3639                 int gtype,
 3640                 int stype)
 3641 {
 3642     Arg args[3];
 3643     Widget rc2, lab;
 3644     SetChoiceItem sel;
 3645     
 3646     rc2 = XtVaCreateWidget("rc", xmRowColumnWidgetClass, parent,
 3647                   XmNorientation, XmVERTICAL, NULL);
 3648     lab = XmCreateLabel(rc2, label, NULL, 0);
 3649     XtManageChild(lab);
 3650     XtSetArg(args[0], XmNlistSizePolicy, XmRESIZE_IF_POSSIBLE);
 3651     XtSetArg(args[1], XmNvisibleItemCount, 6);
 3652     sel.list = XmCreateScrolledList(rc2, "list", args, 2);
 3653     if (stype == SELECTION_TYPE_MULTIPLE) { /* multiple select */
 3654     XtVaSetValues(sel.list,
 3655               XmNselectionPolicy, XmEXTENDED_SELECT,
 3656               NULL);
 3657     } else {            /* single select */
 3658         XtVaSetValues(sel.list,
 3659               XmNselectionPolicy, XmSINGLE_SELECT,
 3660               NULL);
 3661     }
 3662     sel.type = type;
 3663     sel.gno = gtype;
 3664     XtManageChild(sel.list);
 3665     sel.indx = save_set_list(sel);
 3666     update_set_list(gtype == GRAPH_SELECT_CURRENT ? get_cg():sel.gno, sel);
 3667     
 3668     XtManageChild(rc2);
 3669     return sel;
 3670 }
 3671 
 3672 int GetSelectedSet(SetChoiceItem l)
 3673 {
 3674     int retval = SET_SELECT_ERROR;
 3675     int *pos_list;
 3676     int pos_cnt, cnt;
 3677     char buf[256];
 3678     
 3679     if (XmListGetSelectedPos(l.list, &pos_list, &pos_cnt)) {
 3680     XmString *s, cs;
 3681     char *cstr;
 3682     XtVaGetValues(l.list,
 3683               XmNselectedItemCount, &cnt,
 3684               XmNselectedItems, &s,
 3685               NULL);
 3686     cs = XmStringCopy(*s);
 3687     if ((cstr = GetStringSimple(cs))) {
 3688         strcpy(buf, cstr);
 3689         if (strcmp(buf, "New set") == 0) {
 3690         retval = SET_SELECT_NEXT;
 3691         } else if (strcmp(buf, "All sets") == 0) {
 3692         retval = SET_SELECT_ALL;
 3693         } else if (strcmp(buf, "Nearest set") == 0) {
 3694         retval = SET_SELECT_NEAREST;
 3695         } else {
 3696         sscanf(buf, "S%d", &retval);
 3697         }
 3698         XtFree(cstr);
 3699     }
 3700         XmStringFree(cs);
 3701     }
 3702     
 3703     return retval;
 3704 }
 3705 
 3706 /*
 3707  * if the set selection type is multiple, then get a
 3708  * list of sets, returns the number of selected sets.
 3709  */
 3710 int GetSelectedSets(SetChoiceItem l, int **sets)
 3711 {
 3712     int i;
 3713     int cnt = SET_SELECT_ERROR, retval = SET_SELECT_ERROR;
 3714     int *ptr;
 3715     int *pos_list;
 3716     int pos_cnt, gno;
 3717     if (XmListGetSelectedPos(l.list, &pos_list, &pos_cnt)) {
 3718     char buf[256];
 3719     char *cstr;
 3720     XmString *s, cs;
 3721 
 3722     XtVaGetValues(l.list,
 3723               XmNselectedItemCount, &cnt,
 3724               XmNselectedItems, &s,
 3725               NULL);
 3726     *sets = xmalloc(cnt * SIZEOF_INT);
 3727     ptr = *sets;
 3728     for (i = 0; i < cnt; i++) {
 3729         cs = XmStringCopy(s[i]);
 3730         if ((cstr = GetStringSimple(cs))) {
 3731         strcpy(buf, cstr);
 3732         if (strcmp(buf, "New set") == 0) {
 3733             retval = SET_SELECT_NEXT;
 3734             return retval;
 3735         } else if (strcmp(buf, "All sets") == 0) {
 3736             int j, nsets = 0;
 3737             retval = SET_SELECT_ALL;
 3738             if (l.gno == GRAPH_SELECT_CURRENT) {
 3739             gno = get_cg();
 3740             } else {
 3741             gno = l.gno;
 3742             }
 3743             retval = nactive(gno);
 3744             *sets = xrealloc(*sets, retval * SIZEOF_INT);
 3745             ptr = *sets;
 3746             for (j = 0; j < number_of_sets(gno); j++) {
 3747             if (is_set_active(gno, j)) {
 3748                 ptr[nsets] = j;
 3749                 nsets++;
 3750             }
 3751             }
 3752             if (nsets != retval) {
 3753             errwin("Nsets != reval, can't happen!");
 3754             }
 3755             return retval;
 3756         } else {
 3757             sscanf(buf, "S%d", &retval);
 3758         }
 3759         ptr[i] = retval;
 3760         XtFree(cstr);
 3761         }
 3762         XmStringFree(cs);
 3763     }
 3764     }
 3765     return cnt;
 3766 }
 3767 
 3768 int save_set_list(SetChoiceItem l)
 3769 {
 3770     nplist++;
 3771     plist = xrealloc(plist, nplist*sizeof(SetChoiceItem));
 3772     plist[nplist - 1] = l;
 3773     return nplist - 1;
 3774 }
 3775 
 3776 void update_save_set_list( SetChoiceItem l, int newgr )
 3777 {
 3778     plist[l.indx] = l;
 3779     update_set_list( newgr, plist[l.indx] );
 3780 }
 3781 
 3782 void update_set_list(int gno, SetChoiceItem l)
 3783 {
 3784     int i, cnt, scnt=0;
 3785     char buf[1024];
 3786     XmString *xms;
 3787     
 3788     XmListDeleteAllItems(l.list);
 3789     for (i = 0; i < number_of_sets(gno); i++) {
 3790     if (is_set_active(gno, i)) {
 3791         scnt++;
 3792     }
 3793     }
 3794 
 3795     switch (l.type) {       /* TODO */
 3796     case SET_SELECT_ACTIVE:
 3797     xms = xmalloc(sizeof(XmString) * scnt);
 3798     cnt = 0;
 3799     break;
 3800     case SET_SELECT_ALL:
 3801     xms = xmalloc(sizeof(XmString) * (scnt + 1));
 3802     xms[0] = XmStringCreateLocalized("All sets");
 3803     cnt = 1;
 3804     break;
 3805     case SET_SELECT_NEXT:
 3806     xms = xmalloc(sizeof(XmString) * (scnt + 1));
 3807     xms[0] = XmStringCreateLocalized("New set");
 3808     cnt = 1;
 3809     break;
 3810     case SET_SELECT_NEAREST:
 3811     xms = xmalloc(sizeof(XmString) * (scnt + 1));
 3812     xms[0] = XmStringCreateLocalized("Nearest set");
 3813     cnt = 1;
 3814     break;
 3815     default:
 3816     xms = xmalloc(sizeof(XmString) * scnt);
 3817     cnt = 0;
 3818     break;
 3819     }
 3820 
 3821     for (i = 0; i < number_of_sets(gno); i++) {
 3822         if (is_set_active(gno, i)) {
 3823             sprintf(buf, "S%d (N=%d, %s)", i, getsetlength(gno, i), getcomment(gno, i));
 3824             xms[cnt] = XmStringCreateLocalized(buf);
 3825             cnt++;
 3826         }
 3827     }
 3828     XmListAddItemsUnselected(l.list, xms, cnt, 0);
 3829 
 3830     /* automatically highlight if only 1 selection */
 3831     if (scnt == 1) {
 3832         XmListSelectItem(l.list, xms[cnt-1], True);
 3833     }
 3834     
 3835     for (i = 0; i < cnt; i++) {
 3836         XmStringFree(xms[i]);
 3837     }
 3838     xfree(xms);
 3839 }
 3840 
 3841 
 3842 void update_set_lists(int gno)
 3843 {
 3844     int i;
 3845 
 3846     if (gno == GRAPH_SELECT_CURRENT) {
 3847         update_set_selectors(get_cg());
 3848         update_ss_editors(get_cg());
 3849     } else {
 3850         update_set_selectors(gno);
 3851         update_ss_editors(gno);
 3852     }
 3853 
 3854     if (inwin) {
 3855         for (i = 0; i < nplist; i++) {
 3856             if (plist[i].gno == gno || 
 3857                 (gno == get_cg() && plist[i].gno == GRAPH_SELECT_CURRENT)) {
 3858                 update_set_list(gno, plist[i]);
 3859             }
 3860         }
 3861     }
 3862 }
 3863 
 3864 
 3865 Widget CreateSeparator(Widget parent)
 3866 {
 3867     Widget sep;
 3868     
 3869     sep = XmCreateSeparator(parent, "sep", NULL, 0);
 3870     XtManageChild(sep);
 3871     return sep;
 3872 }
 3873 
 3874 Widget CreateMenuBar(Widget parent)
 3875 {
 3876     Widget menubar;
 3877     
 3878     menubar = XmCreateMenuBar(parent, "menuBar", NULL, 0);
 3879     return menubar;
 3880 }
 3881 
 3882 Widget CreateMenu(Widget parent, char *label, char mnemonic, int help)
 3883 {
 3884     Widget menupane, cascade;
 3885     XmString str;
 3886     char *name, ms[2];
 3887     
 3888     name = label_to_resname(label, "Menu");
 3889     menupane = XmCreatePulldownMenu(parent, name, NULL, 0);
 3890     xfree(name);
 3891 
 3892     ms[0] = mnemonic;
 3893     ms[1] = '\0';
 3894     
 3895     str = XmStringCreateLocalized(label);
 3896     cascade = XtVaCreateManagedWidget("cascade",
 3897         xmCascadeButtonGadgetClass, parent, 
 3898         XmNsubMenuId, menupane, 
 3899         XmNlabelString, str, 
 3900         XmNmnemonic, XStringToKeysym(ms),
 3901         NULL);
 3902     XmStringFree(str);
 3903 
 3904     if (help) {
 3905         XtVaSetValues(parent, XmNmenuHelpWidget, cascade, NULL);
 3906         CreateMenuButton(menupane, "On context", 'x',
 3907             ContextHelpCB, NULL);
 3908         CreateSeparator(menupane);
 3909     }
 3910 
 3911     return menupane;
 3912 }
 3913 
 3914 
 3915 Widget CreateMenuButton(Widget parent, char *label, char mnemonic,
 3916     Button_CBProc cb, void *data)
 3917 {
 3918     Widget button;
 3919     XmString str;
 3920     char *name, ms[2];
 3921     
 3922     ms[0] = mnemonic;
 3923     ms[1] = '\0';
 3924     
 3925     str = XmStringCreateLocalized(label);
 3926     name = label_to_resname(label, "Button");
 3927     button = XtVaCreateManagedWidget(name,
 3928         xmPushButtonWidgetClass, parent, 
 3929         XmNlabelString, str,
 3930         XmNmnemonic, XStringToKeysym(ms),
 3931         NULL);
 3932     xfree(name);
 3933     XmStringFree(str);
 3934 
 3935     AddButtonCB(button, cb, data);
 3936 
 3937     return button;
 3938 }
 3939 
 3940 Widget CreateMenuCloseButton(Widget parent, Widget form)
 3941 {
 3942     Widget wbut;
 3943     XmString str;
 3944     
 3945     wbut = CreateMenuButton(parent,
 3946         "Close", 'C', destroy_dialog_cb, XtParent(form));
 3947     str = XmStringCreateLocalized("Esc");
 3948     XtVaSetValues(wbut, XmNacceleratorText, str, NULL);
 3949     XmStringFree(str);
 3950     XtVaSetValues(form, XmNcancelButton, wbut, NULL);
 3951     
 3952     return wbut;
 3953 }
 3954 
 3955 Widget CreateMenuHelpButton(Widget parent, char *label, char mnemonic,
 3956     Widget form, char *ha)
 3957 {
 3958     Widget wbut;
 3959     
 3960     wbut = CreateMenuButton(parent, label, mnemonic, HelpCB, ha);
 3961     AddHelpCB(form, ha);
 3962     
 3963     return wbut;
 3964 }
 3965 
 3966 Widget CreateMenuToggle(Widget parent, char *label, char mnemonic,
 3967     TB_CBProc cb, void *data)
 3968 {
 3969     Widget button;
 3970     XmString str;
 3971     char *name, ms[2];
 3972     
 3973     ms[0] = mnemonic;
 3974     ms[1] = '\0';
 3975     
 3976     str = XmStringCreateLocalized(label);
 3977     name = label_to_resname(label, NULL);
 3978     button = XtVaCreateManagedWidget(name,
 3979         xmToggleButtonWidgetClass, parent, 
 3980         XmNlabelString, str,
 3981         XmNmnemonic, XStringToKeysym(ms),
 3982         XmNvisibleWhenOff, True,
 3983         XmNindicatorOn, True,
 3984         NULL);
 3985     xfree(name);
 3986     XmStringFree(str);
 3987 
 3988     if (cb) {
 3989         AddToggleButtonCB(button, cb, data);
 3990     }
 3991 
 3992     return button;
 3993 }
 3994 
 3995 Widget CreateMenuLabel(Widget parent, char *name)
 3996 {
 3997     Widget lab;
 3998     
 3999     lab = XmCreateLabel(parent, name, NULL, 0);
 4000     XtManageChild(lab);
 4001     return lab;
 4002 }
 4003 
 4004 static void help_int_cb(Widget w, XtPointer client_data, XtPointer call_data)
 4005 {
 4006     HelpCB(client_data);
 4007 }
 4008 
 4009 void AddHelpCB(Widget w, char *ha)
 4010 {
 4011     if (XtHasCallbacks(w, XmNhelpCallback) == XtCallbackHasSome) {
 4012         /* allow only one help callback */
 4013         XtRemoveAllCallbacks(w, XmNhelpCallback);
 4014     }
 4015     
 4016     XtAddCallback(w, XmNhelpCallback, help_int_cb, (XtPointer) ha);
 4017 }
 4018 
 4019 void ContextHelpCB(void *data)
 4020 {
 4021     Widget whelp;
 4022     Cursor cursor;
 4023     int ok = FALSE;
 4024     
 4025     cursor = XCreateFontCursor(disp, XC_question_arrow);
 4026     whelp = XmTrackingLocate(app_shell, cursor, False);
 4027     while (whelp != NULL) {
 4028         if (XtHasCallbacks(whelp, XmNhelpCallback) == XtCallbackHasSome) {
 4029             XtCallCallbacks(whelp, XmNhelpCallback, NULL);
 4030             ok = TRUE;
 4031             break;
 4032         } else {
 4033             whelp = GetParent(whelp);
 4034         }
 4035     }
 4036     if (!ok) {
 4037         HelpCB(NULL);
 4038     }
 4039     XFreeCursor(disp, cursor);
 4040 }
 4041 
 4042 
 4043 static int yesno_retval = 0;
 4044 static Boolean keep_grab = True;
 4045 
 4046 void yesnoCB(Widget w, XtPointer client_data, XtPointer call_data)
 4047 {
 4048     XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;
 4049     int why = cbs->reason;
 4050 
 4051     keep_grab = False;
 4052     
 4053     XtRemoveGrab(XtParent(w));
 4054     XtUnmanageChild(w);
 4055     switch (why) {
 4056     case XmCR_OK:
 4057     yesno_retval = 1;
 4058     /* process ok action */
 4059     break;
 4060     case XmCR_CANCEL:
 4061     yesno_retval = 0;
 4062     /* process cancel action */
 4063     break;
 4064     }
 4065 }
 4066 
 4067 static void update_yesno(Widget w, char *msg, char *ha)
 4068 {
 4069     Widget hb;
 4070     XmString str;
 4071     
 4072     if (msg != NULL) {
 4073         str = XmStringCreateLocalized(msg);
 4074     } else {
 4075         str = XmStringCreateLocalized("Warning");
 4076     }
 4077     XtVaSetValues(w, XmNmessageString, str, NULL);
 4078     XmStringFree(str);
 4079     
 4080     hb = XtNameToWidget(w, "Help");
 4081     if (ha) {
 4082         AddButtonCB(hb, HelpCB, ha);
 4083         XtSetSensitive(hb, True);
 4084     } else {    
 4085         XtSetSensitive(hb, False);
 4086     }
 4087 }
 4088 
 4089 int yesnowin(char *msg, char *s1, char *s2, char *help_anchor)
 4090 {
 4091     static Widget yesno_popup = NULL;
 4092     XEvent event;
 4093 
 4094     keep_grab = True;
 4095 
 4096     if (yesno_popup == NULL) {
 4097     yesno_popup = XmCreateErrorDialog(app_shell, "warndlg", NULL, 0);
 4098 
 4099     XtAddCallback(yesno_popup, XmNokCallback, yesnoCB, NULL);
 4100     XtAddCallback(yesno_popup, XmNcancelCallback, yesnoCB, NULL);
 4101     }
 4102     update_yesno(yesno_popup, msg, help_anchor);
 4103     RaiseWindow(yesno_popup);
 4104     
 4105     XtAddGrab(XtParent(yesno_popup), True, False);
 4106     while (keep_grab || XtAppPending(app_con)) {
 4107     XtAppNextEvent(app_con, &event);
 4108     XtDispatchEvent(&event);
 4109     }
 4110     return yesno_retval;
 4111 }
 4112 
 4113 
 4114 Widget CreateAACButtons(Widget parent, Widget form, Button_CBProc aac_cb)
 4115 {
 4116     Widget w;
 4117     Widget aacbut[3];
 4118     static char *aaclab[3] = {"Apply", "Accept", "Close"};
 4119     
 4120     w = CreateCommandButtons(parent, 3, aacbut, aaclab);
 4121     AddButtonCB(aacbut[0], aac_cb, (void *) AAC_APPLY);
 4122     AddButtonCB(aacbut[1], aac_cb, (void *) AAC_ACCEPT);
 4123     AddButtonCB(aacbut[2], aac_cb, (void *) AAC_CLOSE);
 4124     
 4125     if (form != NULL) {
 4126         XtVaSetValues(form, XmNcancelButton, aacbut[2], NULL);
 4127     }
 4128     
 4129     return w;
 4130 }
 4131 
 4132 void SetLabel(Widget w, char *s)
 4133 {
 4134     XmString str;
 4135 
 4136     str = XmStringCreateLocalized(s);
 4137     XtVaSetValues(w, XmNlabelString, str, NULL);
 4138     XmStringFree(str);
 4139 }
 4140 
 4141 void SetFixedFont(Widget w)
 4142 {
 4143     XFontStruct *f;
 4144     XmFontList xmf;
 4145 
 4146     f = XLoadQueryFont(disp, "fixed");
 4147     xmf = XmFontListCreate(f, charset);
 4148     if (xmf == NULL) {
 4149         errmsg("Can't load font \"fixed\"");
 4150         return;
 4151     } else {
 4152         XtVaSetValues(w, XmNfontList, xmf, NULL);
 4153         XmFontListFree(xmf);
 4154     }
 4155 }
 4156 
 4157 char *GetStringSimple(XmString xms)
 4158 {
 4159     char *s;
 4160 
 4161     if (XmStringGetLtoR(xms, charset, &s)) {
 4162         return s;
 4163     } else {
 4164         return NULL;
 4165     }
 4166 }
 4167 
 4168 extern int ReqUpdateColorSel;
 4169 
 4170 void update_all(void)
 4171 {
 4172     int gno = get_cg();
 4173     
 4174     if (!inwin) {
 4175         return;
 4176     }
 4177     
 4178     update_set_lists(gno);
 4179 
 4180     update_set_selectors(ALL_GRAPHS);
 4181     update_ss_editors(ALL_GRAPHS);
 4182 
 4183     if (ReqUpdateColorSel == TRUE) {
 4184         update_color_selectors();
 4185         ReqUpdateColorSel = FALSE;
 4186     }
 4187 
 4188     update_ticks(gno);
 4189     update_props_items();
 4190     update_hotlinks();
 4191     update_prune_frame();
 4192     update_locator_items(gno);
 4193     set_stack_message();
 4194     set_left_footer(NULL);
 4195 }
 4196 
 4197 void update_all_cb(void *data)
 4198 {
 4199     update_all();
 4200 }