Merge SettingsPopUp into GenericPopUp
authorH.G. Muller <h.g.muller@hccnet.nl>
Sat, 2 Apr 2011 16:36:09 +0000 (18:36 +0200)
committerArun Persaud <apersaud@lbl.gov>
Thu, 7 Apr 2011 05:21:40 +0000 (22:21 -0700)
Based on currentCps the values read from the dialog are sent to the
engine, or stored into the option.target in the callback, and fetched
from the option.target in the PopUp. The currentCps is cleared in the
generic popdown of a transient dialog.

xoptions.c

index bc22faf..213f095 100644 (file)
@@ -623,6 +623,7 @@ int SettingsUp;
 Widget SettingsShell;
 int values[MAX_OPTIONS];
 ChessProgramState *currentCps;
 Widget SettingsShell;
 int values[MAX_OPTIONS];
 ChessProgramState *currentCps;
+static Option *currentOption;
 
 void SettingsPopDown()
 {
 
 void SettingsPopDown()
 {
@@ -649,28 +650,28 @@ void SpinCallback(w, client_data, call_data)
 
     j = 0;
     XtSetArg(args[0], XtNstring, &val);
 
     j = 0;
     XtSetArg(args[0], XtNstring, &val);
-    XtGetValues(currentCps->option[data].handle, args, 1);
+    XtGetValues(currentOption[data].handle, args, 1);
     sscanf(val, "%d", &j);
     if (strcmp(name, "browse") == 0) {
     sscanf(val, "%d", &j);
     if (strcmp(name, "browse") == 0) {
-       if(XsraSelFile(SettingsShell, currentCps->option[data].name, NULL, NULL, "", "", 
-                                 currentCps->option[data].type == PathName ? "p" : "f", NULL, &p)) {
+       if(XsraSelFile(SettingsShell, currentOption[data].name, NULL, NULL, "", "", 
+                                 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);
                int len = strlen(p);
                if(len && p[len-1] == '/') p[len-1] = NULLCHAR;
                XtSetArg(args[0], XtNstring, p);
-               XtSetValues(currentCps->option[data].handle, args, 1);
+               XtSetValues(currentOption[data].handle, args, 1);
        }
        }
-       SetFocus(currentCps->option[data].handle, SettingsShell, (XEvent*) NULL, False);
+       SetFocus(currentOption[data].handle, SettingsShell, (XEvent*) NULL, False);
        return;
     } else
     if (strcmp(name, "+") == 0) {
        return;
     } else
     if (strcmp(name, "+") == 0) {
-       if(++j > currentCps->option[data].max) return;
+       if(++j > currentOption[data].max) return;
     } else
     if (strcmp(name, "-") == 0) {
     } else
     if (strcmp(name, "-") == 0) {
-       if(--j < currentCps->option[data].min) return;
+       if(--j < currentOption[data].min) return;
     } else return;
     snprintf(buf, MSG_SIZ,  "%d", j);
     XtSetArg(args[0], XtNstring, buf);
     } else return;
     snprintf(buf, MSG_SIZ,  "%d", j);
     XtSetArg(args[0], XtNstring, buf);
-    XtSetValues(currentCps->option[data].handle, args, 1);
+    XtSetValues(currentOption[data].handle, args, 1);
 }
 
 void SettingsCallback(w, client_data, call_data)
 }
 
 void SettingsCallback(w, client_data, call_data)
@@ -692,43 +693,43 @@ void SettingsCallback(w, client_data, call_data)
     }
     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
     }
     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(currentCps->option[i].type) {
+           switch(currentOption[i].type) {
                case TextBox:
                    XtSetArg(args[0], XtNstring, &val);
                case TextBox:
                    XtSetArg(args[0], XtNstring, &val);
-                   XtGetValues(currentCps->option[i].handle, args, 1);
-                   if(strcmp(currentCps->option[i].textValue, val)) {
-                     safeStrCpy(currentCps->option[i].textValue, val, MSG_SIZ - (currentCps->option[i].textValue - currentCps->option[i].name) );
-                     snprintf(buf, MSG_SIZ,  "option %s=%s\n", currentCps->option[i].name, 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);
                      SendToProgram(buf, currentCps);
                    }
                    break;
                case Spin:
                    XtSetArg(args[0], XtNstring, &val);
-                   XtGetValues(currentCps->option[i].handle, args, 1);
+                   XtGetValues(currentOption[i].handle, args, 1);
                    sscanf(val, "%d", &j);
                    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;
-                       snprintf(buf, MSG_SIZ,  "option %s=%d\n", currentCps->option[i].name, 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);
                        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;
-                       snprintf(buf, MSG_SIZ,  "option %s=%d\n", currentCps->option[i].name, 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:
                        SendToProgram(buf, currentCps);
                    }
                    break;
                case ComboBox:
-                   if(currentCps->option[i].value != values[i]) {
-                       currentCps->option[i].value = values[i];
-                       snprintf(buf, MSG_SIZ,  "option %s=%s\n", currentCps->option[i].name,
-                               ((char**)currentCps->option[i].textValue)[values[i]]);
+                   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;
                        SendToProgram(buf, currentCps);
                    }
                    break;
@@ -759,8 +760,8 @@ void ComboSelect(w, addr, index) // callback for all combo items
     int j = 255 & (intptr_t) addr;
 
     values[i] = j; // store in temporary, for transfer at OK
     int j = 255 & (intptr_t) addr;
 
     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);
+    XtSetArg(args[0], XtNlabel, ((char**)currentOption[i].textValue)[j]);
+    XtSetValues(currentOption[i].handle, args, 1);
 }
 
 void CreateComboPopup(parent, name, n, mb)
 }
 
 void CreateComboPopup(parent, name, n, mb)
@@ -803,7 +804,7 @@ SettingsPopUp(ChessProgramState *cps)
 
     // to do: start up second engine if needed
     if(!cps->initDone || !cps->nrOptions) return; // nothing to be done
 
     // to do: start up second engine if needed
     if(!cps->initDone || !cps->nrOptions) return; // nothing to be done
-    currentCps = cps;
+    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;
 
     if(cps->nrOptions > 50) width = 4; else if(cps->nrOptions>24) width = 2; else width = 1;
     height = cps->nrOptions / width + 1;
@@ -1021,7 +1022,6 @@ void SecondSettingsProc(w, event, prms, nprms)
 typedef void ButtonCallback(int n);
 
 char *trialSound;
 typedef void ButtonCallback(int n);
 
 char *trialSound;
-static Option *currentOption;
 static int oldCores, oldPonder;
 int MakeColors P((void));
 void CreateGCs P((int redo));
 static int oldCores, oldPonder;
 int MakeColors P((void));
 void CreateGCs P((int redo));
@@ -1067,6 +1067,7 @@ int PopDown(int n)
        XtSetArg(args[0], XtNleftBitmap, None);
        XtSetValues(marked[n], args, 1);
     }
        XtSetArg(args[0], XtNleftBitmap, None);
        XtSetValues(marked[n], args, 1);
     }
+    if(!n) currentCps = NULL; // if an Engine Settings dialog was up, we must be popping it down now
     return 1;
 }
 
     return 1;
 }
 
@@ -1474,7 +1475,7 @@ void GenericReadout()
     int i, j;
     String name, val;
     Arg args[16];
     int i, j;
     String name, val;
     Arg args[16];
-    char buf[MSG_SIZ];
+    char buf[MSG_SIZ], **dest;
     float x;
        for(i=0; ; i++) { // send all options that had to be OK-ed to engine
            switch(currentOption[i].type) {
     float x;
        for(i=0; ; i++) { // send all options that had to be OK-ed to engine
            switch(currentOption[i].type) {
@@ -1483,9 +1484,13 @@ void GenericReadout()
                case PathName:
                    XtSetArg(args[0], XtNstring, &val);
                    XtGetValues(currentOption[i].handle, args, 1);
                case PathName:
                    XtSetArg(args[0], XtNstring, &val);
                    XtGetValues(currentOption[i].handle, args, 1);
-                   if(*(char**) currentOption[i].target == NULL || strcmp(*(char**) currentOption[i].target, val)) {
-                       safeStrCpy(currentOption[i].name + 100, val, MSG_SIZ-100); // text value kept in pivate storage for each option
-                       *(char**) currentOption[i].target = currentOption[i].name + 100; // option gets to point to that
+                   dest = currentCps ? &(currentOption[i].textValue) : (char**) currentOption[i].target;
+                   if(*dest == NULL || strcmp(*dest, val)) {
+                       if(currentCps) {
+                           snprintf(buf, MSG_SIZ,  "option %s=%s\n", currentOption[i].name, val);
+                           SendToProgram(buf, currentCps);
+                       } else *dest = currentOption[i].name + 100; // option gets to point to private storage;
+                       safeStrCpy(*dest, val, MSG_SIZ - (*dest - currentOption[i].name)); // copy text there
                    }
                    break;
                case Spin:
                    }
                    break;
                case Spin:
@@ -1497,7 +1502,10 @@ void GenericReadout()
                    if(x < currentOption[i].min) x = currentOption[i].min;
                    if(currentOption[i].value != x) {
                        currentOption[i].value = x;
                    if(x < currentOption[i].min) x = currentOption[i].min;
                    if(currentOption[i].value != x) {
                        currentOption[i].value = x;
-                       if(currentOption[i].type == Spin) *(int*) currentOption[i].target = x;
+                       if(currentCps) { // engines never have float options, so no decimals!
+                           snprintf(buf, MSG_SIZ,  "option %s=%.0f\n", currentOption[i].name, x);
+                           SendToProgram(buf, currentCps);
+                       } else if(currentOption[i].type == Spin) *(int*) currentOption[i].target = x;
                        else *(float*) currentOption[i].target = x;
                    }
                    break;
                        else *(float*) currentOption[i].target = x;
                    }
                    break;
@@ -1507,12 +1515,21 @@ void GenericReadout()
                    XtGetValues(currentOption[i].handle, args, 1);
                    if(currentOption[i].value != j) {
                        currentOption[i].value = j;
                    XtGetValues(currentOption[i].handle, args, 1);
                    if(currentOption[i].value != j) {
                        currentOption[i].value = j;
-                       *(Boolean*) currentOption[i].target = j;
+                       if(currentCps) {
+                           snprintf(buf, MSG_SIZ,  "option %s=%d\n", currentOption[i].name, j);
+                           SendToProgram(buf, currentCps);
+                       } else *(Boolean*) currentOption[i].target = j;
                    }
                    break;
                case ComboBox:
                    val = ((char**)currentOption[i].choice)[values[i]];
                    }
                    break;
                case ComboBox:
                    val = ((char**)currentOption[i].choice)[values[i]];
-                   if(val && (*(char**) currentOption[i].target == NULL || strcmp(*(char**) currentOption[i].target, val))) {
+                   if(currentCps) {
+                       if(currentOption[i].value == values[i]) break; // not changed
+                       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);
+                   } else if(val && (*(char**) currentOption[i].target == NULL || strcmp(*(char**) currentOption[i].target, val))) {
                      if(*(char**) currentOption[i].target) free(*(char**) currentOption[i].target);
                      *(char**) currentOption[i].target = strdup(val);
                    }
                      if(*(char**) currentOption[i].target) free(*(char**) currentOption[i].target);
                      *(char**) currentOption[i].target = strdup(val);
                    }
@@ -1524,6 +1541,7 @@ void GenericReadout()
            default:
                printf("GenericReadout: unexpected case in switch.\n");
                case Button:
            default:
                printf("GenericReadout: unexpected case in switch.\n");
                case Button:
+               case SaveButton:
                case Label:
              break;
            }
                case Label:
              break;
            }
@@ -1555,8 +1573,11 @@ void GenericCallback(w, client_data, call_data)
         PopDown(data);
         return;
     }
         PopDown(data);
         return;
     }
-    if(currentOption[data].textValue);
-    ((ButtonCallback*) currentOption[data].target)(data);
+    if(currentCps) {
+       if(currentOption[data].type == SaveButton) GenericReadout();
+       snprintf(buf, MSG_SIZ,  "option %s\n", name);
+       SendToProgram(buf, currentCps);
+    } else ((ButtonCallback*) currentOption[data].target)(data);
 }
 
 int
 }
 
 int
@@ -1580,12 +1601,17 @@ GenericPopUp(Option *option, char *title, int dlgNr)
     }
 
     dialogOptions[dlgNr] = option; // make available to callback
     }
 
     dialogOptions[dlgNr] = option; // make available to callback
-    // kludge: fake address of a ChessProgramState struct that contains the options, so Spin and Combo callbacks work on it
+    // 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!
     // WARNING: this kludge does not work for persistent dialogs, so that these cannot have spin or combo controls!
-    currentCps = (ChessProgramState *) ((char *) option - ((char *)&first.option - (char *)&first));
-
-//    if(cps->nrOptions > 50) width = 4; else if(cps->nrOptions>24) width = 2; else width = 1;
-//    height = cps->nrOptions / width + 1;
+    currentOption = option;
+
+    if(currentCps) { // 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(currentOption[n-1].type == Button || currentOption[n-1].type == SaveButton) currentOption[n].min = 1; // 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++;
     popup = shells[dlgNr] =
      i = 0;
     XtSetArg(args[i], XtNresizable, True); i++;
     popup = shells[dlgNr] =
@@ -1617,7 +1643,8 @@ GenericPopUp(Option *option, char *title, int dlgNr)
            option[i].value = *(float*)option[i].target;
            goto tBox;
          case Spin:
            option[i].value = *(float*)option[i].target;
            goto tBox;
          case Spin:
-           snprintf(def, MSG_SIZ,  "%d", option[i].value = *(int*)option[i].target);
+           if(!currentCps) option[i].value = *(int*)option[i].target;
+           snprintf(def, MSG_SIZ,  "%d", option[i].value);
          case TextBox:
          case FileName:
          case PathName:
          case TextBox:
          case FileName:
          case PathName:
@@ -1652,8 +1679,9 @@ GenericPopUp(Option *option, char *title, int dlgNr)
            XtSetArg(args[j], XtNdisplayCaret, False);  j++;
            XtSetArg(args[j], XtNright, XtChainRight);  j++;
            XtSetArg(args[j], XtNresizable, True);  j++;
            XtSetArg(args[j], XtNdisplayCaret, False);  j++;
            XtSetArg(args[j], XtNright, XtChainRight);  j++;
            XtSetArg(args[j], XtNresizable, True);  j++;
-           XtSetArg(args[j], XtNstring, option[i].type==Spin || option[i].type==Fractional ? def : *(char**)option[i].target);  j++;
            XtSetArg(args[j], XtNinsertPosition, 9999);  j++;
            XtSetArg(args[j], XtNinsertPosition, 9999);  j++;
+           XtSetArg(args[j], XtNstring, option[i].type==Spin || option[i].type==Fractional ? def : 
+                               currentCps ? option[i].textValue : *(char**)option[i].target);  j++;
            edit = last;
            option[i].handle = (void*)
                (textField = last = XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j));
            edit = last;
            option[i].handle = (void*)
                (textField = last = XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j));
@@ -1692,13 +1720,14 @@ GenericPopUp(Option *option, char *title, int dlgNr)
                          (XtPointer)(intptr_t) i);
            break;
          case CheckBox:
                          (XtPointer)(intptr_t) i);
            break;
          case CheckBox:
+           if(!currentCps) option[i].value = *(Boolean*)option[i].target;
            j=0;
            XtSetArg(args[j], XtNfromVert, last);  j++;
            XtSetArg(args[j], XtNwidth, 10);  j++;
            XtSetArg(args[j], XtNheight, 10);  j++;
            XtSetArg(args[j], XtNleft, XtChainLeft); j++;
            XtSetArg(args[j], XtNright, XtChainLeft); j++;
            j=0;
            XtSetArg(args[j], XtNfromVert, last);  j++;
            XtSetArg(args[j], XtNwidth, 10);  j++;
            XtSetArg(args[j], XtNheight, 10);  j++;
            XtSetArg(args[j], XtNleft, XtChainLeft); j++;
            XtSetArg(args[j], XtNright, XtChainLeft); j++;
-           XtSetArg(args[j], XtNstate, option[i].value = *(Boolean*)option[i].target);  j++;
+           XtSetArg(args[j], XtNstate, option[i].value);  j++;
            option[i].handle = (void*)
                (dialog = XtCreateManagedWidget(" ", toggleWidgetClass, form, args, j));
          case Label:
            option[i].handle = (void*)
                (dialog = XtCreateManagedWidget(" ", toggleWidgetClass, form, args, j));
          case Label:
@@ -1713,6 +1742,7 @@ GenericPopUp(Option *option, char *title, int dlgNr)
            XtSetArg(args[j], XtNjustify, XtJustifyLeft);  j++;
            last = XtCreateManagedWidget(msg, labelWidgetClass, form, args, j);
            break;
            XtSetArg(args[j], XtNjustify, XtJustifyLeft);  j++;
            last = XtCreateManagedWidget(msg, labelWidgetClass, form, args, j);
            break;
+         case SaveButton:
          case Button:
            j=0;
            XtSetArg(args[j], XtNfromVert, option[i].min & 1 ? lastrow : last);  j++;
          case Button:
            j=0;
            XtSetArg(args[j], XtNfromVert, option[i].min & 1 ? lastrow : last);  j++;
@@ -1726,7 +1756,7 @@ GenericPopUp(Option *option, char *title, int dlgNr)
            }
            option[i].handle = (void*)
                (dialog = last = XtCreateManagedWidget(option[i].name, commandWidgetClass, form, args, j));
            }
            option[i].handle = (void*)
                (dialog = last = XtCreateManagedWidget(option[i].name, commandWidgetClass, form, args, j));
-           if(option[i].target == NULL) SetColor( *(char**) option[i-1].target, last); else
+           if(option[i].target == NULL && !currentCps) SetColor( *(char**) option[i-1].target, last); else
            XtAddCallback(last, XtNcallback, GenericCallback,
                          (XtPointer)(intptr_t) i + (dlgNr<<16));
            if(option[i].textValue) SetColor( option[i].textValue, last);
            XtAddCallback(last, XtNcallback, GenericCallback,
                          (XtPointer)(intptr_t) i + (dlgNr<<16));
            if(option[i].textValue) SetColor( option[i].textValue, last);
@@ -1741,9 +1771,11 @@ GenericPopUp(Option *option, char *title, int dlgNr)
            XtSetArg(args[j], XtNjustify, XtJustifyLeft);  j++;
            texts[h] = dialog = XtCreateManagedWidget(option[i].name, labelWidgetClass, form, args, j);
 
            XtSetArg(args[j], XtNjustify, XtJustifyLeft);  j++;
            texts[h] = dialog = XtCreateManagedWidget(option[i].name, labelWidgetClass, form, args, j);
 
-           for(j=0; option[i].choice[j]; j++)
+           if(currentCps) option[i].choice = (char**) option[i].textValue; else {
+             for(j=0; option[i].choice[j]; j++)
                if(*(char**)option[i].target && !strcmp(*(char**)option[i].target, option[i].choice[j])) break;
                if(*(char**)option[i].target && !strcmp(*(char**)option[i].target, option[i].choice[j])) break;
-           option[i].value = j + (option[i].choice[j] == NULL);
+             option[i].value = j + (option[i].choice[j] == NULL);
+           }
 
            j=0;
            XtSetArg(args[j], XtNfromVert, last);  j++;
 
            j=0;
            XtSetArg(args[j], XtNfromVert, last);  j++;