X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=xoptions.c;h=e66e4bcbade559f38632cf05c510ed519dfa2df6;hb=7e0222e64da6706bf0dc2468f459b98e4346206b;hp=5e4fac87d0742c79a9cf16063583069846bb251a;hpb=74025874f2010f84fd4f7f2e120e84b56ee9781b;p=xboard.git diff --git a/xoptions.c b/xoptions.c index 5e4fac8..cd18a57 100644 --- a/xoptions.c +++ b/xoptions.c @@ -1,28 +1,24 @@ /* * xoptions.c -- Move list window, part of X front end for XBoard * - * Copyright 2000 Free Software Foundation, Inc. - * - * The following terms apply to the enhanced version of XBoard distributed - * by the Free Software Foundation: + * Copyright 2000, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. * ------------------------------------------------------------------------ - * This program is free software; you can redistribute it and/or modify + * + * GNU XBoard is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU XBoard is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * ------------------------------------------------------------------------ + * along with this program. If not, see http://www.gnu.org/licenses/. * * - * See the file ChangeLog for a revision history. - */ + *------------------------------------------------------------------------ + ** See the file ChangeLog for a revision history. */ // [HGM] this file is the counterpart of woptions.c, containing xboard popup menus // similar to those of WinBoard, to set the most common options interactively. @@ -49,10 +45,12 @@ extern char *getenv(); #if HAVE_UNISTD_H # include #endif +#include #include #include #include +#include #include #include #include @@ -68,1656 +66,1162 @@ extern char *getenv(); #include #include #include +#include + +#include +#include #include "common.h" #include "backend.h" #include "xboard.h" - -extern Widget formWidget, shellWidget, boardWidget, menuBarWidget; -extern Display *xDisplay; -extern int squareSize; -extern Pixmap xMarkPixmap; -extern char *layoutName; -extern Window xBoardWindow; -extern Arg layoutArgs[2], formArgs[2]; -Pixel timerForegroundPixel, timerBackgroundPixel; +#include "dialogs.h" +#include "menus.h" +#include "gettext.h" + +#ifdef ENABLE_NLS +# define _(s) gettext (s) +# define N_(s) gettext_noop (s) +#else +# define _(s) (s) +# define N_(s) s +#endif // [HGM] the following code for makng menu popups was cloned from the FileNamePopUp routines static Widget previous = NULL; +static Option *currentOption; -void SetFocus(Widget w, XtPointer data, XEvent *event, Boolean *b) +void +UnCaret () { - Arg args; + Arg args[2]; if(previous) { - XtSetArg(args, XtNdisplayCaret, False); - XtSetValues(previous, &args, 1); + XtSetArg(args[0], XtNdisplayCaret, False); + XtSetValues(previous, args, 1); } - XtSetArg(args, XtNdisplayCaret, True); - XtSetValues(w, &args, 1); + previous = NULL; +} + +void +SetFocus (Widget w, XtPointer data, XEvent *event, Boolean *b) +{ + Arg args[2]; + char *s; + int j; + + UnCaret(); + XtSetArg(args[0], XtNstring, &s); + XtGetValues(w, args, 1); + j = 1; + XtSetArg(args[0], XtNdisplayCaret, True); + if(!strchr(s, '\n') && strlen(s) < 80) XtSetArg(args[1], XtNinsertPosition, strlen(s)), j++; + XtSetValues(w, args, j); XtSetKeyboardFocus((Widget) data, w); previous = w; } -//--------------------------- New Shuffle Game -------------------------------------------- -extern int shuffleOpenings; -extern int startedFromPositionFile; -int shuffleUp; -Widget shuffleShell; - -void ShufflePopDown() +void +BoardFocus () { - if (!shuffleUp) return; - XtPopdown(shuffleShell); - XtDestroyWidget(shuffleShell); - shuffleUp = False; - ModeHighlight(); + XtSetKeyboardFocus(shellWidget, formWidget); } -void ShuffleCallback(w, client_data, call_data) - Widget w; - XtPointer client_data, call_data; +//--------------------------- Engine-specific options menu ---------------------------------- + +int dialogError; +Option *dialogOptions[NrOfDialogs]; + +static Arg layoutArgs[] = { + { XtNborderWidth, 0 }, + { XtNdefaultDistance, 0 }, +}; + +static Arg formArgs[] = { + { XtNborderWidth, 0 }, + { XtNresizable, (XtArgVal) True }, +}; + +void +MarkMenuItem (char *menuRef, int state) { - String name; - Widget w2; - Arg args[16]; - char buf[80]; - - XtSetArg(args[0], XtNlabel, &name); - XtGetValues(w, args, 1); - - if (strcmp(name, "cancel") == 0) { - ShufflePopDown(); - return; - } - if (strcmp(name, "off") == 0) { - ShufflePopDown(); - shuffleOpenings = False; // [HGM] should be moved to New Variant menu, once we have it! - ResetGameEvent(); - AnalysisPopDown(); - return; - } - if (strcmp(name, "random") == 0) { - sprintf(buf, "%d", rand()); - XtSetArg(args[0],XtNvalue, buf); // erase bad (non-numeric) value - XtSetValues(XtParent(w), args, 1); - return; - } - if (strcmp(name, "ok") == 0) { - int nr; String name; - name = XawDialogGetValueString(w2 = XtParent(w)); - if(sscanf(name ,"%d",&nr) != 1) { - sprintf(buf, "%d", appData.defaultFrcPosition); - XtSetArg(args[0],XtNvalue, buf); // erase bad (non-numeric) value - XtSetValues(w2, args, 1); - return; - } - appData.defaultFrcPosition = nr; - shuffleOpenings = True; - ShufflePopDown(); - ResetGameEvent(); - AnalysisPopDown(); - return; + MenuItem *item = MenuNameToItem(menuRef); + + if(item) { + Arg args[2]; + XtSetArg(args[0], XtNleftBitmap, state ? xMarkPixmap : None); + XtSetValues(item->handle, args, 1); } } -void ShufflePopUp() +void +GetWidgetText (Option *opt, char **buf) { - Arg args[16]; - Widget popup, layout, dialog, edit; - Window root, child; - int x, y, i; - int win_x, win_y; - unsigned int mask; - char def[80]; - - i = 0; - XtSetArg(args[i], XtNresizable, True); i++; - XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++; - shuffleShell = popup = - XtCreatePopupShell("New Shuffle Game", transientShellWidgetClass, - shellWidget, args, i); - - layout = - XtCreateManagedWidget(layoutName, formWidgetClass, popup, - layoutArgs, XtNumber(layoutArgs)); - - sprintf(def, "%d\n", appData.defaultFrcPosition); - i = 0; - XtSetArg(args[i], XtNlabel, "Start-position number:"); i++; - XtSetArg(args[i], XtNvalue, def); i++; - XtSetArg(args[i], XtNborderWidth, 0); i++; - dialog = XtCreateManagedWidget("Shuffle", dialogWidgetClass, - layout, args, i); - -// XtSetArg(args[0], XtNeditType, XawtextEdit); // [HGM] can't get edit to work decently -// XtSetArg(args[1], XtNuseStringInPlace, False); -// XtSetValues(dialog, args, 2); - - XawDialogAddButton(dialog, "ok", ShuffleCallback, (XtPointer) dialog); - XawDialogAddButton(dialog, "cancel", ShuffleCallback, (XtPointer) dialog); - XawDialogAddButton(dialog, "random", ShuffleCallback, (XtPointer) dialog); - XawDialogAddButton(dialog, "off", ShuffleCallback, (XtPointer) dialog); - - XtRealizeWidget(popup); - CatchDeleteWindow(popup, "ShufflePopDown"); - - XQueryPointer(xDisplay, xBoardWindow, &root, &child, - &x, &y, &win_x, &win_y, &mask); - - XtSetArg(args[0], XtNx, x - 10); - XtSetArg(args[1], XtNy, y - 30); - XtSetValues(popup, args, 2); - - XtPopup(popup, XtGrabExclusive); - shuffleUp = True; - - edit = XtNameToWidget(dialog, "*value"); - - XtSetKeyboardFocus(popup, edit); + Arg arg; + XtSetArg(arg, XtNstring, buf); + XtGetValues(opt->handle, &arg, 1); } -void ShuffleMenuProc(w, event, prms, nprms) - Widget w; - XEvent *event; - String *prms; - Cardinal *nprms; +void +SetWidgetText (Option *opt, char *buf, int n) { -// if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) { -// Reset(FALSE, TRUE); -// } - ShufflePopUp(); + Arg arg; + XtSetArg(arg, XtNstring, buf); + XtSetValues(opt->handle, &arg, 1); + if(n >= 0) SetFocus(opt->handle, shells[n], NULL, False); } -//--------------------------- Time-Control Menu Popup ---------------------------------- -int TimeControlUp; -Widget TimeControlShell; -int tcInc; -Widget tcMess1, tcMess2, tcData, tcTime, tcOdds1, tcOdds2; -int tcIncrement, tcMoves; - -void TimeControlPopDown() +void +GetWidgetState (Option *opt, int *state) { - if (!TimeControlUp) return; - XtPopdown(TimeControlShell); - XtDestroyWidget(TimeControlShell); - TimeControlUp = False; - ModeHighlight(); + Arg arg; + XtSetArg(arg, XtNstate, state); + XtGetValues(opt->handle, &arg, 1); } -void TimeControlCallback(w, client_data, call_data) - Widget w; - XtPointer client_data, call_data; +void +SetWidgetState (Option *opt, int state) { - String name, txt; - Widget w2; - Arg args[16]; - char buf[80]; - int j; + Arg arg; + XtSetArg(arg, XtNstate, state); + XtSetValues(opt->handle, &arg, 1); +} - XtSetArg(args[0], XtNlabel, &name); - XtGetValues(w, args, 1); - - if (strcmp(name, "classical") == 0) { - if(!tcInc) return; - j=0; - XtSetArg(args[j], XtNlabel, "minutes for each"); j++; - XtSetValues(tcMess1, args, j); - j=0; - XtSetArg(args[j], XtNlabel, "moves"); j++; - XtSetValues(tcMess2, args, j); - j=0; - XtSetArg(args[j], XtNstring, &name); j++; - XtGetValues(tcData, args, j); - tcIncrement = 0; sscanf(name, "%d", &tcIncrement); - sprintf(buf, "%d", tcMoves); - j=0; - XtSetArg(args[j], XtNstring, buf); j++; - XtSetValues(tcData, args, j); - tcInc = False; - return; - } - if (strcmp(name, "incremental") == 0) { - if(tcInc) return; - j=0; - XtSetArg(args[j], XtNlabel, "minutes, plus"); j++; - XtSetValues(tcMess1, args, j); - j=0; - XtSetArg(args[j], XtNlabel, "sec/move"); j++; - XtSetValues(tcMess2, args, j); - j=0; - XtSetArg(args[j], XtNstring, &name); j++; - XtGetValues(tcData, args, j); - tcMoves = appData.movesPerSession; sscanf(name, "%d", &tcMoves); - sprintf(buf, "%d", tcIncrement); - j=0; - XtSetArg(args[j], XtNstring, buf); j++; - XtSetValues(tcData, args, j); - tcInc = True; - return; - } - if (strcmp(name, " OK ") == 0) { - int inc, mps, tc, ok; - XtSetArg(args[0], XtNstring, &txt); - XtGetValues(tcData, args, 1); - if(tcInc) { - ok = sscanf(txt, "%d", &inc); mps = 0; - if(!ok && txt[0] == 0) { inc = 0; ok = 1; } // accept empty string as zero - ok &= (inc >= 0); - } else { - ok = sscanf(txt, "%d", &mps); inc = -1; - ok &= (mps > 0); - } - if(ok != 1) { - XtSetArg(args[0], XtNstring, ""); // erase any offending input - XtSetValues(tcData, args, 1); - return; - } - XtSetArg(args[0], XtNstring, &txt); - XtGetValues(tcTime, args, 1); - if(!ParseTimeControl(txt, inc, mps)) { - XtSetArg(args[0], XtNstring, ""); // erase any offending input - XtSetValues(tcTime, args, 1); - DisplayError("Bad Time-Control String", 0); - return; - } - appData.movesPerSession = mps; - appData.timeIncrement = inc; - appData.timeControl = strdup(txt); - XtSetArg(args[0], XtNstring, &txt); - XtGetValues(tcOdds1, args, 1); - appData.firstTimeOdds = first.timeOdds - = (sscanf(txt, "%d", &j) == 1 && j > 0) ? j : 1; - XtGetValues(tcOdds2, args, 1); - appData.secondTimeOdds = second.timeOdds - = (sscanf(txt, "%d", &j) == 1 && j > 0) ? j : 1; - - Reset(True, True); - TimeControlPopDown(); - return; - } +void +SetWidgetLabel (Option *opt, char *buf) +{ + Arg arg; + XtSetArg(arg, XtNlabel, (XtArgVal) buf); + XtSetValues(opt->handle, &arg, 1); } -void TimeControlPopUp() +void +SetDialogTitle (DialogClass dlg, char *title) { Arg args[16]; - Widget popup, layout, form, edit, b_ok, b_cancel, b_clas, b_inc, mess; - Window root, child; - int x, y, i, j; - int win_x, win_y; - unsigned int mask; - char def[80]; - - tcInc = (appData.timeIncrement >= 0); - tcMoves = appData.movesPerSession; tcIncrement = appData.timeIncrement; - if(!tcInc) tcIncrement = 0; - sprintf(def, "%d", tcInc ? tcIncrement : tcMoves); - - i = 0; - XtSetArg(args[i], XtNresizable, True); i++; -// XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++; - TimeControlShell = popup = - XtCreatePopupShell("TimeControl Menu", transientShellWidgetClass, - shellWidget, args, i); - - layout = - XtCreateManagedWidget(layoutName, formWidgetClass, popup, - layoutArgs, XtNumber(layoutArgs)); - - form = - XtCreateManagedWidget(layoutName, formWidgetClass, layout, - formArgs, XtNumber(formArgs)); - - j = 0; -// XtSetArg(args[j], XtNwidth, (XtArgVal) 300); j++; -// XtSetArg(args[j], XtNheight, (XtArgVal) 85); j++; - XtSetValues(popup, args, j); - - j= 0; - XtSetArg(args[j], XtNborderWidth, 1); j++; - XtSetArg(args[j], XtNeditType, XawtextEdit); j++; - XtSetArg(args[j], XtNuseStringInPlace, False); j++; - XtSetArg(args[j], XtNstring, appData.timeControl); j++; - XtSetArg(args[j], XtNdisplayCaret, False); j++; - XtSetArg(args[j], XtNtop, XtChainTop); j++; - XtSetArg(args[j], XtNbottom, XtChainTop); j++; - XtSetArg(args[j], XtNleft, XtChainLeft); j++; - XtSetArg(args[j], XtNright, XtChainRight); j++; - XtSetArg(args[j], XtNresizable, True); j++; - XtSetArg(args[j], XtNwidth, 85); j++; -// XtSetArg(args[j], XtNheight, 20); j++; - tcTime = XtCreateManagedWidget("TC", asciiTextWidgetClass, form, args, j); - XtAddEventHandler(tcTime, ButtonPressMask, False, SetFocus, (XtPointer) popup); - - j= 0; - XtSetArg(args[j], XtNlabel, tcInc ? " minutes, plus " : "minutes for each"); j++; - XtSetArg(args[j], XtNborderWidth, 0); j++; - XtSetArg(args[j], XtNfromHoriz, tcTime); j++; - XtSetArg(args[j], XtNtop, XtChainTop); j++; - XtSetArg(args[j], XtNbottom, XtChainTop); j++; - XtSetArg(args[j], XtNleft, XtChainRight); j++; - XtSetArg(args[j], XtNright, XtChainRight); j++; - // XtSetArg(args[j], XtNwidth, 100); j++; - // XtSetArg(args[j], XtNheight, 20); j++; - tcMess1 = XtCreateManagedWidget("TCtext", labelWidgetClass, form, args, j); - - j= 0; - XtSetArg(args[j], XtNborderWidth, 1); j++; - XtSetArg(args[j], XtNfromHoriz, tcMess1); j++; - XtSetArg(args[j], XtNeditType, XawtextEdit); j++; - XtSetArg(args[j], XtNuseStringInPlace, False); j++; - XtSetArg(args[j], XtNstring, def); j++; - XtSetArg(args[j], XtNdisplayCaret, False); j++; - XtSetArg(args[j], XtNtop, XtChainTop); j++; - XtSetArg(args[j], XtNbottom, XtChainTop); j++; - XtSetArg(args[j], XtNleft, XtChainRight); j++; - XtSetArg(args[j], XtNright, XtChainRight); j++; - XtSetArg(args[j], XtNresizable, True); j++; - XtSetArg(args[j], XtNwidth, 40); j++; -// XtSetArg(args[j], XtNheight, 20); j++; - tcData = XtCreateManagedWidget("MPS", asciiTextWidgetClass, form, args, j); - XtAddEventHandler(tcData, ButtonPressMask, False, SetFocus, (XtPointer) popup); - - j= 0; - XtSetArg(args[j], XtNlabel, tcInc ? "sec/move" : "moves "); j++; - XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++; - XtSetArg(args[j], XtNborderWidth, 0); j++; - XtSetArg(args[j], XtNfromHoriz, tcData); j++; - XtSetArg(args[j], XtNtop, XtChainTop); j++; - XtSetArg(args[j], XtNbottom, XtChainTop); j++; - XtSetArg(args[j], XtNleft, XtChainRight); j++; - XtSetArg(args[j], XtNright, XtChainRight); j++; -// XtSetArg(args[j], XtNwidth, 80); j++; -// XtSetArg(args[j], XtNheight, 20); j++; - tcMess2 = XtCreateManagedWidget("MPStext", labelWidgetClass, - form, args, j); - - j= 0; - XtSetArg(args[j], XtNborderWidth, 1); j++; - XtSetArg(args[j], XtNfromVert, tcTime); j++; - XtSetArg(args[j], XtNeditType, XawtextEdit); j++; - XtSetArg(args[j], XtNuseStringInPlace, False); j++; - XtSetArg(args[j], XtNstring, "1"); j++; - XtSetArg(args[j], XtNdisplayCaret, False); j++; - XtSetArg(args[j], XtNtop, XtChainTop); j++; - XtSetArg(args[j], XtNbottom, XtChainTop); j++; - XtSetArg(args[j], XtNleft, XtChainLeft); j++; - XtSetArg(args[j], XtNright, XtChainLeft); j++; - XtSetArg(args[j], XtNresizable, True); j++; - XtSetArg(args[j], XtNwidth, 40); j++; -// XtSetArg(args[j], XtNheight, 20); j++; - tcOdds1 = XtCreateManagedWidget("Odds1", asciiTextWidgetClass, form, args, j); - XtAddEventHandler(tcOdds1, ButtonPressMask, False, SetFocus, (XtPointer) popup); - - j= 0; - XtSetArg(args[j], XtNborderWidth, 1); j++; - XtSetArg(args[j], XtNfromVert, tcTime); j++; - XtSetArg(args[j], XtNfromHoriz, tcOdds1); j++; - XtSetArg(args[j], XtNeditType, XawtextEdit); j++; - XtSetArg(args[j], XtNuseStringInPlace, False); j++; - XtSetArg(args[j], XtNstring, "1"); j++; - XtSetArg(args[j], XtNdisplayCaret, False); j++; - XtSetArg(args[j], XtNtop, XtChainTop); j++; - XtSetArg(args[j], XtNbottom, XtChainTop); j++; - XtSetArg(args[j], XtNleft, XtChainLeft); j++; - XtSetArg(args[j], XtNright, XtChainLeft); j++; - XtSetArg(args[j], XtNresizable, True); j++; - XtSetArg(args[j], XtNwidth, 40); j++; -// XtSetArg(args[j], XtNheight, 20); j++; - tcOdds2 = XtCreateManagedWidget("Odds2", asciiTextWidgetClass, form, args, j); - XtAddEventHandler(tcOdds2, ButtonPressMask, False, SetFocus, (XtPointer) popup); - - j= 0; - XtSetArg(args[j], XtNlabel, "Engine #1 and #2 Time-Odds Factors"); j++; - XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++; - XtSetArg(args[j], XtNborderWidth, 0); j++; - XtSetArg(args[j], XtNfromVert, tcTime); j++; - XtSetArg(args[j], XtNfromHoriz, tcOdds2); j++; - XtSetArg(args[j], XtNtop, XtChainTop); j++; - XtSetArg(args[j], XtNbottom, XtChainTop); j++; - XtSetArg(args[j], XtNleft, XtChainLeft); j++; - XtSetArg(args[j], XtNright, XtChainRight); j++; -// XtSetArg(args[j], XtNwidth, 200); j++; -// XtSetArg(args[j], XtNheight, 20); j++; - mess = XtCreateManagedWidget("Oddstext", labelWidgetClass, - form, args, j); - j=0; - XtSetArg(args[j], XtNfromVert, tcOdds1); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainLeft); j++; - XtSetArg(args[j], XtNright, XtChainLeft); j++; - b_clas= XtCreateManagedWidget("classical", commandWidgetClass, - form, args, j); - XtAddCallback(b_clas, XtNcallback, TimeControlCallback, (XtPointer) 0); + XtSetArg(args[0], XtNtitle, title); + XtSetValues(shells[dlg], args, 1); +} - j=0; - XtSetArg(args[j], XtNfromVert, tcOdds1); j++; - XtSetArg(args[j], XtNfromHoriz, b_clas); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainLeft); j++; - XtSetArg(args[j], XtNright, XtChainLeft); j++; - b_inc = XtCreateManagedWidget("incremental", commandWidgetClass, - form, args, j); - XtAddCallback(b_inc, XtNcallback, TimeControlCallback, (XtPointer) 0); +void +LoadListBox (Option *opt, char *emptyText) +{ + static char *dummyList[2]; + dummyList[0] = emptyText; // empty listboxes tend to crash X, so display user-supplied warning string instead + XawListChange(opt->handle, *(char*)opt->target ? opt->target : dummyList, 0, 0, True); +} - j=0; - XtSetArg(args[j], XtNfromVert, tcOdds1); j++; - XtSetArg(args[j], XtNfromHoriz, tcData); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainRight); j++; - XtSetArg(args[j], XtNright, XtChainRight); j++; - b_ok= XtCreateManagedWidget(" OK ", commandWidgetClass, - form, args, j); - XtAddCallback(b_ok, XtNcallback, TimeControlCallback, (XtPointer) 0); +int +ReadScroll (Option *opt, float *top, float *bottom) +{ // retreives fractions of top and bottom of thumb + Arg args[16]; + Widget w = XtParent(opt->handle); // viewport + Widget v = XtNameToWidget(w, "vertical"); + int j=0; + float h; + if(!v) return FALSE; // no scroll bar + XtSetArg(args[j], XtNshown, &h); j++; + XtSetArg(args[j], XtNtopOfThumb, top); j++; + XtGetValues(v, args, j); + *bottom = *top + h; + return TRUE; +} - j=0; - XtSetArg(args[j], XtNfromVert, tcOdds1); j++; - XtSetArg(args[j], XtNfromHoriz, b_ok); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainRight); j++; - XtSetArg(args[j], XtNright, XtChainRight); j++; - b_cancel= XtCreateManagedWidget("cancel", commandWidgetClass, - form, args, j); - XtAddCallback(b_cancel, XtNcallback, TimeControlPopDown, (XtPointer) 0); +void +SetScroll (Option *opt, float f) +{ // sets top of thumb to given fraction + static char *params[3] = { "", "Continuous", "Proportional" }; + static XEvent event; + Widget w = XtParent(opt->handle); // viewport + Widget v = XtNameToWidget(w, "vertical"); + if(!v) return; // no scroll bar + XtCallActionProc(v, "StartScroll", &event, params+1, 1); + XawScrollbarSetThumb(v, f, -1.0); + XtCallActionProc(v, "NotifyThumb", &event, params, 0); +// XtCallActionProc(v, "NotifyScroll", &event, params+2, 1); + XtCallActionProc(v, "EndScroll", &event, params, 0); +} - XtRealizeWidget(popup); - CatchDeleteWindow(popup, "TimeControlPopDown"); - - XQueryPointer(xDisplay, xBoardWindow, &root, &child, - &x, &y, &win_x, &win_y, &mask); - - XtSetArg(args[0], XtNx, x - 10); - XtSetArg(args[1], XtNy, y - 30); - XtSetValues(popup, args, 2); - - XtPopup(popup, XtGrabExclusive); - TimeControlUp = True; - - previous = NULL; - SetFocus(tcTime, popup, (XEvent*) NULL, False); -// XtSetKeyboardFocus(popup, tcTime); +void +HighlightListBoxItem (Option *opt, int nr) +{ + XawListHighlight(opt->handle, nr); } -void TimeControlProc(w, event, prms, nprms) - Widget w; - XEvent *event; - String *prms; - Cardinal *nprms; +void +HighlightWithScroll (Option *opt, int sel, int max) { - TimeControlPopUp(); + float top, bottom, f, g; + HighlightListBoxItem(opt, sel); + if(!ReadScroll(opt, &top, &bottom)) return; // no scroll bar + bottom = bottom*max - 1.f; + f = g = top; + top *= max; + if(sel > (top + 3*bottom)/4) f = (sel - 0.75f*(bottom-top))/max; else + if(sel < (3*top + bottom)/4) f = (sel - 0.25f*(bottom-top))/max; + if(f < 0.f) f = 0.; if(f + 1.f/max > 1.f) f = 1. - 1./max; + if(f != g) SetScroll(opt, f); } -//--------------------------- Engine-Options Menu Popup ---------------------------------- -int EngineUp; -Widget EngineShell; -extern int adjudicateLossThreshold; +int +SelectedListBoxItem (Option *opt) +{ + XawListReturnStruct *rs; + rs = XawListShowCurrent(opt->handle); + return rs->list_index; +} -Widget engDrawMoves, engThreshold, engRule, engRepeat; +void +FocusOnWidget (Option *opt, DialogClass dlg) +{ + UnCaret(); + XtSetKeyboardFocus(shells[dlg], opt->handle); +} -void EnginePopDown() +void +SetIconName (DialogClass dlg, char *name) { - if (!EngineUp) return; - XtPopdown(EngineShell); - XtDestroyWidget(EngineShell); - EngineUp = False; - ModeHighlight(); + Arg args[16]; + int j = 0; + XtSetArg(args[j], XtNiconName, (XtArgVal) name); j++; +// XtSetArg(args[j], XtNtitle, (XtArgVal) name); j++; + XtSetValues(shells[dlg], args, j); } -int ReadToggle(Widget w) +static void +CheckCallback (Widget ww, XtPointer client_data, XEvent *event, Boolean *b) { - Arg args; Boolean res; + int s, data = (intptr_t) client_data; + Option *opt = dialogOptions[data >> 8] + (data & 255); - XtSetArg(args, XtNstate, &res); - XtGetValues(w, &args, 1); + if(opt->type == Label) { ((ButtonCallback*) opt->target)(data&255); return; } - return res; + GetWidgetState(opt, &s); + SetWidgetState(opt, !s); } -Widget w1, w2, w3, w4, w5, w6, w7, w8; - -void EngineCallback(w, client_data, call_data) - Widget w; - XtPointer client_data, call_data; +static void +SpinCallback (Widget w, XtPointer client_data, XtPointer call_data) { - String name; - Widget s2; + String name, val; Arg args[16]; - char buf[80]; - int j; - + char buf[MSG_SIZ], *p; + int j = 0; // Initialisation is necessary because the text value may be non-numeric causing the scanf conversion to fail + int data = (intptr_t) client_data; + Option *opt = dialogOptions[data >> 8] + (data & 255); + XtSetArg(args[0], XtNlabel, &name); XtGetValues(w, args, 1); - - if (strcmp(name, "OK") == 0) { - // read all switches - appData.periodicUpdates = ReadToggle(w1); -// appData.hideThinkingFromHuman = ReadToggle(w2); - appData.firstScoreIsAbsolute = ReadToggle(w3); - appData.secondScoreIsAbsolute = ReadToggle(w4); - appData.testClaims = ReadToggle(w5); - appData.checkMates = ReadToggle(w6); - appData.materialDraws = ReadToggle(w7); - appData.trivialDraws = ReadToggle(w8); - - // adjust setting in other menu for duplicates - // (perhaps duplicates should be removed from general Option Menu?) -// XtSetArg(args[0], XtNleftBitmap, appData.showThinking ? xMarkPixmap : None); -// XtSetValues(XtNameToWidget(menuBarWidget, -// "menuOptions.Show Thinking"), args, 1); - - // read out numeric controls, simply ignore bad formats for now - XtSetArg(args[0], XtNstring, &name); - XtGetValues(engDrawMoves, args, 1); - if(sscanf(name, "%d", &j) == 1) appData.adjudicateDrawMoves = j; - XtGetValues(engThreshold, args, 1); - if(sscanf(name, "%d", &j) == 1) - adjudicateLossThreshold = appData.adjudicateLossThreshold = -j; // inverted! - XtGetValues(engRule, args, 1); - if(sscanf(name, "%d", &j) == 1) appData.ruleMoves = j; - XtGetValues(engRepeat, args, 1); - if(sscanf(name, "%d", &j) == 1) appData.drawRepeats = j; - - EnginePopDown(); - ShowThinkingEvent(); // [HGM] thinking: score adjudication might need thinking output - return; - } + + GetWidgetText(opt, &val); + sscanf(val, "%d", &j); + if (strcmp(name, _("browse")) == 0) { + char *q=val, *r; + for(r = ""; *q; q++) if(*q == '.') r = q; else if(*q == '/') r = ""; // last dot after last slash + if(!strcmp(r, "") && !currentCps && opt->type == FileName && opt->textValue) + r = opt->textValue; + Browse(data>>8, opt->name, NULL, r, opt->type == PathName, "", &p, (FILE**) opt); + return; + } else + if (strcmp(name, "+") == 0) { + if(++j > opt->max) return; + } else + if (strcmp(name, "-") == 0) { + if(--j < opt->min) return; + } else return; + snprintf(buf, MSG_SIZ, "%d", j); + SetWidgetText(opt, buf, TransientDlg); } -void EnginePopUp() +static void +ComboSelect (Widget w, caddr_t addr, caddr_t index) // callback for all combo items { Arg args[16]; - Widget popup, layout, form, edit, b_ok, b_cancel, b_clas, b_inc, s1; - Window root, child; - int x, y, i, j, width; - int win_x, win_y; - unsigned int mask; - char def[80]; - - tcInc = (appData.timeIncrement >= 0); - tcMoves = appData.movesPerSession; tcIncrement = appData.timeIncrement; - if(!tcInc) tcIncrement = 0; - sprintf(def, "%d", tcInc ? tcIncrement : tcMoves); - - i = 0; - XtSetArg(args[i], XtNresizable, True); i++; -// XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++; - EngineShell = popup = - XtCreatePopupShell("Adjudications", transientShellWidgetClass, - shellWidget, args, i); - - layout = - XtCreateManagedWidget(layoutName, formWidgetClass, popup, - layoutArgs, XtNumber(layoutArgs)); - - form = - XtCreateManagedWidget(layoutName, formWidgetClass, layout, - formArgs, XtNumber(formArgs)); - - j = 0; -// XtSetArg(args[j], XtNwidth, (XtArgVal) 250); j++; -// XtSetArg(args[j], XtNheight, (XtArgVal) 400); j++; -// XtSetValues(popup, args, j); - - j = 0; -// XtSetArg(args[j], XtNwidth, (XtArgVal) 250); j++; -// XtSetArg(args[j], XtNheight, (XtArgVal) 20); j++; - XtSetArg(args[j], XtNleft, (XtArgVal) XtChainLeft); j++; - XtSetArg(args[j], XtNright, (XtArgVal) XtChainRight); j++; - XtSetArg(args[j], XtNstate, appData.periodicUpdates); j++; -// XtSetArg(args[j], XtNjustify, (XtArgVal) XtJustifyLeft); j++; - w1 = XtCreateManagedWidget("Periodic Updates (Analysis Mode)", toggleWidgetClass, form, args, j); - - XtSetArg(args[j], XtNwidth, (XtArgVal) &width); - XtGetValues(w1, &args[j], 1); - -// XtSetArg(args[j-1], XtNfromVert, (XtArgVal) w1); -// XtSetArg(args[j-3], XtNstate, appData.hideThinkingFromHuman); -// w2 = XtCreateManagedWidget("Hide Thinking from Human", toggleWidgetClass, form, args, j); - - XtSetArg(args[j], XtNwidth, (XtArgVal) width); j++; - XtSetArg(args[j-2], XtNstate, appData.firstScoreIsAbsolute); - XtSetArg(args[j], XtNfromVert, (XtArgVal) w1); j++; - w3 = XtCreateManagedWidget("Engine #1 Score is Absolute", toggleWidgetClass, form, args, j); - - XtSetArg(args[j-1], XtNfromVert, (XtArgVal) w3); - XtSetArg(args[j-3], XtNstate, appData.secondScoreIsAbsolute); - w4 = XtCreateManagedWidget("Engine #2 Score is Absolute", toggleWidgetClass, form, args, j); - - s1 = XtCreateManagedWidget("\nEngine-Engine Adjudications:", labelWidgetClass, form, args, 3); - - XtSetArg(args[j-1], XtNfromVert, (XtArgVal) s1); - XtSetArg(args[j-3], XtNstate, appData.testClaims); - w5 = XtCreateManagedWidget("Verify Engine Result Claims", toggleWidgetClass, form, args, j); - - XtSetArg(args[j-1], XtNfromVert, (XtArgVal) w5); - XtSetArg(args[j-3], XtNstate, appData.checkMates); - w6 = XtCreateManagedWidget("Detect All Mates", toggleWidgetClass, form, args, j); - - XtSetArg(args[j-1], XtNfromVert, (XtArgVal) w6); - XtSetArg(args[j-3], XtNstate, appData.materialDraws); - w7 = XtCreateManagedWidget("Draw when Insuff. Mating Material", toggleWidgetClass, form, args, j); - - XtSetArg(args[j-1], XtNfromVert, (XtArgVal) w7); - XtSetArg(args[j-3], XtNstate, appData.trivialDraws); - w8 = XtCreateManagedWidget("Adjudicate Trivial Draws", toggleWidgetClass, form, args, j); - - XtSetArg(args[0], XtNfromVert, (XtArgVal) w4); - XtSetArg(args[1], XtNborderWidth, (XtArgVal) 0); - XtSetValues(s1, args, 2); - - sprintf(def, "%d", appData.adjudicateDrawMoves); - j= 0; - XtSetArg(args[j], XtNborderWidth, 1); j++; - XtSetArg(args[j], XtNfromVert, w8); j++; - XtSetArg(args[j], XtNeditType, XawtextEdit); j++; - XtSetArg(args[j], XtNuseStringInPlace, False); j++; - XtSetArg(args[j], XtNstring, def); j++; - XtSetArg(args[j], XtNdisplayCaret, False); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainLeft); j++; - XtSetArg(args[j], XtNright, XtChainLeft); j++; - XtSetArg(args[j], XtNresizable, True); j++; - XtSetArg(args[j], XtNwidth, 60); j++; -// XtSetArg(args[j], XtNheight, 20); j++; - engDrawMoves = XtCreateManagedWidget("Length", asciiTextWidgetClass, form, args, j); - XtAddEventHandler(engDrawMoves, ButtonPressMask, False, SetFocus, (XtPointer) popup); - - j= 0; - XtSetArg(args[j], XtNlabel, " moves maximum, then draw"); j++; - XtSetArg(args[j], XtNjustify, (XtArgVal) XtJustifyLeft); j++; - XtSetArg(args[j], XtNborderWidth, 0); j++; - XtSetArg(args[j], XtNfromVert, w8); j++; - XtSetArg(args[j], XtNfromHoriz, engDrawMoves); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainLeft); j++; - XtSetArg(args[j], XtNright, XtChainLeft); j++; -// XtSetArg(args[j], XtNwidth, 170); j++; -// XtSetArg(args[j], XtNheight, 20); j++; - tcMess1 = XtCreateManagedWidget("TCtext", labelWidgetClass, form, args, j); - - sprintf(def, "%d", -appData.adjudicateLossThreshold); // inverted! - j= 0; - XtSetArg(args[j], XtNborderWidth, 1); j++; - XtSetArg(args[j], XtNfromVert, engDrawMoves); j++; - XtSetArg(args[j], XtNeditType, XawtextEdit); j++; - XtSetArg(args[j], XtNuseStringInPlace, False); j++; - XtSetArg(args[j], XtNstring, def); j++; - XtSetArg(args[j], XtNdisplayCaret, False); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainLeft); j++; - XtSetArg(args[j], XtNright, XtChainLeft); j++; - XtSetArg(args[j], XtNresizable, True); j++; - XtSetArg(args[j], XtNwidth, 60); j++; -// XtSetArg(args[j], XtNheight, 20); j++; - engThreshold = XtCreateManagedWidget("Threshold", asciiTextWidgetClass, form, args, j); - XtAddEventHandler(engThreshold, ButtonPressMask, False, SetFocus, (XtPointer) popup); - - j= 0; - XtSetArg(args[j], XtNlabel, "-centiPawn lead is win"); j++; - XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++; - XtSetArg(args[j], XtNborderWidth, 0); j++; - XtSetArg(args[j], XtNfromVert, engDrawMoves); j++; - XtSetArg(args[j], XtNfromHoriz, engThreshold); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainLeft); j++; - XtSetArg(args[j], XtNright, XtChainLeft); j++; -// XtSetArg(args[j], XtNwidth, 150); j++; -// XtSetArg(args[j], XtNheight, 20); j++; - tcMess2 = XtCreateManagedWidget("MPStext", labelWidgetClass, form, args, j); - - sprintf(def, "%d", appData.ruleMoves); - j= 0; - XtSetArg(args[j], XtNborderWidth, 1); j++; - XtSetArg(args[j], XtNfromVert, engThreshold); j++; - XtSetArg(args[j], XtNeditType, XawtextEdit); j++; - XtSetArg(args[j], XtNuseStringInPlace, False); j++; - XtSetArg(args[j], XtNstring, def); j++; - XtSetArg(args[j], XtNdisplayCaret, False); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainLeft); j++; - XtSetArg(args[j], XtNright, XtChainLeft); j++; - XtSetArg(args[j], XtNresizable, True); j++; - XtSetArg(args[j], XtNwidth, 30); j++; -// XtSetArg(args[j], XtNheight, 20); j++; - engRule = XtCreateManagedWidget("Rule", asciiTextWidgetClass, form, args, j); - XtAddEventHandler(engRule, ButtonPressMask, False, SetFocus, (XtPointer) popup); - - j= 0; - XtSetArg(args[j], XtNlabel, "-move rule applied"); j++; - XtSetArg(args[j], XtNjustify, (XtArgVal) XtJustifyLeft); j++; - XtSetArg(args[j], XtNborderWidth, 0); j++; - XtSetArg(args[j], XtNfromVert, engThreshold); j++; - XtSetArg(args[j], XtNfromHoriz, engRule); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainLeft); j++; - XtSetArg(args[j], XtNright, XtChainLeft); j++; -// XtSetArg(args[j], XtNwidth, 130); j++; -// XtSetArg(args[j], XtNheight, 20); j++; - tcMess1 = XtCreateManagedWidget("TCtext", labelWidgetClass, form, args, j); - - sprintf(def, "%d", appData.drawRepeats); - j= 0; - XtSetArg(args[j], XtNborderWidth, 1); j++; - XtSetArg(args[j], XtNfromVert, engRule); j++; - XtSetArg(args[j], XtNeditType, XawtextEdit); j++; - XtSetArg(args[j], XtNuseStringInPlace, False); j++; - XtSetArg(args[j], XtNstring, def); j++; - XtSetArg(args[j], XtNdisplayCaret, False); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainLeft); j++; - XtSetArg(args[j], XtNright, XtChainLeft); j++; - XtSetArg(args[j], XtNresizable, True); j++; - XtSetArg(args[j], XtNwidth, 30); j++; -// XtSetArg(args[j], XtNheight, 20); j++; - engRepeat = XtCreateManagedWidget("Repeats", asciiTextWidgetClass, form, args, j); - XtAddEventHandler(engRepeat, ButtonPressMask, False, SetFocus, (XtPointer) popup); - - j= 0; - XtSetArg(args[j], XtNlabel, "-fold repeat is draw"); j++; - XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++; - XtSetArg(args[j], XtNborderWidth, 0); j++; - XtSetArg(args[j], XtNfromVert, engRule); j++; - XtSetArg(args[j], XtNfromHoriz, engRepeat); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainLeft); j++; - XtSetArg(args[j], XtNright, XtChainLeft); j++; -// XtSetArg(args[j], XtNwidth, 130); j++; -// XtSetArg(args[j], XtNheight, 20); j++; - tcMess2 = XtCreateManagedWidget("MPStext", labelWidgetClass, form, args, j); + Option *opt = dialogOptions[((intptr_t)addr)>>24]; // applicable option list + int i = ((intptr_t)addr)>>16 & 255; // option number + int j = 0xFFFF & (intptr_t) addr; - j=0; - XtSetArg(args[j], XtNfromVert, engRepeat); j++; - XtSetArg(args[j], XtNfromHoriz, tcMess2); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainRight); j++; - XtSetArg(args[j], XtNright, XtChainRight); j++; - b_ok= XtCreateManagedWidget("OK", commandWidgetClass, form, args, j); - XtAddCallback(b_ok, XtNcallback, EngineCallback, (XtPointer) 0); + values[i] = j; // store selected value in Option struct, for retrieval at OK - j=0; - XtSetArg(args[j], XtNfromVert, engRepeat); j++; - XtSetArg(args[j], XtNfromHoriz, b_ok); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainRight); j++; - XtSetArg(args[j], XtNright, XtChainRight); j++; - b_cancel= XtCreateManagedWidget("cancel", commandWidgetClass, - form, args, j); - XtAddCallback(b_cancel, XtNcallback, EnginePopDown, (XtPointer) 0); + if(opt[i].type == Graph || opt[i].min & COMBO_CALLBACK && (!currentCps || shellUp[BrowserDlg])) { + ((ButtonCallback*) opt[i].target)(i); + return; + } - XtRealizeWidget(popup); - CatchDeleteWindow(popup, "EnginePopDown"); - - XQueryPointer(xDisplay, xBoardWindow, &root, &child, - &x, &y, &win_x, &win_y, &mask); - - XtSetArg(args[0], XtNx, x - 10); - XtSetArg(args[1], XtNy, y - 30); - XtSetValues(popup, args, 2); - - XtPopup(popup, XtGrabExclusive); - EngineUp = True; - - previous = NULL; - SetFocus(engThreshold, popup, (XEvent*) NULL, False); + if(opt[i].min & NO_GETTEXT) + XtSetArg(args[0], XtNlabel, ((char**)opt[i].choice)[j]); + else + XtSetArg(args[0], XtNlabel, _(((char**)opt[i].choice)[j])); + + XtSetValues(opt[i].handle, args, 1); } -void EngineMenuProc(w, event, prms, nprms) - Widget w; - XEvent *event; - String *prms; - Cardinal *nprms; +Widget +CreateMenuItem (Widget menu, char *msg, XtCallbackProc CB, int n) { - EnginePopUp(); + int j=0; + Widget entry; + Arg args[16]; + XtSetArg(args[j], XtNleftMargin, 20); j++; + XtSetArg(args[j], XtNrightMargin, 20); j++; + if(!strcmp(msg, "----")) { XtCreateManagedWidget(msg, smeLineObjectClass, menu, args, j); return NULL; } + XtSetArg(args[j], XtNlabel, msg); + entry = XtCreateManagedWidget("item", smeBSBObjectClass, menu, args, j+1); + XtAddCallback(entry, XtNcallback, CB, (caddr_t)(intptr_t) n); + return entry; } -//--------------------------- New-Variant Menu PopUp ----------------------------------- -struct NewVarButton { - char *name; - char *color; - Widget handle; - VariantClass variant; -}; +static Widget +CreateComboPopup (Widget parent, Option *opt, int n, int fromList, int def) +{ // fromList determines if the item texts are taken from a list of strings, or from a menu table + int i; + Widget menu, entry; + Arg arg; + MenuItem *mb = (MenuItem *) opt->choice; + char **list = (char **) opt->choice; + + if(list[0] == NULL) return NULL; // avoid empty menus, as they cause crash + menu = XtCreatePopupShell(opt->name, simpleMenuWidgetClass, parent, NULL, 0); + + for (i=0; 1; i++) + { + char *msg = fromList ? list[i] : mb[i].string; + if(!msg) break; + entry = CreateMenuItem(menu, opt->min & NO_GETTEXT ? msg : _(msg), (XtCallbackProc) ComboSelect, (n<<16)+i); + if(!fromList) mb[i].handle = (void*) entry; // save item ID, for enabling / checkmarking + if(i==def) { + XtSetArg(arg, XtNpopupOnEntry, entry); + XtSetValues(menu, &arg, 1); + } + } + return menu; +} -struct NewVarButton buttonDesc[] = { - {"normal", "#FFFFFF", 0, VariantNormal}, - {"FRC", "#FFFFFF", 0, VariantFischeRandom}, - {"wild castle", "#FFFFFF", 0, VariantWildCastle}, - {"no castle", "#FFFFFF", 0, VariantNoCastle}, - {"knightmate", "#FFFFFF", 0, VariantKnightmate}, - {"berolina", "#FFFFFF", 0, VariantBerolina}, - {"cylinder", "#FFFFFF", 0, VariantCylinder}, - {"shatranj", "#FFFFFF", 0, VariantShatranj}, - {"atomic", "#FFFFFF", 0, VariantAtomic}, - {"two kings", "#FFFFFF", 0, VariantTwoKings}, - {"3-checks", "#FFFFFF", 0, Variant3Check}, - {"suicide", "#FFFFBF", 0, VariantSuicide}, - {"give-away", "#FFFFBF", 0, VariantGiveaway}, - {"losers", "#FFFFBF", 0, VariantLosers}, - {"fairy", "#BFBFBF", 0, VariantFairy}, - {"Superchess", "#FFBFBF", 0, VariantSuper}, - {"crazyhouse", "#FFBFBF", 0, VariantCrazyhouse}, - {"bughouse", "#FFBFBF", 0, VariantBughouse}, - {"shogi (9x9)", "#BFFFFF", 0, VariantShogi}, - {"xiangqi (9x10)", "#BFFFFF", 0, VariantXiangqi}, - {"courier (12x8)", "#BFFFBF", 0, VariantCourier}, - {"janus (10x8)", "#BFBFFF", 0, VariantJanus}, - {"Capablanca (10x8)", "#BFBFFF", 0, VariantCapablanca}, - {"CRC (10x8)", "#BFBFFF", 0, VariantCapaRandom}, -#ifdef GOTHIC - {"Gothic (10x8)", "#BFBFFF", 0, VariantGothic}, -#endif -#ifdef FALCON - {"Falcon (10x8)", "#BFBFFF", 0, VariantFalcon}, -#endif - {NULL, 0, 0, (VariantClass) 0} -}; +char moveTypeInTranslations[] = + "Return: TypeInProc(1) \n" + "Escape: TypeInProc(0) \n"; +extern char filterTranslations[]; +extern char gameListTranslations[]; +extern char memoTranslations[]; -int NewVariantUp; -Widget NewVariantShell; -void NewVariantPopDown() +char *translationTable[] = { // beware: order is essential! + historyTranslations, commentTranslations, moveTypeInTranslations, ICSInputTranslations, + filterTranslations, gameListTranslations, memoTranslations +}; + +void +AddHandler (Option *opt, int nr) { - if (!NewVariantUp) return; - XtPopdown(NewVariantShell); - XtDestroyWidget(NewVariantShell); - NewVariantUp = False; - ModeHighlight(); + XtOverrideTranslations(opt->handle, XtParseTranslationTable(translationTable[nr])); } -void NewVariantCallback(w, client_data, call_data) - Widget w; - XtPointer client_data, call_data; -{ - String name; - Widget w2; - Arg args[16]; - char buf[80]; - VariantClass v; - - XtSetArg(args[0], XtNlabel, &name); - XtGetValues(w, args, 1); - - if (strcmp(name, " OK ") == 0) { - int nr = (int) XawToggleGetCurrent(buttonDesc[0].handle) - 1; - if(nr < 0) return; - v = buttonDesc[nr].variant; - if(!appData.noChessProgram) { - char *name = VariantName(v), buf[MSG_SIZ]; - if (first.protocolVersion > 1 && StrStr(first.variants, name) == NULL) { - /* [HGM] in protocol 2 we check if variant is suported by engine */ - sprintf(buf, "Variant %s not supported by %s", name, first.tidy); - DisplayError(buf, 0); -// NewVariantPopDown(); - return; /* ignore OK if first engine does not support it */ - } else - if (second.initDone && second.protocolVersion > 1 && StrStr(second.variants, name) == NULL) { - sprintf(buf, "Warning: second engine (%s) does not support this!", second.tidy); - DisplayError(buf, 0); /* use of second engine is optional; only warn user */ - } - } +//----------------------------Generic dialog -------------------------------------------- + +// cloned from Engine Settings dialog (and later merged with it) + +Widget shells[NrOfDialogs]; +DialogClass parents[NrOfDialogs]; +WindowPlacement *wp[NrOfDialogs] = { // Beware! Order must correspond to DialogClass enum + NULL, &wpComment, &wpTags, NULL, NULL, NULL, NULL, &wpMoveHistory, &wpGameList, &wpEngineOutput, &wpEvalGraph, + NULL, NULL, NULL, NULL, /*&wpMain*/ NULL +}; + +int +DialogExists (DialogClass n) +{ // accessor for use in back-end + return shells[n] != NULL; +} - gameInfo.variant = v; - appData.variant = VariantName(v); +void +RaiseWindow (DialogClass dlg) +{ + static XEvent xev; + Window root = RootWindow(xDisplay, DefaultScreen(xDisplay)); + Atom atom = XInternAtom (xDisplay, "_NET_ACTIVE_WINDOW", False); + + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.display = xDisplay; + xev.xclient.window = XtWindow(shells[dlg]); + xev.xclient.message_type = atom; + xev.xclient.format = 32; + xev.xclient.data.l[0] = 1; + xev.xclient.data.l[1] = CurrentTime; + + XSendEvent (xDisplay, + root, False, + SubstructureRedirectMask | SubstructureNotifyMask, + &xev); + + XFlush(xDisplay); + XSync(xDisplay, False); +} - shuffleOpenings = FALSE; /* [HGM] shuffle: possible shuffle reset when we switch */ - startedFromPositionFile = FALSE; /* [HGM] loadPos: no longer valid in new variant */ - appData.pieceToCharTable = NULL; - Reset(True, True); - NewVariantPopDown(); - return; +int +PopDown (DialogClass n) +{ // pops down any dialog created by GenericPopUp (or returns False if it wasn't up), unmarks any associated marked menu + int j; + Arg args[10]; + Dimension windowH, windowW; Position windowX, windowY; + if (!shellUp[n] || !shells[n]) return 0; + if(n && wp[n]) { // remember position + j = 0; + XtSetArg(args[j], XtNx, &windowX); j++; + XtSetArg(args[j], XtNy, &windowY); j++; + XtSetArg(args[j], XtNheight, &windowH); j++; + XtSetArg(args[j], XtNwidth, &windowW); j++; + XtGetValues(shells[n], args, j); + wp[n]->x = windowX; + wp[n]->x = windowY; + wp[n]->width = windowW; + wp[n]->height = windowH; } + previous = NULL; + XtPopdown(shells[n]); + shellUp[n]--; // count rather than clear + if(n == 0 || n >= PromoDlg) XtDestroyWidget(shells[n]), shells[n] = NULL; + if(marked[n]) { + MarkMenuItem(marked[n], False); + marked[n] = NULL; + } + if(!n && n != BrowserDlg) currentCps = NULL; // if an Engine Settings dialog was up, we must be popping it down now + currentOption = dialogOptions[TransientDlg]; // just in case a transient dialog was up (to allow its check and combo callbacks to work) + RaiseWindow(parents[n]); + if(parents[n] == BoardWindow) XtSetKeyboardFocus(shellWidget, formWidget); + return 1; +} + +void +GenericPopDown (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ // to cause popdown through a translation (Delete Window button!) + int dlg = atoi(prms[0]); + Widget sh = shells[dlg]; + if(shellUp[BrowserDlg] && dlg != BrowserDlg || dialogError) return; // prevent closing dialog when it has an open file-browse daughter + shells[dlg] = w; + PopDown(dlg); + shells[dlg] = sh; // restore } -void NewVariantPopUp() +int +AppendText (Option *opt, char *s) { - Arg args[16]; - Widget popup, layout, dialog, edit, form, last = NULL, b_ok, b_cancel; - Window root, child; - int x, y, i, j; - int win_x, win_y; - unsigned int mask; - char def[80]; - XrmValue vFrom, vTo; + XawTextBlock t; + char *v; + int len; + GetWidgetText(opt, &v); + len = strlen(v); + t.ptr = s; t.firstPos = 0; t.length = strlen(s); t.format = XawFmt8Bit; + XawTextReplace(opt->handle, len, len, &t); + return len; +} - i = 0; - XtSetArg(args[i], XtNresizable, True); i++; -// XtSetArg(args[i], XtNwidth, 250); i++; -// XtSetArg(args[i], XtNheight, 300); i++; - NewVariantShell = popup = - XtCreatePopupShell("NewVariant Menu", transientShellWidgetClass, - shellWidget, args, i); - - layout = - XtCreateManagedWidget(layoutName, formWidgetClass, popup, - layoutArgs, XtNumber(layoutArgs)); - - form = - XtCreateManagedWidget("form", formWidgetClass, layout, - formArgs, XtNumber(formArgs)); - - for(i = 0; buttonDesc[i].name != NULL; i++) { +void +SetColor (char *colorName, Option *box) +{ // sets the color of a widget + Arg args[5]; Pixel buttonColor; + XrmValue vFrom, vTo; if (!appData.monoMode) { - vFrom.addr = (caddr_t) buttonDesc[i].color; - vFrom.size = strlen(buttonDesc[i].color); + vFrom.addr = (caddr_t) colorName; + vFrom.size = strlen(colorName); XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo); if (vTo.addr == NULL) { buttonColor = (Pixel) -1; } else { buttonColor = *(Pixel *) vTo.addr; } - } - - j = 0; - XtSetArg(args[j], XtNradioGroup, last); j++; - XtSetArg(args[j], XtNwidth, 125); j++; -// XtSetArg(args[j], XtNheight, 16); j++; - XtSetArg(args[j], XtNfromVert, i == 15 ? NULL : last); j++; - XtSetArg(args[j], XtNfromHoriz, i < 15 ? NULL : buttonDesc[i-15].handle); j++; - XtSetArg(args[j], XtNradioData, i+1); j++; - XtSetArg(args[j], XtNbackground, buttonColor); j++; - XtSetArg(args[j], XtNstate, gameInfo.variant == buttonDesc[i].variant); j++; - buttonDesc[i].handle = last = - XtCreateManagedWidget(buttonDesc[i].name, toggleWidgetClass, form, args, j); - } - - j=0; - XtSetArg(args[j], XtNfromVert, buttonDesc[12].handle); j++; - XtSetArg(args[j], XtNfromHoriz, buttonDesc[12].handle); j++; - XtSetArg(args[j], XtNheight, 35); j++; -// XtSetArg(args[j], XtNwidth, 60); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainRight); j++; - XtSetArg(args[j], XtNright, XtChainRight); j++; - b_cancel= XtCreateManagedWidget("CANCEL", commandWidgetClass, form, args, j); - XtAddCallback(b_cancel, XtNcallback, NewVariantPopDown, (XtPointer) 0); - - j=0; - XtSetArg(args[j], XtNfromHoriz, b_cancel); j++; - XtSetArg(args[j], XtNfromVert, buttonDesc[12].handle); j++; - XtSetArg(args[j], XtNheight, 35); j++; -// XtSetArg(args[j], XtNwidth, 60); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainRight); j++; - XtSetArg(args[j], XtNright, XtChainRight); j++; - b_ok= XtCreateManagedWidget(" OK ", commandWidgetClass, form, args, j); - XtAddCallback(b_ok, XtNcallback, NewVariantCallback, (XtPointer) 0); - - XtRealizeWidget(popup); - CatchDeleteWindow(popup, "NewVariantPopDown"); - - XQueryPointer(xDisplay, xBoardWindow, &root, &child, - &x, &y, &win_x, &win_y, &mask); - - XtSetArg(args[0], XtNx, x - 10); - XtSetArg(args[1], XtNy, y - 30); - XtSetValues(popup, args, 2); - - XtPopup(popup, XtGrabExclusive); - NewVariantUp = True; + } else buttonColor = timerBackgroundPixel; + XtSetArg(args[0], XtNbackground, buttonColor);; + XtSetValues(box->handle, args, 1); } -void NewVariantProc(w, event, prms, nprms) - Widget w; - XEvent *event; - String *prms; - Cardinal *nprms; -{ - NewVariantPopUp(); +void +ColorChanged (Widget w, XtPointer data, XEvent *event, Boolean *b) +{ // for detecting a typed change in color + char buf[10]; + if ( (XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) && *buf == '\r' ) + RefreshColor((int)(intptr_t) data, 0); } -//--------------------------- UCI Menu Popup ------------------------------------------ -int UciUp; -Widget UciShell; - -struct UciControl { - char *name; - Widget handle; - void *ptr; -}; - -struct UciControl controlDesc[] = { - {"maximum nr of CPUs:", 0, &appData.smpCores}, - {"Polyglot Directory:", 0, &appData.polyglotDir}, - {"Hash Size (MB):", 0, &appData.defaultHashSize}, - {"EGTB Path:", 0, &appData.defaultPathEGTB}, - {"EGTB Cache (MB):", 0, &appData.defaultCacheSizeEGTB}, - {"Polyglot Book:", 0, &appData.polyglotBook}, - {NULL, 0, NULL}, -}; - -void UciPopDown() -{ - if (!UciUp) return; - XtPopdown(UciShell); - XtDestroyWidget(UciShell); - UciUp = False; - ModeHighlight(); -} - -void UciCallback(w, client_data, call_data) - Widget w; - XtPointer client_data, call_data; -{ - String name; +static void +GraphEventProc(Widget widget, caddr_t client_data, XEvent *event) +{ // handle expose and mouse events on Graph widget + Dimension w, h; Arg args[16]; - char buf[80]; - int oldCores = appData.smpCores, ponder = 0; - - XtSetArg(args[0], XtNlabel, &name); - XtGetValues(w, args, 1); - - if (strcmp(name, "OK") == 0) { - int nr, i, j; String name; - for(i=0; i<6; i++) { - XtSetArg(args[0], XtNstring, &name); - XtGetValues(controlDesc[i].handle, args, 1); - if(i&1) { - if(name) - *(char**) controlDesc[i].ptr = strdup(name); - } else { - if(sscanf(name, "%d", &j) == 1) - *(int*) controlDesc[i].ptr = j; + int j, button=10, f=1, sizing=0; + Option *opt, *graph = (Option *) client_data; + PointerCallback *userHandler = graph->target; + + if (!XtIsRealized(widget)) return; + + switch(event->type) { + case Expose: // make handling of expose events generic, just copying from memory buffer (->choice) to display (->textValue) + /* Get window size */ + j = 0; + XtSetArg(args[j], XtNwidth, &w); j++; + XtSetArg(args[j], XtNheight, &h); j++; + XtGetValues(widget, args, j); + + if(w < graph->max || w > graph->max + 1 || h != graph->value) { // use width fudge of 1 pixel + if(((XExposeEvent*)event)->count >= 0) { // suppress sizing on expose for ordered redraw in response to sizing. + sizing = 1; + graph->max = w; graph->value = h; // note: old values are kept if we we don't exceed width fudge + } + } else w = graph->max; + + if(sizing && ((XExposeEvent*)event)->count > 0) { graph->max = 0; return; } // don't bother if further exposure is pending during resize + if(!graph->textValue || sizing) { // create surfaces of new size for display widget + if(graph->textValue) cairo_surface_destroy((cairo_surface_t *)graph->textValue); + graph->textValue = (char*) cairo_xlib_surface_create(xDisplay, XtWindow(widget), DefaultVisual(xDisplay, 0), w, h); + } + if(sizing) { // the memory buffer was already created in GenericPopup(), + // to give drawing routines opportunity to use it before first expose event + // (which are only processed when main gets to the event loop, so after all init!) + // so only change when size is no longer good + if(graph->choice) cairo_surface_destroy((cairo_surface_t *) graph->choice); + graph->choice = (char**) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h); + break; + } + w = ((XExposeEvent*)event)->width; + if(((XExposeEvent*)event)->x + w > graph->max) w--; // cut off fudge pixel + if(w) ExposeRedraw(graph, ((XExposeEvent*)event)->x, ((XExposeEvent*)event)->y, w, ((XExposeEvent*)event)->height); + return; + case MotionNotify: + f = 0; + w = ((XButtonEvent*)event)->x; h = ((XButtonEvent*)event)->y; + break; + case ButtonRelease: + f = -1; // release indicated by negative button numbers + case ButtonPress: + w = ((XButtonEvent*)event)->x; h = ((XButtonEvent*)event)->y; + switch(((XButtonEvent*)event)->button) { + case Button1: button = 1; break; + case Button2: button = 2; break; + case Button3: button = 3; break; + case Button4: button = 4; break; + case Button5: button = 5; break; } - } - XtSetArg(args[0], XtNstate, &appData.usePolyglotBook); - XtGetValues(w1, args, 1); - XtSetArg(args[0], XtNstate, &appData.firstHasOwnBookUCI); - XtGetValues(w2, args, 1); - XtSetArg(args[0], XtNstate, &appData.secondHasOwnBookUCI); - XtGetValues(w3, args, 1); - XtSetArg(args[0], XtNstate, &ponder); - XtGetValues(w4, args, 1); - - // adjust setting in other menu for duplicates - // (perhaps duplicates should be removed from general Option Menu?) - XtSetArg(args[0], XtNleftBitmap, ponder ? xMarkPixmap : None); - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.Ponder Next Move"), args, 1); - - // make sure changes are sent to first engine by re-initializing it - // if it was already started pre-emptively at end of previous game - if(gameMode == BeginningOfGame) Reset(True, True); else { - // Some changed setting need immediate sending always. - PonderNextMoveEvent(ponder); - if(oldCores != appData.smpCores) - NewSettingEvent(False, "cores", appData.smpCores); - } - UciPopDown(); - return; } -} - -void UciPopUp() -{ - Arg args[16]; - Widget popup, layout, dialog, edit, form, b_ok, b_cancel, last = NULL, new, upperLeft; - Window root, child; - int x, y, i, j; - int win_x, win_y; - unsigned int mask; - char def[80]; - - i = 0; - XtSetArg(args[i], XtNresizable, True); i++; -// XtSetArg(args[i], XtNwidth, 300); i++; - UciShell = popup = - XtCreatePopupShell("Engine Settings", transientShellWidgetClass, - shellWidget, args, i); - - layout = - XtCreateManagedWidget(layoutName, formWidgetClass, popup, - layoutArgs, XtNumber(layoutArgs)); - - - form = - XtCreateManagedWidget("form", formWidgetClass, layout, - formArgs, XtNumber(formArgs)); - - j = 0; - XtSetArg(args[j], XtNtop, XtChainTop); j++; - XtSetArg(args[j], XtNbottom, XtChainTop); j++; - XtSetArg(args[j], XtNleft, XtChainLeft); j++; -// XtSetArg(args[j], XtNheight, 20); j++; - for(i = 0; controlDesc[i].name != NULL; i++) { - j = 3; - XtSetArg(args[j], XtNfromVert, last); j++; -// XtSetArg(args[j], XtNwidth, 130); j++; - XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++; - XtSetArg(args[j], XtNright, XtChainLeft); j++; - XtSetArg(args[j], XtNborderWidth, 0); j++; - new = XtCreateManagedWidget(controlDesc[i].name, labelWidgetClass, form, args, j); - if(i==0) upperLeft = new; - - j = 4; - XtSetArg(args[j], XtNborderWidth, 1); j++; - XtSetArg(args[j], XtNeditType, XawtextEdit); j++; - XtSetArg(args[j], XtNuseStringInPlace, False); j++; - XtSetArg(args[j], XtNdisplayCaret, False); j++; - XtSetArg(args[j], XtNright, XtChainRight); j++; - XtSetArg(args[j], XtNresizable, True); j++; - XtSetArg(args[j], XtNwidth, i&1 ? 245 : 50); j++; - if(i&1) { - XtSetArg(args[j], XtNstring, * (char**) controlDesc[i].ptr ? - * (char**) controlDesc[i].ptr : ""); j++; - } else { - sprintf(def, "%d", * (int*) controlDesc[i].ptr); - XtSetArg(args[j], XtNstring, def); j++; - } - XtSetArg(args[j], XtNfromHoriz, upperLeft); j++; - controlDesc[i].handle = last = - XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j); - XtAddEventHandler(last, ButtonPressMask, False, SetFocus, (XtPointer) popup); + button *= f; + opt = userHandler(button, w, h); + if(opt) { // user callback specifies a context menu; pop it up + XUngrabPointer(xDisplay, CurrentTime); + XtCallActionProc(widget, "XawPositionSimpleMenu", event, &(opt->name), 1); + XtPopupSpringLoaded(opt->handle); } - - j=0; - XtSetArg(args[j], XtNfromHoriz, controlDesc[0].handle); j++; - XtSetArg(args[j], XtNbottom, XtChainTop); j++; - XtSetArg(args[j], XtNtop, XtChainTop); j++; - XtSetArg(args[j], XtNleft, XtChainRight); j++; - XtSetArg(args[j], XtNright, XtChainRight); j++; - XtSetArg(args[j], XtNstate, appData.ponderNextMove); j++; - w4 = XtCreateManagedWidget("Ponder", toggleWidgetClass, form, args, j); - - j=0; - XtSetArg(args[j], XtNfromVert, last); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainLeft); j++; - XtSetArg(args[j], XtNright, XtChainLeft); j++; - b_ok = XtCreateManagedWidget("OK", commandWidgetClass, form, args, j); - XtAddCallback(b_ok, XtNcallback, UciCallback, (XtPointer) 0); - - XtSetArg(args[j], XtNfromHoriz, b_ok); j++; - b_cancel = XtCreateManagedWidget("cancel", commandWidgetClass, form, args, j); - XtAddCallback(b_cancel, XtNcallback, UciPopDown, (XtPointer) 0); - - j = 5; - XtSetArg(args[j], XtNfromHoriz, upperLeft); j++; - XtSetArg(args[j], XtNstate, appData.usePolyglotBook); j++; - w1 = XtCreateManagedWidget(" use book ", toggleWidgetClass, form, args, j); -// XtAddCallback(w1, XtNcallback, UciCallback, (XtPointer) 0); - - j = 5; - XtSetArg(args[j], XtNfromHoriz, w1); j++; - XtSetArg(args[j], XtNstate, appData.firstHasOwnBookUCI); j++; - w2 = XtCreateManagedWidget("own book 1", toggleWidgetClass, form, args, j); -// XtAddCallback(w2, XtNcallback, UciCallback, (XtPointer) 0); - - j = 5; - XtSetArg(args[j], XtNfromHoriz, w2); j++; - XtSetArg(args[j], XtNstate, appData.secondHasOwnBookUCI); j++; - w3 = XtCreateManagedWidget("own book 2", toggleWidgetClass, form, args, j); -// XtAddCallback(w3, XtNcallback, UciCallback, (XtPointer) 0); - - XtRealizeWidget(popup); - CatchDeleteWindow(popup, "UciPopDown"); - - XQueryPointer(xDisplay, xBoardWindow, &root, &child, - &x, &y, &win_x, &win_y, &mask); - - XtSetArg(args[0], XtNx, x - 10); - XtSetArg(args[1], XtNy, y - 30); - XtSetValues(popup, args, 2); - - XtPopup(popup, XtGrabExclusive); - UciUp = True; - - previous = NULL; - SetFocus(controlDesc[2].handle, popup, (XEvent*) NULL, False); -// XtSetKeyboardFocus(popup, controlDesc[1].handle); + XSync(xDisplay, False); } -void UciMenuProc(w, event, prms, nprms) - Widget w; - XEvent *event; - String *prms; - Cardinal *nprms; +void +GraphExpose (Option *opt, int x, int y, int w, int h) { - UciPopUp(); + XExposeEvent e; + if(!opt->handle) return; + e.x = x; e.y = y; e.width = w; e.height = h; e.count = -1; e.type = Expose; // count = -1: kludge to suppress sizing + GraphEventProc(opt->handle, (caddr_t) opt, (XEvent *) &e); // fake expose event } -//--------------------------- Engine-specific options menu ---------------------------------- - -int SettingsUp; -Widget SettingsShell; -int values[MAX_OPTIONS]; -ChessProgramState *currentCps; - -void SettingsPopDown() -{ - if (!SettingsUp) return; - XtPopdown(SettingsShell); - XtDestroyWidget(SettingsShell); - SettingsUp = False; - ModeHighlight(); -} - -void SpinCallback(w, client_data, call_data) - Widget w; - XtPointer client_data, call_data; -{ - String name, val; - Widget w2; +static void +GenericCallback (Widget w, XtPointer client_data, XtPointer call_data) +{ // all Buttons in a dialog (including OK, cancel) invoke this + String name; Arg args[16]; char buf[MSG_SIZ]; - int i, j; - - XtSetArg(args[0], XtNlabel, &name); - XtGetValues(w, args, 1); - - j = 0; - XtSetArg(args[0], XtNstring, &val); - XtGetValues(currentCps->option[(int)client_data].handle, args, 1); - sscanf(val, "%d", &j); - if (strcmp(name, "+") == 0) { - if(++j > currentCps->option[(int)client_data].max) return; + int data = (intptr_t) client_data; + DialogClass dlg; + Widget sh = XtParent(XtParent(XtParent(w))), oldSh; + + currentOption = dialogOptions[dlg=data>>16]; data &= 0xFFFF; + oldSh = shells[dlg]; shells[dlg] = sh; // bow to reality + if (data == 30000) { // cancel + PopDown(dlg); } else - if (strcmp(name, "-") == 0) { - if(--j < currentCps->option[(int)client_data].min) return; - } else return; - sprintf(buf, "%d", j); - XtSetArg(args[0], XtNstring, buf); - XtSetValues(currentCps->option[(int)client_data].handle, args, 1); + if (data == 30001) { // save buttons imply OK + if(GenericReadout(currentOption, -1)) PopDown(dlg); // calls OK-proc after full readout, but no popdown if it returns false + } else + + if(currentCps && dlg != BrowserDlg) { + XtSetArg(args[0], XtNlabel, &name); + XtGetValues(w, args, 1); + if(currentOption[data].type == SaveButton) GenericReadout(currentOption, -1); + snprintf(buf, MSG_SIZ, "option %s\n", name); + SendToProgram(buf, currentCps); + } else ((ButtonCallback*) currentOption[data].target)(data); + + shells[dlg] = oldSh; // in case of multiple instances, restore previous (as this one could be popped down now) } -void SettingsCallback(w, client_data, call_data) - Widget w; - XtPointer client_data, call_data; -{ - String name, val; - Widget w2; - Arg args[16]; - char buf[MSG_SIZ]; - int i, j; - - XtSetArg(args[0], XtNlabel, &name); - XtGetValues(w, args, 1); - - if (strcmp(name, "cancel") == 0) { - SettingsPopDown(); - return; - } - if (strcmp(name, "OK") == 0 || (int)client_data) { // save buttons imply OK - int nr; - - for(i=0; inrOptions; i++) { // send all options that had to be OK-ed to engine - switch(currentCps->option[i].type) { - case TextBox: - XtSetArg(args[0], XtNstring, &val); - XtGetValues(currentCps->option[i].handle, args, 1); - if(strcmp(currentCps->option[i].textValue, val)) { - strcpy(currentCps->option[i].textValue, val); - sprintf(buf, "option %s %s\n", currentCps->option[i].name, val); - SendToProgram(buf, currentCps); - } - break; - case Spin: - XtSetArg(args[0], XtNstring, &val); - XtGetValues(currentCps->option[i].handle, args, 1); - sscanf(val, "%d", &j); - if(j > currentCps->option[i].max) j = currentCps->option[i].max; - if(j < currentCps->option[i].min) j = currentCps->option[i].min; - if(currentCps->option[i].value != j) { - currentCps->option[i].value = j; - sprintf(buf, "option %s %d\n", currentCps->option[i].name, j); - SendToProgram(buf, currentCps); - } - break; - case CheckBox: - j = 0; - XtSetArg(args[0], XtNstate, &j); - XtGetValues(currentCps->option[i].handle, args, 1); - if(currentCps->option[i].value != j) { - currentCps->option[i].value = j; - sprintf(buf, "option %s %d\n", currentCps->option[i].name, j); - SendToProgram(buf, currentCps); - } - break; - case ComboBox: - if(currentCps->option[i].value != values[i]) { - currentCps->option[i].value = values[i]; - sprintf(buf, "option %s %s\n", currentCps->option[i].name, - ((char**)currentCps->option[i].textValue)[values[i]]); - SendToProgram(buf, currentCps); - } - break; +void +TabProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ // for transfering focus to the next text-edit + Option *opt; + for(opt = currentOption; opt->type != EndMark; opt++) { + if(opt->handle == w) { + while(++opt) { + if(opt->type == EndMark) opt = currentOption; // wrap + if(opt->handle == w) return; // full circle + if(opt->type == TextBox || opt->type == Spin || opt->type == Fractional || opt->type == FileName || opt->type == PathName) { + SetFocus(opt->handle, XtParent(XtParent(XtParent(w))), NULL, 0); + return; + } } } - if((int)client_data) { // send save-button command to engine - sprintf(buf, "option %s\n", name); - SendToProgram(buf, currentCps); - } - SettingsPopDown(); - return; } - sprintf(buf, "option %s\n", name); - SendToProgram(buf, currentCps); } -void ComboSelect(w, addr, index) // callback for all combo items - Widget w; - caddr_t addr; - caddr_t index; -{ +void +WheelProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ // for scrolling a widget seen through a viewport with the mouse wheel (ListBox!) + int j=0, n = atoi(prms[0]); + static char *params[3] = { "", "Continuous", "Proportional" }; Arg args[16]; - int i = ((int)addr)>>8; - int j = 255 & (int) addr; + float h, top; + Widget v; + if(!n) { // transient dialogs also use this for list-selection callback + n = prms[1][0]-'0'; + Option *opt=dialogOptions[prms[2][0]-'A'] + n; + if(opt->textValue) ((ListBoxCallback*) opt->textValue)(n, SelectedListBoxItem(opt)); + return; + } + v = XtNameToWidget(XtParent(w), "vertical"); + if(!v) return; + XtSetArg(args[j], XtNshown, &h); j++; + XtSetArg(args[j], XtNtopOfThumb, &top); j++; + XtGetValues(v, args, j); + top += 0.1f*h*n; if(top < 0.f) top = 0.; + XtCallActionProc(v, "StartScroll", event, params+1, 1); + XawScrollbarSetThumb(v, top, -1.0); + XtCallActionProc(v, "NotifyThumb", event, params, 0); +// XtCallActionProc(w, "NotifyScroll", event, params+2, 1); + XtCallActionProc(v, "EndScroll", event, params, 0); +} + +static char *oneLiner = + "Return: redraw-display() \n \ + Tab: TabProc() \n "; +static char scrollTranslations[] = + "(2): WheelProc(0 0 A) \n \ + : WheelProc(-1) \n \ + : WheelProc(1) \n "; + +static void +SqueezeIntoBox (Option *opt, int nr, int width) +{ // size buttons in bar to fit, clipping button names where necessary + int i, wtot = 0; + Dimension widths[20], oldWidths[20]; + Arg arg; + for(i=1; imin = wtot; + if(width <= 0) return; + while(wtot > width) { + int wmax=0, imax=0; + for(i=1; i wmax) wmax = widths[imax=i]; + widths[imax]--; + wtot--; + } + for(i=1; imin = wtot; +} - values[i] = j; // store in temporary, for transfer at OK - XtSetArg(args[0], XtNlabel, ((char**)currentCps->option[i].textValue)[j]); - XtSetValues(currentCps->option[i].handle, args, 1); +int +SetPositionAndSize (Arg *args, Widget leftNeigbor, Widget topNeigbor, int b, int w, int h, int chaining) +{ // sizing and positioning most widgets have in common + int j = 0; + // first position the widget w.r.t. earlier ones + if(chaining & 1) { // same row: position w.r.t. last (on current row) and lastrow + XtSetArg(args[j], XtNfromVert, topNeigbor); j++; + XtSetArg(args[j], XtNfromHoriz, leftNeigbor); j++; + } else // otherwise it goes at left margin (which is default), below the previous element + XtSetArg(args[j], XtNfromVert, leftNeigbor), j++; + // arrange chaining ('2'-bit indicates top and bottom chain the same) + if((chaining & 14) == 6) XtSetArg(args[j], XtNtop, XtChainBottom), j++; + if((chaining & 14) == 10) XtSetArg(args[j], XtNbottom, XtChainTop ), j++; + if(chaining & 4) XtSetArg(args[j], XtNbottom, XtChainBottom ), j++; + if(chaining & 8) XtSetArg(args[j], XtNtop, XtChainTop), j++; + if(chaining & 0x10) XtSetArg(args[j], XtNright, XtChainRight), j++; + if(chaining & 0x20) XtSetArg(args[j], XtNleft, XtChainRight), j++; + if(chaining & 0x40) XtSetArg(args[j], XtNright, XtChainLeft ), j++; + if(chaining & 0x80) XtSetArg(args[j], XtNleft, XtChainLeft ), j++; + // set size (if given) + if(w) XtSetArg(args[j], XtNwidth, w), j++; + if(h) XtSetArg(args[j], XtNheight, h), j++; + // color + if(!appData.monoMode) { + if(!b && appData.dialogColor[0]) XtSetArg(args[j], XtNbackground, dialogColor), j++; + if(b == 3 && appData.buttonColor[0]) XtSetArg(args[j], XtNbackground, buttonColor), j++; + } + if(b == 3) b = 1; + // border + XtSetArg(args[j], XtNborderWidth, b); j++; + return j; } -void CreateComboPopup(parent, name, n, mb) - Widget parent; - String name; - int n; - char *mb[]; -{ - int i=0, j; - Widget menu, entry; - Arg args[16]; - - menu = XtCreatePopupShell(name, simpleMenuWidgetClass, - parent, NULL, 0); - j = 0; - XtSetArg(args[j], XtNwidth, 100); j++; -// XtSetArg(args[j], XtNright, XtChainRight); j++; - while (mb[i] != NULL) { - entry = XtCreateManagedWidget(mb[i], smeBSBObjectClass, - menu, args, j); - XtAddCallback(entry, XtNcallback, - (XtCallbackProc) ComboSelect, - (caddr_t) (256*n+i)); - i++; - } -} - -void SettingsPopUp(ChessProgramState *cps) +int +GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent, int modal, int top) { - Arg args[16]; - Widget popup, layout, dialog, edit, form, oldform, last, b_ok, b_cancel; + Arg args[24]; + Widget popup, layout, dialog=NULL, edit=NULL, form, last, b_ok, b_cancel, previousPane = NULL, textField = NULL, oldForm, oldLastRow, oldForeLast; Window root, child; - int x, y, i, j; - int win_x, win_y; + int x, y, i, j, height=999, width=1, h, c, w, shrink=FALSE, stack = 0, box, chain; + int win_x, win_y, maxWidth, maxTextWidth; unsigned int mask; - char def[80], *p, *q; - - // to do: start up second engine if needed - if(!cps->initDone || !cps->nrOptions) return; // nothing to be done - currentCps = cps; + char def[MSG_SIZ], *msg, engineDlg = (currentCps != NULL && dlgNr != BrowserDlg); + static char pane[6] = "paneX"; + Widget texts[100], forelast = NULL, anchor, widest, lastrow = NULL, browse = NULL; + Dimension bWidth = 50; + + if(dlgNr < PromoDlg && shellUp[dlgNr]) return 0; // already up + if(dlgNr && dlgNr < PromoDlg && shells[dlgNr]) { // reusable, and used before (but popped down) + XtPopup(shells[dlgNr], XtGrabNone); + shellUp[dlgNr] = True; + return 0; + } - i = 0; + dialogOptions[dlgNr] = option; // make available to callback + // post currentOption globally, so Spin and Combo callbacks can already use it + // WARNING: this kludge does not work for persistent dialogs, so that these cannot have spin or combo controls! + currentOption = option; + + if(engineDlg) { // Settings popup for engine: format through heuristic + int n = currentCps->nrOptions; + if(n > 50) width = 4; else if(n>24) width = 2; else width = 1; + height = n / width + 1; + if(n && (currentOption[n-1].type == Button || currentOption[n-1].type == SaveButton)) currentOption[n].min = SAME_ROW; // OK on same line + currentOption[n].type = EndMark; currentOption[n].target = NULL; // delimit list by callback-less end mark + } + i = 0; XtSetArg(args[i], XtNresizable, True); i++; - SettingsShell = popup = - XtCreatePopupShell("Settings Menu", transientShellWidgetClass, - shellWidget, args, i); - + shells[BoardWindow] = shellWidget; parents[dlgNr] = parent; + + if(dlgNr == BoardWindow) popup = shellWidget; else + popup = shells[dlgNr] = + XtCreatePopupShell(title, !top || !appData.topLevel ? transientShellWidgetClass : topLevelShellWidgetClass, + shells[parent], args, i); + layout = XtCreateManagedWidget(layoutName, formWidgetClass, popup, layoutArgs, XtNumber(layoutArgs)); - + if(!appData.monoMode && appData.dialogColor[0]) XtSetArg(args[0], XtNbackground, dialogColor); + XtSetValues(layout, args, 1); + + for(c=0; cnrOptions; i++) { - Widget box; - switch(cps->option[i].type) { + j=0; + XtSetArg(args[j], stack ? XtNfromVert : XtNfromHoriz, previousPane); j++; + if(!appData.monoMode && appData.dialogColor[0]) XtSetArg(args[j], XtNbackground, dialogColor), j++; + XtSetValues(form, args, j); + lastrow = forelast = NULL; + previousPane = form; + + last = widest = NULL; anchor = lastrow; + for(h=0; hoption[i].value); + if(!engineDlg) option[i].value = *(int*)option[i].target; + snprintf(def, MSG_SIZ, "%d", option[i].value); case TextBox: - j=0; - XtSetArg(args[j], XtNfromVert, last); j++; - XtSetArg(args[j], XtNborderWidth, 0); j++; - XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++; - dialog = XtCreateManagedWidget(cps->option[i].name, labelWidgetClass, form, args, j); - j=0; - XtSetArg(args[j], XtNfromVert, last); j++; - XtSetArg(args[j], XtNfromHoriz, dialog); j++; - XtSetArg(args[j], XtNborderWidth, 1); j++; - XtSetArg(args[j], XtNwidth, cps->option[i].type == Spin ? 40 : 100); j++; + case FileName: + case PathName: + tBox: + if(option[i].name[0]) { // prefixed by label with option name + j = SetPositionAndSize(args, last, lastrow, 0 /* border */, + 0 /* w */, textHeight /* h */, 0xC0 /* chain to left edge */); + XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++; + XtSetArg(args[j], XtNlabel, _(option[i].name)); j++; + texts[h] = dialog = XtCreateManagedWidget(option[i].name, labelWidgetClass, form, args, j); + } else texts[h] = dialog = NULL; // kludge to position from left margin + w = option[i].type == Spin || option[i].type == Fractional ? 70 : option[i].max ? option[i].max : 205; + if(option[i].type == FileName || option[i].type == PathName) w -= 55; + j = SetPositionAndSize(args, dialog, last, 1 /* border */, + w /* w */, option[i].type == TextBox ? option[i].value : 0 /* h */, 0x91 /* chain full width */); + if(option[i].type == TextBox) { // decorations for multi-line text-edits + if(option[i].min & T_VSCRL) { XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++; } + if(option[i].min & T_HSCRL) { XtSetArg(args[j], XtNscrollHorizontal, XawtextScrollAlways); j++; } + if(option[i].min & T_FILL) { XtSetArg(args[j], XtNautoFill, True); j++; } + if(option[i].min & T_WRAP) { XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++; } + if(option[i].min & T_TOP) { XtSetArg(args[j], XtNtop, XtChainTop); j++; + if(!option[i].value) { XtSetArg(args[j], XtNbottom, XtChainTop); j++; + XtSetValues(dialog, args+j-2, 2); + } + } + } else shrink = TRUE; XtSetArg(args[j], XtNeditType, XawtextEdit); j++; XtSetArg(args[j], XtNuseStringInPlace, False); j++; XtSetArg(args[j], XtNdisplayCaret, False); j++; - XtSetArg(args[j], XtNright, XtChainRight); j++; XtSetArg(args[j], XtNresizable, True); j++; - XtSetArg(args[j], XtNstring, cps->option[i].type==Spin ? def : cps->option[i].textValue); j++; + XtSetArg(args[j], XtNinsertPosition, 9999); j++; + XtSetArg(args[j], XtNstring, option[i].type==Spin || option[i].type==Fractional ? def : + engineDlg ? option[i].textValue : *(char**)option[i].target); j++; edit = last; - cps->option[i].handle = (void*) - (last = XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j)); - XtAddEventHandler(box, ButtonPressMask, False, SetFocus, (XtPointer) popup); - if(cps->option[i].type == TextBox) break; + option[i].handle = (void*) + (textField = last = XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j)); + XtAddEventHandler(last, ButtonPressMask, False, SetFocus, (XtPointer) popup); // gets focus on mouse click + if(option[i].min == 0 || option[i].type != TextBox) + XtOverrideTranslations(last, XtParseTranslationTable(oneLiner)); // standard handler for and + + if(option[i].type == TextBox || option[i].type == Fractional) break; + // add increment and decrement controls for spin - j=0; - XtSetArg(args[j], XtNfromVert, edit); j++; - XtSetArg(args[j], XtNfromHoriz, box); j++; - XtSetArg(args[j], XtNheight, 10); j++; - XtSetArg(args[j], XtNwidth, 20); j++; - edit = XtCreateManagedWidget("+", commandWidgetClass, form, args, j); - XtAddCallback(edit, XtNcallback, SpinCallback, (XtPointer) i); - j=0; - XtSetArg(args[j], XtNfromVert, edit); j++; - XtSetArg(args[j], XtNfromHoriz, last); j++; - XtSetArg(args[j], XtNheight, 10); j++; - XtSetArg(args[j], XtNwidth, 20); j++; + if(option[i].type == FileName || option[i].type == PathName) { + msg = _("browse"); w = 0; // automatically scale to width of text + j = textHeight ? textHeight : 0; + } else { + w = 20; msg = "+"; j = textHeight/2; // spin button + } + j = SetPositionAndSize(args, last, edit, 3 /* border */, + w /* w */, j /* h */, 0x31 /* chain to right edge */); + edit = XtCreateManagedWidget(msg, commandWidgetClass, form, args, j); + XtAddCallback(edit, XtNcallback, SpinCallback, (XtPointer)(intptr_t) i + 256*dlgNr); + if(w == 0) browse = edit; + + if(option[i].type != Spin) break; + + j = SetPositionAndSize(args, last, edit, 3 /* border */, + 20 /* w */, textHeight/2 /* h */, 0x31 /* chain to right edge */); + XtSetArg(args[j], XtNvertDistance, -1); j++; last = XtCreateManagedWidget("-", commandWidgetClass, form, args, j); - XtAddCallback(last, XtNcallback, SpinCallback, (XtPointer) i); + XtAddCallback(last, XtNcallback, SpinCallback, (XtPointer)(intptr_t) i + 256*dlgNr); break; case CheckBox: - j=0; - XtSetArg(args[j], XtNfromVert, last); j++; - XtSetArg(args[j], XtNwidth, 10); j++; - XtSetArg(args[j], XtNheight, 10); j++; - XtSetArg(args[j], XtNstate, cps->option[i].value); j++; - cps->option[i].handle = (void*) - (dialog = XtCreateManagedWidget(" ", toggleWidgetClass, form, args, j)); - j=0; - XtSetArg(args[j], XtNfromVert, last); j++; - XtSetArg(args[j], XtNfromHoriz, dialog); j++; - XtSetArg(args[j], XtNborderWidth, 0); j++; + if(!engineDlg) option[i].value = *(Boolean*)option[i].target; // where checkbox callback uses it + j = SetPositionAndSize(args, last, lastrow, 1 /* border */, + textHeight/2 /* w */, textHeight/2 /* h */, 0xC0 /* chain both to left edge */); + XtSetArg(args[j], XtNvertDistance, (textHeight+2)/4 + 3); j++; + XtSetArg(args[j], XtNstate, option[i].value); j++; + lastrow = last; + option[i].handle = (void*) + (last = XtCreateManagedWidget(" ", toggleWidgetClass, form, args, j)); + j = SetPositionAndSize(args, last, lastrow, 0 /* border */, + option[i].max /* w */, textHeight /* h */, 0xC1 /* chain */); XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++; - last = XtCreateManagedWidget(cps->option[i].name, labelWidgetClass, form, args, j); + XtSetArg(args[j], XtNlabel, _(option[i].name)); j++; + last = XtCreateManagedWidget("label", commandWidgetClass, form, args, j); + // make clicking the text toggle checkbox + XtAddEventHandler(last, ButtonPressMask, False, CheckCallback, (XtPointer)(intptr_t) i + 256*dlgNr); + shrink = TRUE; // following buttons must get text height + break; + case Label: + msg = option[i].name; + if(!msg) break; + chain = option[i].min; + if(chain & SAME_ROW) forelast = lastrow; else shrink = FALSE; + j = SetPositionAndSize(args, last, lastrow, (chain & 2) != 0 /* border */, + option[i].max /* w */, shrink ? textHeight : 0 /* h */, chain | 2 /* chain */); +#if ENABLE_NLS + if(option[i].choice) XtSetArg(args[j], XtNfontSet, *(XFontSet*)option[i].choice), j++; +#else + if(option[i].choice) XtSetArg(args[j], XtNfont, (XFontStruct*)option[i].choice), j++; +#endif + XtSetArg(args[j], XtNresizable, False); j++; + XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++; + XtSetArg(args[j], XtNlabel, _(msg)); j++; + option[i].handle = (void*) (last = XtCreateManagedWidget("label", labelWidgetClass, form, args, j)); + if(option[i].target) // allow user to specify event handler for button presses + XtAddEventHandler(last, ButtonPressMask, False, CheckCallback, (XtPointer)(intptr_t) i + 256*dlgNr); break; case SaveButton: case Button: - j=0; - XtSetArg(args[j], XtNfromVert, last); j++; - XtSetArg(args[j], XtNstate, cps->option[i].value); j++; - cps->option[i].handle = (void*) - (last = XtCreateManagedWidget(cps->option[i].name, commandWidgetClass, form, args, j)); - XtAddCallback(last, XtNcallback, SettingsCallback, (XtPointer) (cps->option[i].type == SaveButton)); + if(option[i].min & SAME_ROW) { + chain = 0x31; // 0011.0001 = both left and right side to right edge + forelast = lastrow; + } else chain = 0, shrink = FALSE; + j = SetPositionAndSize(args, last, lastrow, 3 /* border */, + option[i].max /* w */, shrink ? textHeight : 0 /* h */, option[i].min & 0xE | chain /* chain */); + XtSetArg(args[j], XtNlabel, _(option[i].name)); j++; + if(option[i].textValue) { // special for buttons of New Variant dialog + XtSetArg(args[j], XtNsensitive, appData.noChessProgram || option[i].value < 0 + || strstr(first.variants, VariantName(option[i].value))); j++; + XtSetArg(args[j], XtNborderWidth, (gameInfo.variant == option[i].value)+1); j++; + } + option[i].handle = (void*) + (dialog = last = XtCreateManagedWidget(option[i].name, commandWidgetClass, form, args, j)); + if(option[i].choice && ((char*)option[i].choice)[0] == '#' && !engineDlg) { // for the color picker default-reset + SetColor( *(char**) option[i-1].target, &option[i]); + XtAddEventHandler(option[i-1].handle, KeyReleaseMask, False, ColorChanged, (XtPointer)(intptr_t) i-1); + } + XtAddCallback(last, XtNcallback, GenericCallback, (XtPointer)(intptr_t) i + (dlgNr<<16)); // invokes user callback + if(option[i].textValue) SetColor( option[i].textValue, &option[i]); // for new-variant buttons break; case ComboBox: - j=0; - XtSetArg(args[j], XtNfromVert, last); j++; - XtSetArg(args[j], XtNborderWidth, 0); j++; + j = SetPositionAndSize(args, last, lastrow, 0 /* border */, + 0 /* w */, textHeight /* h */, 0xC0 /* chain both sides to left edge */); XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++; - dialog = XtCreateManagedWidget(cps->option[i].name, labelWidgetClass, form, args, j); + XtSetArg(args[j], XtNlabel, _(option[i].name)); j++; + texts[h] = dialog = XtCreateManagedWidget(option[i].name, labelWidgetClass, form, args, j); - j=0; - XtSetArg(args[j], XtNfromVert, last); j++; - XtSetArg(args[j], XtNfromHoriz, dialog); j++; - XtSetArg(args[j], XtNwidth, 100); j++; - XtSetArg(args[j], XtNmenuName, XtNewString(cps->option[i].name)); j++; - XtSetArg(args[j], XtNlabel, ((char**)cps->option[i].textValue)[cps->option[i].value]); j++; - cps->option[i].handle = (void*) - (last = XtCreateManagedWidget(" ", menuButtonWidgetClass, form, args, j)); - CreateComboPopup(last, cps->option[i].name, i, (char **) cps->option[i].textValue); - values[i] = cps->option[i].value; + if(option[i].min & COMBO_CALLBACK) msg = _(option[i].name); else { + if(!engineDlg) SetCurrentComboSelection(option+i); + msg=_(((char**)option[i].choice)[option[i].value]); + } + + j = SetPositionAndSize(args, dialog, last, (option[i].min & 2) == 0 /* border */, + option[i].max && !engineDlg ? option[i].max : 100 /* w */, + textHeight /* h */, 0x91 /* chain */); // same row as its label! + XtSetArg(args[j], XtNmenuName, XtNewString(option[i].name)); j++; + XtSetArg(args[j], XtNlabel, msg); j++; + shrink = TRUE; + option[i].handle = (void*) + (last = XtCreateManagedWidget(" ", menuButtonWidgetClass, form, args, j)); + CreateComboPopup(last, option + i, i + 256*dlgNr, TRUE, -1); + values[i] = option[i].value; + break; + case ListBox: + // Listbox goes in viewport, as needed for game list + if(option[i].min & SAME_ROW) forelast = lastrow; + j = SetPositionAndSize(args, last, lastrow, 1 /* border */, + option[i].max /* w */, option[i].value /* h */, option[i].min /* chain */); + XtSetArg(args[j], XtNresizable, False); j++; + XtSetArg(args[j], XtNallowVert, True); j++; // scoll direction + last = + XtCreateManagedWidget("viewport", viewportWidgetClass, form, args, j); + j = 0; // now list itself + XtSetArg(args[j], XtNdefaultColumns, 1); j++; + XtSetArg(args[j], XtNforceColumns, True); j++; + XtSetArg(args[j], XtNverticalList, True); j++; + option[i].handle = (void*) + (edit = XtCreateManagedWidget("list", listWidgetClass, last, args, j)); + XawListChange(option[i].handle, option[i].target, 0, 0, True); + XawListHighlight(option[i].handle, 0); + scrollTranslations[25] = '0' + i; + scrollTranslations[27] = 'A' + dlgNr; + XtOverrideTranslations(edit, XtParseTranslationTable(scrollTranslations)); // for mouse-wheel + break; + case Graph: + j = SetPositionAndSize(args, last, lastrow, 0 /* border */, + option[i].max /* w */, option[i].value /* h */, option[i].min /* chain */); + option[i].handle = (void*) + (last = XtCreateManagedWidget("graph", widgetClass, form, args, j)); + XtAddEventHandler(last, ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask, False, + (XtEventHandler) GraphEventProc, &option[i]); // mandatory user-supplied expose handler + if(option[i].min & SAME_ROW) last = forelast, forelast = lastrow; + option[i].choice = (char**) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, option[i].max, option[i].value); // image buffer + break; + case PopUp: // note: used only after Graph, so 'last' refers to the Graph widget + option[i].handle = (void*) CreateComboPopup(last, option + i, i + 256*dlgNr, TRUE, option[i].value); + break; + case BoxBegin: + if(option[i].min & SAME_ROW) forelast = lastrow; + j = SetPositionAndSize(args, last, lastrow, 0 /* border */, + 0 /* w */, 0 /* h */, option[i].min /* chain */); + XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++; + XtSetArg(args[j], XtNvSpace, 0); j++; + option[box=i].handle = (void*) + (last = XtCreateWidget("box", boxWidgetClass, form, args, j)); + oldForm = form; form = last; oldLastRow = lastrow; oldForeLast = forelast; + lastrow = NULL; last = NULL; + break; + case DropDown: + j = SetPositionAndSize(args, last, lastrow, 0 /* border */, + 0 /* w */, 0 /* h */, 1 /* chain (always on same row) */); + forelast = lastrow; + msg = _(option[i].name); // write name on the menu button + XtSetArg(args[j], XtNmenuName, XtNewString(option[i].name)); j++; + XtSetArg(args[j], XtNlabel, msg); j++; + option[i].handle = (void*) + (last = XtCreateManagedWidget(option[i].name, menuButtonWidgetClass, form, args, j)); + option[i].textValue = (char*) CreateComboPopup(last, option + i, i + 256*dlgNr, FALSE, -1); + break; + case BoxEnd: + XtManageChildren(&form, 1); + SqueezeIntoBox(&option[box], i-box, option[box].max); + if(option[i].target) ((ButtonCallback*)option[i].target)(box); // callback that can make sizing decisions + last = form; lastrow = oldLastRow; form = oldForm; forelast = oldForeLast; + break; + case Break: + width++; + height = i+1; + stack = !(option[i].min & SAME_ROW); + break; + default: + printf("GenericPopUp: unexpected case in switch.\n"); break; } } - j=0; - XtSetArg(args[j], XtNfromVert, last); j++; - XtSetArg(args[j], XtNbottom, XtChainBottom); j++; - XtSetArg(args[j], XtNtop, XtChainBottom); j++; - XtSetArg(args[j], XtNleft, XtChainLeft); j++; - XtSetArg(args[j], XtNright, XtChainLeft); j++; - b_ok = XtCreateManagedWidget("OK", commandWidgetClass, form, args, j); - XtAddCallback(b_ok, XtNcallback, SettingsCallback, (XtPointer) 0); - - XtSetArg(args[j], XtNfromHoriz, b_ok); j++; - b_cancel = XtCreateManagedWidget("cancel", commandWidgetClass, form, args, j); - XtAddCallback(b_cancel, XtNcallback, SettingsPopDown, (XtPointer) 0); + // make an attempt to align all spins and textbox controls + maxWidth = maxTextWidth = 0; + if(browse != NULL) { + j=0; + XtSetArg(args[j], XtNwidth, &bWidth); j++; + XtGetValues(browse, args, j); + } + for(h=0; h maxWidth) maxWidth = w; + widest = texts[h]; + } else { + if(w > maxTextWidth) maxTextWidth = w; + if(!widest) widest = texts[h]; + } + } + } + if(maxTextWidth + 110 < maxWidth) + maxTextWidth = maxWidth - 110; + else maxWidth = maxTextWidth + 110; + for(h=0; hWM_PROTOCOLS: GenericPopDown(\"%d\") \n", dlgNr); + XtAugmentTranslations(popup, XtParseTranslationTable(def)); + XQueryPointer(xDisplay, xBoardWindow, &root, &child, + &x, &y, &win_x, &win_y, &mask); + + XtSetArg(args[0], XtNx, x - 10); + XtSetArg(args[1], XtNy, y - 30); + XtSetValues(popup, args, 2); + } + XtPopup(popup, modal ? XtGrabExclusive : XtGrabNone); + shellUp[dlgNr]++; // count rather than flag previous = NULL; - SetFocus(edit, popup, (XEvent*) NULL, False); + if(textField) SetFocus(textField, popup, (XEvent*) NULL, False); + if(dlgNr && wp[dlgNr] && wp[dlgNr]->width > 0) { // if persistent window-info available, reposition + j = 0; + XtSetArg(args[j], XtNheight, (Dimension) (wp[dlgNr]->height)); j++; + XtSetArg(args[j], XtNwidth, (Dimension) (wp[dlgNr]->width)); j++; + XtSetArg(args[j], XtNx, (Position) (wp[dlgNr]->x)); j++; + XtSetArg(args[j], XtNy, (Position) (wp[dlgNr]->y)); j++; + XtSetValues(popup, args, j); + } + RaiseWindow(dlgNr); + return 1; // tells caller he must do initialization (e.g. add specific event handlers) } -void FirstSettingsProc(w, event, prms, nprms) - Widget w; - XEvent *event; - String *prms; - Cardinal *nprms; -{ - SettingsPopUp(&first); -} -void SecondSettingsProc(w, event, prms, nprms) - Widget w; - XEvent *event; - String *prms; - Cardinal *nprms; +/* function called when the data to Paste is ready */ +static void +SendTextCB (Widget w, XtPointer client_data, Atom *selection, + Atom *type, XtPointer value, unsigned long *len, int *format) { - SettingsPopUp(&second); + char buf[MSG_SIZ], *p = (char*) textOptions[(int)(intptr_t) client_data].choice, *name = (char*) value, *q; + if (value==NULL || *len==0) return; /* nothing selected, abort */ + name[*len]='\0'; + strncpy(buf, p, MSG_SIZ); + q = strstr(p, "$name"); + snprintf(buf + (q-p), MSG_SIZ -(q-p), "%s%s", name, q+5); + SendString(buf); + XtFree(value); } -//--------------------------- General Popup for Cloning ---------------------------------- -#if 0 -int XXXUp; -Widget XXXShell; - -void XXXPopDown() +void +SendText (int n) { - if (!XXXUp) return; - XtPopdown(XXXShell); - XtDestroyWidget(XXXShell); - XXXUp = False; - ModeHighlight(); + char *p = (char*) textOptions[n].choice; + if(strstr(p, "$name")) { + XtGetSelectionValue(menuBarWidget, + XA_PRIMARY, XA_STRING, + /* (XtSelectionCallbackProc) */ SendTextCB, + (XtPointer) (intptr_t) n, /* client_data passed to PastePositionCB */ + CurrentTime + ); + } else SendString(p); } -void XXXCallback(w, client_data, call_data) - Widget w; - XtPointer client_data, call_data; +void +SetInsertPos (Option *opt, int pos) { - String name; - Widget w2; Arg args[16]; - char buf[80]; - - XtSetArg(args[0], XtNlabel, &name); - XtGetValues(w, args, 1); - - if (strcmp(name, "cancel") == 0) { - XXXPopDown(); - return; - } - if (strcmp(name, "ok") == 0) { - int nr; String name; - name = XawDialogGetValueString(w2 = XtParent(w)); - if(sscanf(name ,"%d",&nr) != 1) { - sprintf(buf, "%d", appData.defaultFrcPosition); - XtSetArg(args[0],XtNvalue, buf); // erase bad (non-numeric) value - XtSetValues(w2, args, 1); - return; - } - XXXPopDown(); - return; - } + XtSetArg(args[0], XtNinsertPosition, pos); + XtSetValues(opt->handle, args, 1); +// SetFocus(opt->handle, shells[InputBoxDlg], NULL, False); // No idea why this does not work, and the following is needed: +// XSetInputFocus(xDisplay, XtWindow(opt->handle), RevertToPointerRoot, CurrentTime); } -void XXXPopUp() -{ - Arg args[16]; - Widget popup, layout, dialog, edit; - Window root, child; - int x, y, i; - int win_x, win_y; - unsigned int mask; - char def[80]; - - i = 0; - XtSetArg(args[i], XtNresizable, True); i++; - XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++; - XXXShell = popup = - XtCreatePopupShell("XXX Menu", transientShellWidgetClass, - shellWidget, args, i); - - layout = - XtCreateManagedWidget(layoutName, formWidgetClass, popup, - layoutArgs, XtNumber(layoutArgs)); - - sprintf(def, "%d\n", appData.defaultFrcPosition); - i = 0; - XtSetArg(args[i], XtNlabel, ""); i++; - XtSetArg(args[i], XtNvalue, def); i++; - XtSetArg(args[i], XtNborderWidth, 0); i++; - dialog = XtCreateManagedWidget("XXX", dialogWidgetClass, - layout, args, i); - - XawDialogAddButton(dialog, "ok", XXXCallback, (XtPointer) dialog); - XawDialogAddButton(dialog, "cancel", XXXCallback, (XtPointer) dialog); - - XtRealizeWidget(popup); - CatchDeleteWindow(popup, "XXXPopDown"); - - XQueryPointer(xDisplay, xBoardWindow, &root, &child, - &x, &y, &win_x, &win_y, &mask); - - XtSetArg(args[0], XtNx, x - 10); - XtSetArg(args[1], XtNy, y - 30); - XtSetValues(popup, args, 2); - - XtPopup(popup, XtGrabExclusive); - XXXUp = True; - - edit = XtNameToWidget(dialog, "*value"); +void +TypeInProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ // can be used as handler for any text edit in any dialog (from GenericPopUp, that is) + int n = prms[0][0] - '0'; + Widget sh = XtParent(XtParent(XtParent(w))); // popup shell - previous = NULL; - SetFocus(engThreshold, popup, (XEvent*) NULL, False); + if(n<2) { // Enter or Esc typed from primed text widget: treat as if dialog OK or cancel button hit. + int dlgNr; // figure out what the dialog number is by comparing shells (because we must pass it :( ) + for(dlgNr=0; dlgNrhandle), RevertToPointerRoot, CurrentTime); } -#endif +