Refactor move type-in code
[xboard.git] / xoptions.c
index 213f095..0689355 100644 (file)
@@ -50,6 +50,7 @@ extern char *getenv();
 #include <X11/Intrinsic.h>
 #include <X11/StringDefs.h>
 #include <X11/Shell.h>
+#include <X11/Xatom.h>
 #include <X11/Xaw/Dialog.h>
 #include <X11/Xaw/Form.h>
 #include <X11/Xaw/List.h>
@@ -81,7 +82,7 @@ extern char *getenv();
 
 extern void SendToProgram P((char *message, ChessProgramState *cps));
 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
-               char *init_path, char *mode, int (*show_entry)(), char **name_return));
+               char *init_path, char *filter, char *mode, int (*show_entry)(), char **name_return));
 
 extern Widget formWidget, shellWidget, boardWidget, menuBarWidget;
 extern Display *xDisplay;
@@ -619,20 +620,21 @@ void TimeControlProc(w, event, prms, nprms)
 
 //--------------------------- Engine-specific options menu ----------------------------------
 
-int SettingsUp;
-Widget SettingsShell;
 int values[MAX_OPTIONS];
 ChessProgramState *currentCps;
 static Option *currentOption;
+extern Widget shells[];
 
-void SettingsPopDown()
+void CheckCallback(Widget ww, XtPointer data, XEvent *event, Boolean *b)
 {
-    if (!SettingsUp) return;
-    previous = NULL;
-    XtPopdown(SettingsShell);
-    XtDestroyWidget(SettingsShell);
-    SettingsUp = False;
-    ModeHighlight();
+    Widget w = currentOption[(int)(intptr_t)data].handle;
+    Boolean s;
+    Arg args[16];
+
+    XtSetArg(args[0], XtNstate, &s);
+    XtGetValues(w, args, 1);
+    XtSetArg(args[0], XtNstate, !s);
+    XtSetValues(w, args, 1);
 }
 
 void SpinCallback(w, client_data, call_data)
@@ -653,14 +655,18 @@ void SpinCallback(w, client_data, call_data)
     XtGetValues(currentOption[data].handle, args, 1);
     sscanf(val, "%d", &j);
     if (strcmp(name, "browse") == 0) {
-       if(XsraSelFile(SettingsShell, currentOption[data].name, NULL, NULL, "", "", 
+       char *q, *r;
+       XtSetArg(args[0], XtNstring, &q);
+       XtGetValues(currentOption[data].handle, args, 1);
+       for(r = ""; *q; q++) if(*q == '.') r = q; else if(*q == '/') r = ""; // last dot after last slash
+       if(XsraSelFile(shells[0], currentOption[data].name, NULL, NULL, "", "", r,
                                  currentOption[data].type == PathName ? "p" : "f", NULL, &p)) {
                int len = strlen(p);
                if(len && p[len-1] == '/') p[len-1] = NULLCHAR;
                XtSetArg(args[0], XtNstring, p);
                XtSetValues(currentOption[data].handle, args, 1);
        }
-       SetFocus(currentOption[data].handle, SettingsShell, (XEvent*) NULL, False);
+       SetFocus(currentOption[data].handle, shells[0], (XEvent*) NULL, False);
        return;
     } else
     if (strcmp(name, "+") == 0) {
@@ -672,82 +678,7 @@ void SpinCallback(w, client_data, call_data)
     snprintf(buf, MSG_SIZ,  "%d", j);
     XtSetArg(args[0], XtNstring, buf);
     XtSetValues(currentOption[data].handle, args, 1);
-}
-
-void SettingsCallback(w, client_data, call_data)
-     Widget w;
-     XtPointer client_data, call_data;
-{
-    String name, val;
-    Arg args[16];
-    char buf[MSG_SIZ];
-    int i, j;
-    int data = (intptr_t) client_data;
-
-    XtSetArg(args[0], XtNlabel, &name);
-    XtGetValues(w, args, 1);
-
-    if (strcmp(name, _("cancel")) == 0) {
-        SettingsPopDown();
-        return;
-    }
-    if (strcmp(name, _("OK")) == 0 || data) { // save buttons imply OK
-       for(i=0; i<currentCps->nrOptions; i++) { // send all options that had to be OK-ed to engine
-           switch(currentOption[i].type) {
-               case TextBox:
-                   XtSetArg(args[0], XtNstring, &val);
-                   XtGetValues(currentOption[i].handle, args, 1);
-                   if(strcmp(currentOption[i].textValue, val)) {
-                     safeStrCpy(currentOption[i].textValue, val, MSG_SIZ - (currentOption[i].textValue - currentOption[i].name) );
-                     snprintf(buf, MSG_SIZ,  "option %s=%s\n", currentOption[i].name, val);
-                     SendToProgram(buf, currentCps);
-                   }
-                   break;
-               case Spin:
-                   XtSetArg(args[0], XtNstring, &val);
-                   XtGetValues(currentOption[i].handle, args, 1);
-                   sscanf(val, "%d", &j);
-                   if(j > currentOption[i].max) j = currentOption[i].max;
-                   if(j < currentOption[i].min) j = currentOption[i].min;
-                   if(currentOption[i].value != j) {
-                       currentOption[i].value = j;
-                       snprintf(buf, MSG_SIZ,  "option %s=%d\n", currentOption[i].name, j);
-                       SendToProgram(buf, currentCps);
-                   }
-                   break;
-               case CheckBox:
-                   j = 0;
-                   XtSetArg(args[0], XtNstate, &j);
-                   XtGetValues(currentOption[i].handle, args, 1);
-                   if(currentOption[i].value != j) {
-                       currentOption[i].value = j;
-                       snprintf(buf, MSG_SIZ,  "option %s=%d\n", currentOption[i].name, j);
-                       SendToProgram(buf, currentCps);
-                   }
-                   break;
-               case ComboBox:
-                   if(currentOption[i].value != values[i]) {
-                       currentOption[i].value = values[i];
-                       snprintf(buf, MSG_SIZ,  "option %s=%s\n", currentOption[i].name,
-                               ((char**)currentOption[i].textValue)[values[i]]);
-                       SendToProgram(buf, currentCps);
-                   }
-                   break;
-           default:
-             if( appData.debugMode )
-               fprintf(debugFP, "SettingsPopUp: unexpected case in switch.\n");
-             break;
-           }
-       }
-       if(data) { // send save-button command to engine
-         snprintf(buf, MSG_SIZ,  "option %s\n", name);
-         SendToProgram(buf, currentCps);
-       }
-        SettingsPopDown();
-        return;
-    }
-    snprintf(buf, MSG_SIZ,  "option %s\n", name);
-    SendToProgram(buf, currentCps);
+    SetFocus(currentOption[data].handle, shells[0], NULL, False);
 }
 
 void ComboSelect(w, addr, index) // callback for all combo items
@@ -789,238 +720,14 @@ void CreateComboPopup(parent, name, n, mb)
     }
 }
 
-void
-SettingsPopUp(ChessProgramState *cps)
-{
-    Arg args[16];
-    Widget popup, layout, dialog, edit=NULL, form,  last, b_ok, b_cancel, leftMargin = NULL, textField = NULL;
-    Window root, child;
-    int x, y, i, j, height, width, h, c;
-    int win_x, win_y, maxWidth, maxTextWidth;
-    unsigned int mask;
-    char def[MSG_SIZ];
-    static char pane[6] = "paneX";
-    Widget texts[100], forelast = NULL, anchor, widest;
-
-    // to do: start up second engine if needed
-    if(!cps->initDone || !cps->nrOptions) return; // nothing to be done
-    currentCps = cps; currentOption = cps->option;
-
-    if(cps->nrOptions > 50) width = 4; else if(cps->nrOptions>24) width = 2; else width = 1;
-    height = cps->nrOptions / width + 1;
-     i = 0;
-    XtSetArg(args[i], XtNresizable, True); i++;
-    SettingsShell = popup =
-      XtCreatePopupShell(_("Settings Menu"), transientShellWidgetClass,
-                        shellWidget, args, i);
-
-    layout =
-      XtCreateManagedWidget(layoutName, formWidgetClass, popup,
-                           layoutArgs, XtNumber(layoutArgs));
-  for(c=0; c<width; c++) {
-    pane[4] = 'A'+c;
-    form =
-      XtCreateManagedWidget(pane, formWidgetClass, layout,
-                           formArgs, XtNumber(formArgs));
-    j=0;
-    XtSetArg(args[j], XtNfromHoriz, leftMargin);  j++;
-    XtSetValues(form, args, j);
-    leftMargin = form;
-
-    last = widest = NULL; anchor = forelast;
-    for(h=0; h<height; h++) {
-       forelast = last;
-       i = h + c*height;
-        if(i >= cps->nrOptions) break;
-       switch(cps->option[i].type) {
-         case Spin:
-           snprintf(def, MSG_SIZ,  "%d", cps->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++;
-           texts[h] =
-           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 : 175); 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], XtNstring, cps->option[i].type==Spin ? def : cps->option[i].textValue);  j++;
-           XtSetArg(args[j], XtNinsertPosition, 9999);  j++;
-           edit = last;
-           cps->option[i].handle = (void*)
-               (textField = last = XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j));
-           XtAddEventHandler(last, ButtonPressMask, False, SetFocus, (XtPointer) popup);
-           if(cps->option[i].type == TextBox) break;
-
-           // add increment and decrement controls for spin
-           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++;
-           edit = XtCreateManagedWidget("+", commandWidgetClass, form, args, j);
-           XtAddCallback(edit, XtNcallback, SpinCallback,
-                         (XtPointer)(intptr_t) 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++;
-           last = XtCreateManagedWidget("-", commandWidgetClass, form, args, j);
-           XtAddCallback(last, XtNcallback, SpinCallback,
-                         (XtPointer)(intptr_t) i);
-           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++;
-           XtSetArg(args[j], XtNjustify, XtJustifyLeft);  j++;
-           last = XtCreateManagedWidget(cps->option[i].name, labelWidgetClass, form, args, j);
-           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*)
-               (dialog = last = XtCreateManagedWidget(cps->option[i].name, commandWidgetClass, form, args, j));
-           XtAddCallback(last, XtNcallback, SettingsCallback,
-                         (XtPointer)(intptr_t) (cps->option[i].type == SaveButton));
-           break;
-         case ComboBox:
-           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], 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;
-           break;
-       default:
-         if( appData.debugMode )
-           fprintf(debugFP, "SettingsPopUp: unexpected case in switch.\n");
-         break;
-       }
-    }
-
-    // make an attempt to align all spins and textbox controls
-    maxWidth = maxTextWidth = 0;
-    for(h=0; h<height; h++) {
-       i = h + c*height;
-        if(i >= cps->nrOptions) break;
-       if(cps->option[i].type == Spin || cps->option[i].type == TextBox) {
-           Dimension w;
-           j=0;
-           XtSetArg(args[j], XtNwidth, &w);  j++;
-           XtGetValues(texts[h], args, j);
-           if(cps->option[i].type == Spin) {
-               if(w > 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; h<height; h++) {
-       i = h + c*height;
-        if(i >= cps->nrOptions) break;
-       j=0;
-       if(cps->option[i].type == Spin) {
-           XtSetArg(args[j], XtNwidth, maxWidth);  j++;
-           XtSetValues(texts[h], args, j);
-       } else
-       if(cps->option[i].type == TextBox) {
-           XtSetArg(args[j], XtNwidth, maxTextWidth);  j++;
-           XtSetValues(texts[h], args, j);
-       }
-    }
-  }
-    j=0;
-    XtSetArg(args[j], XtNfromVert, anchor ? anchor : last);  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++;
-    XtSetArg(args[j], XtNfromHoriz, widest ? widest : dialog);  j++;
-    b_ok = XtCreateManagedWidget(_("OK"), commandWidgetClass, form, args, j);
-    XtAddCallback(b_ok, XtNcallback, SettingsCallback, (XtPointer) 0);
-
-    XtSetArg(args[j-1], XtNfromHoriz, b_ok);
-    b_cancel = XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
-    XtAddCallback(b_cancel, XtNcallback, SettingsPopDown, (XtPointer) 0);
-
-    XtRealizeWidget(popup);
-    CatchDeleteWindow(popup, "SettingsPopDown");
-
-    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);
-    SettingsUp = True;
-
-    previous = NULL;
-    if(textField)SetFocus(textField, popup, (XEvent*) NULL, False);
-}
-
-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;
-{
-   if(WaitForSecond(SettingsMenuIfReady)) return;
-   SettingsPopUp(&second);
-}
 
 //----------------------------Generic dialog --------------------------------------------
 
-// cloned from Engine Settings dialog
+// cloned from Engine Settings dialog (and later merged with it)
 
 typedef void ButtonCallback(int n);
 
+extern WindowPlacement wpComment, wpTags;
 char *trialSound;
 static int oldCores, oldPonder;
 int MakeColors P((void));
@@ -1031,7 +738,7 @@ void GenericReadout();
 Widget shells[10];
 Widget marked[10];
 Boolean shellUp[10];
-WindowPlacement *wp[10];
+WindowPlacement *wp[10] = { NULL, &wpComment, &wpTags };
 Option *dialogOptions[10];
 
 void MarkMenu(char *item, int dlgNr)
@@ -1100,7 +807,7 @@ void GeneralOptionsOK(int n)
 }
 
 Option generalOptions[] = {
-{ 0,  0, 0, NULL, (void*) &appData.alwaysPromoteToQueen, "", NULL, CheckBox, _("Always Queen") },
+{ 0,  0, 0, NULL, (void*) &appData.sweepSelect, "", NULL, CheckBox, _("Almost Always Queen (Detour Under-Promote)") },
 { 0,  0, 0, NULL, (void*) &appData.animateDragging, "", NULL, CheckBox, _("Animate Dragging") },
 { 0,  0, 0, NULL, (void*) &appData.animate, "", NULL, CheckBox, _("Animate Moving") },
 { 0,  0, 0, NULL, (void*) &appData.autoCallFlag, "", NULL, CheckBox, _("Auto Flag") },
@@ -1386,34 +1093,60 @@ void SetColor(char *colorName, Widget box)
        XtSetValues(box, args, 1);
 }
 
-void AdjustColor(int i)
+void SetColorText(int n, char *buf)
 {
-    int n = currentOption[i].value, col, j, r, g, b, step = 10;
+    Arg args[5];
+    XtSetArg(args[0], XtNstring, buf);
+    XtSetValues(currentOption[n-1].handle, args, 1);
+    SetFocus(currentOption[n-1].handle, shells[0], NULL, False);
+    SetColor(buf, currentOption[n].handle);
+}
+
+void DefColor(int n)
+{
+    SetColorText(n, (char*) currentOption[n].choice);
+}
+
+void RefreshColor(int source, int n)
+{
+    int col, j, r, g, b, step = 10;
     char *s, buf[MSG_SIZ]; // color string
     Arg args[5];
     XtSetArg(args[0], XtNstring, &s);
-    XtGetValues(currentOption[i-n-1].handle, args, 1);
+    XtGetValues(currentOption[source].handle, args, 1);
     if(sscanf(s, "#%x", &col) != 1) return;   // malformed
     b = col & 0xFF; g = col & 0xFF00; r = col & 0xFF0000;
     switch(n) {
-       case 1: g -= 0x100*step; b -= step; break;
-       case 2: r -= 0x10000*step; b -= step; break;
-       case 3: g -= 0x100*step; r -= 0x10000*step; break;
-       case 4: r += 0x10000*step; g += 0x100*step; b += step; break;
+       case 1: r += 0x10000*step;break;
+       case 2: g += 0x100*step;  break;
+       case 3: b += step;        break;
+       case 4: r -= 0x10000*step; g -= 0x100*step; b -= step; break;
     }
     if(r < 0) r = 0; if(g < 0) g = 0; if(b < 0) b = 0;
     if(r > 0xFF0000) r = 0xFF0000; if(g > 0xFF00) g = 0xFF00; if(b > 0xFF) b = 0xFF;
     col = r | g | b;
     snprintf(buf, MSG_SIZ, "#%06x", col);
     for(j=1; j<7; j++) if(buf[j] >= 'a') buf[j] -= 32; // capitalize
-    SetColor(buf, currentOption[i-n].handle);
-    XtSetArg(args[0], XtNstring, buf);
-    XtSetValues(currentOption[i-n-1].handle, args, 1);
+    SetColorText(source+1, buf);
+}
+
+void ColorChanged(Widget w, XtPointer data, XEvent *event, Boolean *b)
+{
+    char buf[10];
+    if ( (XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) && *buf == '\r' )
+       RefreshColor((int)(intptr_t) data, 0);
+}
+
+void AdjustColor(int i)
+{
+    int n = currentOption[i].value;
+    RefreshColor(i-n-1, n);
 }
 
 void BoardOptionsOK(int n)
 {
-    if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
+    extern int defaultLineGap;
+    if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap; else lineGap = defaultLineGap;
     MakeColors(); CreateGCs(True);
     CreateXPMPieces();
     CreateXPMBoard(appData.liteBackTextureFile, 1);
@@ -1424,42 +1157,42 @@ void BoardOptionsOK(int n)
 
 Option boardOptions[] = {
 { 0,   0, 70, NULL, (void*) &appData.whitePieceColor, "", NULL, TextBox, _("White Piece Color:") },
-{ 1000, 1, 0, NULL, NULL, NULL, NULL, Button, "      " },
+{ 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#FFFFCC", Button, "      " },
 {    1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "R" },
 {    2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "G" },
 {    3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "B" },
-{    4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "W" },
+{    4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "D" },
 { 0,   0, 70, NULL, (void*) &appData.blackPieceColor, "", NULL, TextBox, _("Black Piece Color:") },
-{ 1000, 1, 0, NULL, NULL, NULL, NULL, Button, "      " },
+{ 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#202020", Button, "      " },
 {    1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "R" },
 {    2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "G" },
 {    3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "B" },
-{    4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "W" },
+{    4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "D" },
 { 0,   0, 70, NULL, (void*) &appData.lightSquareColor, "", NULL, TextBox, _("Light Square Color:") },
-{ 1000, 1, 0, NULL, NULL, NULL, NULL, Button, "      " },
+{ 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#C8C365", Button, "      " },
 {    1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "R" },
 {    2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "G" },
 {    3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "B" },
-{    4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "W" },
+{    4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "D" },
 { 0,   0, 70, NULL, (void*) &appData.darkSquareColor, "", NULL, TextBox, _("Dark Square Color:") },
-{ 1000, 1, 0, NULL, NULL, NULL, NULL, Button, "      " },
+{ 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#77A26D", Button, "      " },
 {    1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "R" },
 {    2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "G" },
 {    3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "B" },
-{    4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "W" },
+{    4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "D" },
 { 0,   0, 70, NULL, (void*) &appData.highlightSquareColor, "", NULL, TextBox, _("Highlight Color:") },
-{ 1000, 1, 0, NULL, NULL, NULL, NULL, Button, "      " },
+{ 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#FFFF00", Button, "      " },
 {    1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "R" },
 {    2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "G" },
 {    3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "B" },
-{    4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "W" },
+{    4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "D" },
 { 0,   0, 70, NULL, (void*) &appData.premoveHighlightColor, "", NULL, TextBox, _("Premove Highlight Color:") },
-{ 1000, 1, 0, NULL, NULL, NULL, NULL, Button, "      " },
+{ 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#FF0000", Button, "      " },
 {    1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "R" },
 {    2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "G" },
 {    3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "B" },
-{    4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "W" },
-{ 0, 0, 0, NULL, (void*) &appData.upsideDown, "", NULL, CheckBox, _("Flip Pieces Shogi Style") },
+{    4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "D" },
+{ 0, 0, 0, NULL, (void*) &appData.upsideDown, "", NULL, CheckBox, _("Flip Pieces Shogi Style        (Colored buttons restore default)") },
 { 0, 0, 0, NULL, (void*) &appData.allWhite, "", NULL, CheckBox, _("Use Outline Pieces for Black") },
 { 0, 0, 0, NULL, (void*) &appData.monoMode, "", NULL, CheckBox, _("Mono Mode") },
 { 0,-1, 5, NULL, (void*) &appData.overrideLineGap, "", NULL, Spin, _("Line Gap ( -1 = default for board size):") },
@@ -1543,6 +1276,7 @@ void GenericReadout()
                case Button:
                case SaveButton:
                case Label:
+               case Break:
              break;
            }
            if(currentOption[i].type == EndMark) break;
@@ -1580,6 +1314,8 @@ void GenericCallback(w, client_data, call_data)
     } else ((ButtonCallback*) currentOption[data].target)(data);
 }
 
+static char *oneLiner  = "<Key>Return: redraw-display()\n";
+
 int
 GenericPopUp(Option *option, char *title, int dlgNr)
 {
@@ -1593,7 +1329,7 @@ GenericPopUp(Option *option, char *title, int dlgNr)
     static char pane[6] = "paneX";
     Widget texts[100], forelast = NULL, anchor, widest, lastrow = NULL;
 
-    if(shellUp[dlgNr]) return 0; // already up
+    if(shellUp[dlgNr]) return 0; // already up         
     if(dlgNr && shells[dlgNr]) {
        XtPopup(shells[dlgNr], XtGrabNone);
        shellUp[dlgNr] = True;
@@ -1686,6 +1422,8 @@ GenericPopUp(Option *option, char *title, int dlgNr)
            option[i].handle = (void*)
                (textField = last = XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j));
            XtAddEventHandler(last, ButtonPressMask, False, SetFocus, (XtPointer) popup);
+           if(option[i].min == 0 || option[i].type != TextBox)
+               XtOverrideTranslations(last, XtParseTranslationTable(oneLiner));
 
            if(option[i].type == TextBox || option[i].type == Fractional) break;
 
@@ -1703,8 +1441,7 @@ GenericPopUp(Option *option, char *title, int dlgNr)
            }
            XtSetArg(args[j], XtNwidth, w);  j++;
            edit = XtCreateManagedWidget(msg, commandWidgetClass, form, args, j);
-           XtAddCallback(edit, XtNcallback, SpinCallback,
-                         (XtPointer)(intptr_t) i);
+           XtAddCallback(edit, XtNcallback, SpinCallback, (XtPointer)(intptr_t) i);
 
            if(option[i].type != Spin) break;
 
@@ -1716,8 +1453,7 @@ GenericPopUp(Option *option, char *title, int dlgNr)
            XtSetArg(args[j], XtNleft, XtChainRight); j++;
            XtSetArg(args[j], XtNright, XtChainRight); j++;
            last = XtCreateManagedWidget("-", commandWidgetClass, form, args, j);
-           XtAddCallback(last, XtNcallback, SpinCallback,
-                         (XtPointer)(intptr_t) i);
+           XtAddCallback(last, XtNcallback, SpinCallback, (XtPointer)(intptr_t) i);
            break;
          case CheckBox:
            if(!currentCps) option[i].value = *(Boolean*)option[i].target;
@@ -1741,6 +1477,8 @@ GenericPopUp(Option *option, char *title, int dlgNr)
            XtSetArg(args[j], XtNborderWidth, 0);  j++;
            XtSetArg(args[j], XtNjustify, XtJustifyLeft);  j++;
            last = XtCreateManagedWidget(msg, labelWidgetClass, form, args, j);
+           if(option[i].type == CheckBox)
+               XtAddEventHandler(last, ButtonPressMask, False, CheckCallback, (XtPointer)(intptr_t) i);
            break;
          case SaveButton:
          case Button:
@@ -1756,7 +1494,10 @@ GenericPopUp(Option *option, char *title, int dlgNr)
            }
            option[i].handle = (void*)
                (dialog = last = XtCreateManagedWidget(option[i].name, commandWidgetClass, form, args, j));
-           if(option[i].target == NULL && !currentCps) SetColor( *(char**) option[i-1].target, last); else
+           if(option[i].choice && ((char*)option[i].choice)[0] == '#' && !currentCps) {
+               SetColor( *(char**) option[i-1].target, last);
+               XtAddEventHandler(option[i-1].handle, KeyReleaseMask, False, ColorChanged, (XtPointer)(intptr_t) i-1);
+           }
            XtAddCallback(last, XtNcallback, GenericCallback,
                          (XtPointer)(intptr_t) i + (dlgNr<<16));
            if(option[i].textValue) SetColor( option[i].textValue, last);
@@ -1780,7 +1521,7 @@ GenericPopUp(Option *option, char *title, int dlgNr)
            j=0;
            XtSetArg(args[j], XtNfromVert, last);  j++;
            XtSetArg(args[j], XtNfromHoriz, dialog);  j++;
-           XtSetArg(args[j], XtNwidth, option[i].max ? option[i].max : 100);  j++;
+           XtSetArg(args[j], XtNwidth, option[i].max && !currentCps ? option[i].max : 100);  j++;
            XtSetArg(args[j], XtNleft, XtChainLeft); j++;
            XtSetArg(args[j], XtNmenuName, XtNewString(option[i].name));  j++;
            XtSetArg(args[j], XtNlabel, ((char**)option[i].textValue)[option[i].value]);  j++;
@@ -1849,11 +1590,11 @@ GenericPopUp(Option *option, char *title, int dlgNr)
     XtSetArg(args[j], XtNleft, XtChainRight);  j++;
     XtSetArg(args[j], XtNright, XtChainRight);  j++;
     b_ok = XtCreateManagedWidget(_("OK"), commandWidgetClass, form, args, j);
-    XtAddCallback(b_ok, XtNcallback, GenericCallback, (XtPointer) dlgNr);
+    XtAddCallback(b_ok, XtNcallback, GenericCallback, (XtPointer)(intptr_t) dlgNr + (dlgNr<<16));
 
     XtSetArg(args[0], XtNfromHoriz, b_ok);
     b_cancel = XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
-    XtAddCallback(b_cancel, XtNcallback, GenericCallback, (XtPointer) dlgNr);
+    XtAddCallback(b_cancel, XtNcallback, GenericCallback, (XtPointer)(intptr_t) dlgNr);
   }
 
     XtRealizeWidget(popup);
@@ -1977,6 +1718,277 @@ void MatchOptionsProc(w, event, prms, nprms)
    GenericPopUp(matchOptions, _("Match Options"), 0);
 }
 
+Option textOptions[100];
+extern char *icsTextMenuString;
+void PutText P((char *text, int pos));
+
+SendString(char *p)
+{
+    char buf[MSG_SIZ], *q;
+    if(q = strstr(p, "$input")) {
+       if(!shellUp[4]) return;
+       strncpy(buf, p, MSG_SIZ);
+       strncpy(buf + (q-p), q+6, MSG_SIZ-(q-p));
+       PutText(buf, q-p);
+       return;
+    }
+    snprintf(buf, MSG_SIZ, "%s\n", p);
+    SendToICS(buf);
+}
+
+/* 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)
+{
+  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);
+}
+
+void SendText(int n)
+{
+    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 IcsTextProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+   int i=0, j;
+   char *p, *q, *r;
+   if((p = icsTextMenuString) == NULL) return;
+   do {
+       q = r = p; while(*p && *p != ';') p++;
+       for(j=0; j<p-q; j++) textOptions[i].name[j] = *r++;
+       textOptions[i].name[j++] = 0;
+       if(!*p) break;
+       if(*++p == '\n') p++; // optional linefeed after button-text terminating semicolon
+       q = p;
+       textOptions[i].choice = (char**) (r = textOptions[i].name + j);
+       while(*p && (*p != ';' || p[1] != '\n')) textOptions[i].name[j++] = *p++;
+       textOptions[i].name[j++] = 0;
+       if(*p) p += 2;
+       textOptions[i].max = 135;
+       textOptions[i].min = i&1;
+       textOptions[i].handle = NULL;
+       textOptions[i].target = &SendText;
+       textOptions[i].textValue = strstr(r, "$input") ? "#80FF80" : strstr(r, "$name") ? "#FF8080" : "#FFFFFF";
+       textOptions[i].type = Button;
+   } while(++i < 99 && *p);
+   if(i == 0) return;
+   textOptions[i].type = EndMark;
+   textOptions[i].target = NULL;
+   textOptions[i].min = 2;
+   MarkMenu("menuView.ICStex", 3);
+   GenericPopUp(textOptions, _("ICS text menu"), 3);
+}
+
+static char *commentText;
+static int commentIndex;
+void ClearComment P((int n));
+extern char commentTranslations[];
+
+void NewComCallback(int n)
+{
+    ReplaceComment(commentIndex, commentText);
+}
+
+void SaveChanges(int n)
+{
+    Arg args[16];
+    XtSetArg(args[0], XtNstring, &commentText);
+    XtGetValues(currentOption[0].handle, args, 1);
+    ReplaceComment(commentIndex, commentText);
+}
+
+Option commentOptions[] = {
+{ 0xD, 200, 300, NULL, (void*) &commentText, "", NULL, TextBox, "" },
+{   0,  0,    0, NULL, (void*) &ClearComment, NULL, NULL, Button, "clear" },
+{   0,  1,    0, NULL, (void*) &SaveChanges, NULL, NULL, Button, "save changes" },
+{   0,  1,    0, NULL, (void*) &NewComCallback, "", NULL, EndMark , "" }
+};
+
+void ClearComment(int n)
+{
+    XtCallActionProc(commentOptions[0].handle, "select-all", NULL, NULL, 0);
+    XtCallActionProc(commentOptions[0].handle, "kill-selection", NULL, NULL, 0);
+}
+
+void NewCommentPopup(char *title, char *text, int index)
+{
+    Widget edit;
+    Arg args[16];
+
+    if(shells[1]) { // if already exists, alter title and content
+       XtSetArg(args[0], XtNtitle, title);
+       XtSetValues(shells[1], args, 1);
+       XtSetArg(args[0], XtNstring, text);
+       XtSetValues(commentOptions[0].handle, args, 1);
+    }
+    commentText = text;
+    commentIndex = index;
+    MarkMenu("menuView.Show Comments", 1);
+    if(GenericPopUp(commentOptions, title, 1))
+       XtOverrideTranslations(commentOptions[0].handle, XtParseTranslationTable(commentTranslations));
+}
+
+static char *tagsText, *msgText;
+
+void NewTagsCallback(int n)
+{
+    ReplaceTags(tagsText, &gameInfo);
+}
+
+void changeTags(int n)
+{
+    Arg args[16];
+    XtSetArg(args[0], XtNstring, &tagsText);
+    XtGetValues(currentOption[0].handle, args, 1);
+    ReplaceTags(tagsText, &gameInfo);
+}
+
+Option tagsOptions[] = {
+{ 0xD, 200, 250, NULL, (void*) &tagsText, "", NULL, TextBox, "" },
+{   0,  0,    0, NULL, NULL, NULL, NULL, Label,  "" },
+{   0,  0,    0, NULL, (void*) &changeTags, NULL, NULL, Button, "save changes" },
+{   0,  1,    0, NULL, (void*) &NewTagsCallback, "", NULL, EndMark , "" }
+};
+
+void NewTagsPopup(char *text, char *msg)
+{
+    Widget edit;
+    Arg args[16];
+
+    if(shells[2]) { // if already exists, alter title and content
+       XtSetArg(args[0], XtNstring, text);
+       XtSetValues(tagsOptions[0].handle, args, 1);
+    }
+    tagsText = text;
+    tagsOptions[1].textValue = msg;
+    MarkMenu("menuView.Show Tags", 2);
+    GenericPopUp(tagsOptions, _("Tags"), 2);
+}
+
+extern char ICSInputTranslations[];
+char *icsText;
+
+Option boxOptions[] = {
+{   0, 30,  400, NULL, (void*) &icsText, "", NULL, TextBox, "" },
+{   0,  3,    0, NULL, NULL, "", NULL, EndMark , "" }
+};
+
+void PutText(char *text, int pos)
+{
+    Widget edit;
+    Arg args[16];
+    char buf[MSG_SIZ], *p;
+
+    if(strstr(text, "$add ") == text) {
+       XtSetArg(args[0], XtNstring, &p);
+       XtGetValues(boxOptions[0].handle, args, 1);
+       snprintf(buf, MSG_SIZ, "%s%s", p, text+5); text = buf;
+       pos += strlen(p) - 5;
+    }
+    XtSetArg(args[0], XtNstring, text);
+    XtSetValues(boxOptions[0].handle, args, 1);
+    XtSetArg(args[0], XtNinsertPosition, pos);
+    XtSetValues(boxOptions[0].handle, args, 1);
+//    SetFocus(boxOptions[0].handle, shells[4], NULL, False); // No idea why this does not work, and the following is needed:
+    XSetInputFocus(xDisplay, XtWindow(boxOptions[0].handle), RevertToPointerRoot, CurrentTime);
+}
+
+void InputBoxPopup()
+{
+    MarkMenu("menuView.ICS Input Box", 4);
+    if(GenericPopUp(boxOptions, _("ICS input box"), 4))
+       XtOverrideTranslations(boxOptions[0].handle, XtParseTranslationTable(ICSInputTranslations));
+}
+
+void TypeInProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+    Arg args[2];
+    String val;
+
+    if(prms[0][0] == '1') {
+       XtSetArg(args[0], XtNstring, &val);
+       XtGetValues(boxOptions[0].handle, args, 1);
+       TypeInDoneEvent((char*)val);
+    }
+    PopDown(0);\r
+}
+
+char moveTypeInTranslations[] =
+    "<Key>Return: TypeInProc(1) \n"
+    "<Key>Escape: TypeInProc(0) \n";
+
+void PopUpMoveDialog(char firstchar)
+{
+    static char buf[2];
+    buf[0] = firstchar; icsText = buf;
+    if(GenericPopUp(boxOptions, _("Type a move"), 0))
+       XtOverrideTranslations(boxOptions[0].handle, XtParseTranslationTable(moveTypeInTranslations));
+}
+
+void MoveTypeInProc(Widget widget, caddr_t unused, XEvent *event)
+{
+    char buf[10], keys[32];
+    KeySym sym;
+    KeyCode metaL, metaR;
+    int n = XLookupString(&(event->xkey), buf, 10, &sym, NULL);
+    XQueryKeymap(xDisplay,keys);
+    metaL = XKeysymToKeycode(xDisplay, XK_Meta_L);
+    metaR = XKeysymToKeycode(xDisplay, XK_Meta_R);
+    if ( n == 1 && *buf > 32 && !(keys[metaL>>3]&1<<(metaL&7)) && !(keys[metaR>>3]&1<<(metaR&7))) // printable, no alt
+       PopUpMoveDialog(*buf);
+
+}
+
+void
+SettingsPopUp(ChessProgramState *cps)
+{
+   currentCps = cps;
+   GenericPopUp(cps->option, _("Engine Settings"), 0);
+}
+
+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;
+{
+   if(WaitForSecond(SettingsMenuIfReady)) return;
+   SettingsPopUp(&second);
+}
+
 //---------------------------- Chat Windows ----------------------------------------------
 
 void OutputChatMessage(int partner, char *mess)