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;
+static Option *currentOption;
 
 void SettingsPopDown()
 {
@@ -649,28 +650,28 @@ void SpinCallback(w, client_data, call_data)
 
     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) {
-       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);
-               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) {
-       if(++j > currentCps->option[data].max) return;
+       if(++j > currentOption[data].max) return;
     } 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);
-    XtSetValues(currentCps->option[data].handle, args, 1);
+    XtSetValues(currentOption[data].handle, args, 1);
 }
 
 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
-           switch(currentCps->option[i].type) {
+           switch(currentOption[i].type) {
                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);
-                   XtGetValues(currentCps->option[i].handle, args, 1);
+                   XtGetValues(currentOption[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;
-                       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);
-                   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:
-                   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;
@@ -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
-    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)
@@ -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
-    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;
@@ -1021,7 +1022,6 @@ void SecondSettingsProc(w, event, prms, nprms)
 typedef void ButtonCallback(int n);
 
 char *trialSound;
-static Option *currentOption;
 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);
     }
+    if(!n) currentCps = NULL; // if an Engine Settings dialog was up, we must be popping it down now
     return 1;
 }
 
@@ -1474,7 +1475,7 @@ void GenericReadout()
     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) {
@@ -1483,9 +1484,13 @@ void GenericReadout()
                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:
@@ -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(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;
@@ -1507,12 +1515,21 @@ void GenericReadout()
                    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]];
-                   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);
                    }
@@ -1524,6 +1541,7 @@ void GenericReadout()
            default:
                printf("GenericReadout: unexpected case in switch.\n");
                case Button:
+               case SaveButton:
                case Label:
              break;
            }
@@ -1555,8 +1573,11 @@ void GenericCallback(w, client_data, call_data)
         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
@@ -1580,12 +1601,17 @@ GenericPopUp(Option *option, char *title, int dlgNr)
     }
 
     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!
-    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] =
@@ -1617,7 +1643,8 @@ GenericPopUp(Option *option, char *title, int dlgNr)
            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:
@@ -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], XtNstring, option[i].type==Spin || option[i].type==Fractional ? def : *(char**)option[i].target);  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));
@@ -1692,13 +1720,14 @@ GenericPopUp(Option *option, char *title, int dlgNr)
                          (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++;
-           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:
@@ -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;
+         case SaveButton:
          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));
-           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);
@@ -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);
 
-           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;
-           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++;