Fix installing chosen protocols
[xboard.git] / winboard / wsettings.c
index 2cb488e..b65566c 100644 (file)
@@ -1,4 +1,28 @@
 /*\r
+ * woptions.h -- Options dialog box routines for WinBoard\r
+ *\r
+ * Copyright 2003, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Free\r
+ * Software Foundation, Inc.\r
+ *\r
+ * ------------------------------------------------------------------------\r
+ *\r
+ * GNU XBoard is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or (at\r
+ * your option) any later version.\r
+ *\r
+ * GNU XBoard is distributed in the hope that it will be useful, but\r
+ * WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+ * General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program. If not, see http://www.gnu.org/licenses/.  *\r
+ *\r
+ *------------------------------------------------------------------------\r
+ ** See the file ChangeLog for a revision history.  */\r
+\r
+/*\r
  * Engine-settings dialog. The complexity come from an attempt to present the engine-defined options\r
  * in a nicey formatted layout. To this end we first run a back-end pre-formatter, which will distribute\r
  * the controls over two columns (the minimum required, as some are double width). It also takes care of\r
@@ -33,7 +57,7 @@ int groupNameList[2*MAX_OPTIONS];
 int breaks[MAX_OPTIONS];\r
 int checks, combos, buttons, layout, groups;\r
 char title[MSG_SIZ];\r
-char *engineName, *engineDir, *engineChoice, *engineLine, *nickName, *params;\r
+char *engineName, *engineDir, *protocolChoice, *engineLine, *nickName, *params;\r
 Boolean isUCI, hasBook, storeVariant, v1, addToList, useNick, isUCCI;\r
 extern Option installOptions[], matchOptions[];\r
 char *engineList[MAXENGINES] = {""}, *engineMnemonic[MAXENGINES] = {""};\r
@@ -97,7 +121,7 @@ void
 LayoutOptions(int firstOption, int endOption, char *groupName, Option *optionList)\r
 {\r
     int i, b = strlen(groupName), stop, prefix, right, nextOption, firstButton = buttons;\r
-    Control lastType, nextType;\r
+    Control lastType, nextType=Label;\r
 \r
     nextOption = firstOption;\r
     while(nextOption < endOption) {\r
@@ -117,6 +141,7 @@ LayoutOptions(int firstOption, int endOption, char *groupName, Option *optionLis
                case PathName:\r
                case Slider:\r
                case Label:\r
+               case GroupBox:\r
                case Spin: stop++;\r
                default:\r
                case Message: ; // cannot happen\r
@@ -217,6 +242,7 @@ DesignOptionDialog(int nrOpt, Option *optionList)
        // look if we hit a group of options having names that start with the same word\r
        int groupSize = 1, groupNameLength = 50;\r
        sscanf(optionList[k].name, "%s", buf); // get first word of option name\r
+       if(optionList[k].type == GroupBox) groupSize = optionList[k].max, groupNameLength = -strlen(optionList[k].name), groupNameList[groups+1] = k; else\r
        while(k + groupSize < nrOpt &&\r
              strstr(optionList[k+groupSize].name, buf) == optionList[k+groupSize].name) {\r
                int j;\r
@@ -231,6 +257,7 @@ DesignOptionDialog(int nrOpt, Option *optionList)
                LayoutOptions(n, k, "", optionList); // flush all solitary options appearing before the group\r
                groupNameList[groups] = groupNameLength;\r
                boxList[groups++] = layout; // group start in even entries\r
+               if(groupNameLength <= 0) n = ++k;\r
                LayoutOptions(k, k+groupSize, buf, optionList); // flush the group\r
                boxList[groups++] = layout; // group end in odd entries\r
                k = n = k + groupSize;\r
@@ -348,6 +375,7 @@ SetOptionValues(HWND hDlg, ChessProgramState *cps, Option *optionList)
        if(layoutList[k] < 0) continue;\r
        for(p=0; p<groupNameList[i]; p++) buf[p] = optionList[layoutList[k]].name[p];\r
        buf[p] = 0;\r
+       if(groupNameList[i] < 0) safeStrCpy(buf, optionList[groupNameList[i+1]].name, MSG_SIZ);\r
        SetDlgItemText( hDlg, 2000+2*(id+MAX_OPTIONS), buf );\r
     }\r
 }\r
@@ -357,7 +385,6 @@ int
 GetOptionValues(HWND hDlg, ChessProgramState *cps, Option *optionList)\r
 // read out all controls, and if value is altered, remember it and send it to the engine\r
 {\r
-    HANDLE hwndCombo;\r
     int i, k, new=0, changed=0, len;\r
     char **choices, newText[MSG_SIZ], buf[MSG_SIZ], *text;\r
     BOOL success;\r
@@ -401,14 +428,13 @@ GetOptionValues(HWND hDlg, ChessProgramState *cps, Option *optionList)
                break;\r
            case ComboBox:\r
                choices = (char**) optionList[j].textValue;\r
-               hwndCombo = GetDlgItem(hDlg, 2001+2*i);\r
                success = GetDlgItemText( hDlg, 2001+2*i, newText, MSG_SIZ );\r
                if(!success) break;\r
                new = -1;\r
                for(k=0; k<optionList[j].max; k++) {\r
                    if(choices[k] && !strcmp(choices[k], newText)) new = k;\r
                }\r
-               if(!cps && new > 0) {\r
+               if(!cps && new >= 0) {\r
                    if(*(char**)optionList[j].target) free(*(char**)optionList[j].target);\r
                    *(char**)optionList[j].target = strdup(optionList[j].choice[new]);\r
                    break;\r
@@ -434,6 +460,7 @@ GetOptionValues(HWND hDlg, ChessProgramState *cps, Option *optionList)
 }\r
 \r
 char *defaultExt[] = { NULL, "pgn", "fen", "exe", "trn", "bin", "log", "ini" };\r
+HWND settingsDlg;\r
 \r
 LRESULT CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
 {\r
@@ -446,7 +473,7 @@ LRESULT CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa
 \r
 //        CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER));\r
        SetOptionValues(hDlg, activeCps, activeList);\r
-\r
+       settingsDlg = hDlg;\r
         SetFocus(GetDlgItem(hDlg, IDCANCEL));\r
 \r
         break;\r
@@ -456,12 +483,12 @@ LRESULT CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa
         case IDOK:\r
            if(!GetOptionValues(hDlg, activeCps, activeList)) return FALSE;\r
             EndDialog( hDlg, 0 );\r
-           comboCallback = NULL; activeCps = NULL;\r
+           comboCallback = NULL; activeCps = NULL; settingsDlg = NULL;\r
             return TRUE;\r
 \r
         case IDCANCEL:\r
             EndDialog( hDlg, 1 );\r
-           comboCallback = NULL; activeCps = NULL;\r
+           comboCallback = NULL; activeCps = NULL; settingsDlg = NULL;\r
             return TRUE;\r
 \r
        default:\r
@@ -518,6 +545,12 @@ LRESULT CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa
                     GetOptionValues(hDlg, activeCps, activeList);\r
                else if( activeList[j].type  != Button) break;\r
                else if( !activeCps ) { (*(ButtonCallback*) activeList[j].target)(hDlg); break; }\r
+               if(j == 0) { // WinBoard save button\r
+                   SaveEngineSettings(activeCps == &second);\r
+                   EndDialog( hDlg, 0 );\r
+                   comboCallback = NULL; activeCps = NULL; settingsDlg = NULL;\r
+                   return TRUE;\r
+               }\r
                snprintf(buf, MSG_SIZ, "option %s\n", activeList[j].name);\r
                SendToProgram(buf, activeCps);\r
            }\r
@@ -554,7 +587,7 @@ void AddOption(int x, int y, Control type, int i)
     int extra, num = ES_NUMBER;\r
 \r
     switch(type) {\r
-       case Slider+100:\r
+       case Spin+100:\r
            num = 0; // needs text control for accepting negative numbers\r
        case Slider:\r
        case Spin:\r
@@ -611,7 +644,7 @@ CreateDialogTemplate(int *layoutList, int nr, Option *optionList)
     template.header.cdit = 0;\r
     template.header.cx = 307;\r
     buttonRows = (buttons + 1 + 3)/4; // 4 per row, rounded up\r
-    if(nr > 50) {\r
+    if(nr > 48) {\r
        breakPoint = (nr+2*buttonRows+1)/2 & ~1;\r
        template.header.cx = 625;\r
     }\r
@@ -619,10 +652,11 @@ CreateDialogTemplate(int *layoutList, int nr, Option *optionList)
     for(ii=0; ii<nr; ii++) {\r
        i = ii^1; if(i == nr) i = ii; // if two on one line, swap order of treatment, to get good (left to right) tabbing order.\r
        if(k < groups && ii == boxList[k]) {\r
+           int tlen = groupNameList[k]; if(tlen < 0) tlen = -tlen;\r
            y += 10;\r
            AddControl(x+2, y+13*(i>>1)-2, 301, 13*(boxList[k+1]-boxList[k]>>1)+8,\r
                                                0x0082, WS_VISIBLE | WS_CHILD | SS_BLACKFRAME, 2400);\r
-           AddControl(x+60, y+13*(i>>1)-6, 10*groupNameList[k]/3, 10,\r
+           AddControl(x+60, y+13*(i>>1)-6, 10*tlen/3, 10,\r
                                                0x0082, SS_ENDELLIPSIS | WS_VISIBLE | WS_CHILD, 2*(ii+MAX_OPTIONS));\r
        }\r
        j = layoutList[i];\r
@@ -670,14 +704,32 @@ EngineOptionsPopup(HWND hwnd, ChessProgramState *cps)
     return;\r
 }\r
 \r
+void\r
+RefreshSettingsDialog (ChessProgramState *cps, int val)\r
+{\r
+    int isUp = (settingsDlg != NULL);\r
+    if(val == 1) {\r
+       if(activeCps == cps && isUp) SetOptionValues(settingsDlg, cps, activeList);\r
+       return;\r
+    }\r
+    if(settingsDlg) EndDialog(settingsDlg, 1);\r
+    comboCallback = NULL; activeCps = NULL; settingsDlg = NULL;\r
+    if(val == 3 || isUp) EngineOptionsPopup(hwndMain, cps);\r
+}\r
+\r
 int EnterGroup P((HWND hDlg));\r
 \r
 static int engineNr, selected;\r
+char *protocols[] = { "autodetect", "WB", "UCI", "USI/UCCI", "WB v1", NULL };\r
 \r
 int InstallOK()\r
 {\r
     if(selected >= 0) { ASSIGN(engineLine, engineList[selected]); }\r
     if(engineLine[0] == '#') { DisplayError(_("Select single engine from the group"), 0); return 0; }\r
+    if(!strcmp(protocolChoice, protocols[0])) isUCI = 3; else\r
+    if(!strcmp(protocolChoice, protocols[2])) isUCI = 1; else\r
+    if(!strcmp(protocolChoice, protocols[3])) isUCCI = 1; else\r
+    if(!strcmp(protocolChoice, protocols[4])) v1 = 1;\r
     if(isUCCI) isUCI = 2;\r
     if(!engineNr) Load(&first, 0); else Load(&second, 1);\r
     return 1;\r
@@ -687,19 +739,19 @@ Option installOptions[] = {
 //  {   0,  0,    0, NULL, (void*) &engineLine, (char*) engineMnemonic, engineList, ComboBox, N_("Select engine from list:") },\r
   { 195, 14,    0, NULL, (void*) &EnterGroup, (char*) &selected, engineMnemonic, ListBox, N_("Select engine from list:") },\r
   {   0,  0,    0, NULL, NULL, NULL, NULL, Label, N_("or specify one below:") },\r
+  {   0,  0, 32+3, NULL, (void*) &engineName, NULL, NULL, FileName, N_("Engine (.exe or .jar):") },\r
+  {   0,  0,    5, NULL, (void*) &protocolChoice, (char*) protocols, protocols, ComboBox, N_("Engine protocol") },\r
+  {   0,  0,    5, NULL, NULL, NULL, NULL, GroupBox, N_("Optional user preferences") },\r
   {   0,  0,    0, NULL, (void*) &nickName, NULL, NULL, TextBox, N_("Nickname (optional):") },\r
+  {   0,  0,    0, NULL, (void*) &addToList, NULL, NULL, CheckBox, N_("Add this engine to the list") },\r
+  {   0,  0,    0, NULL, (void*) &hasBook, NULL, NULL, CheckBox, N_("Must not use GUI book") },\r
   {   0,  0,    0, NULL, (void*) &useNick, NULL, NULL, CheckBox, N_("Use nickname in PGN tag") },\r
-  {   0,  0, 32+3, NULL, (void*) &engineName, NULL, NULL, FileName, N_("Engine (.exe or .jar):") },\r
+  {   0,  0,    0, NULL, (void*) &storeVariant, NULL, NULL, CheckBox, N_("Force current variant with this engine") },\r
+  {   0,  0,    4, NULL, NULL, NULL, NULL, GroupBox, N_("Advanced (special cases only, as per engine README file)") },\r
   {   0,  0,    0, NULL, (void*) &params, NULL, NULL, TextBox, N_("command-line parameters:") },\r
   {   0,  0,    0, NULL, (void*) &wbOptions, NULL, NULL, TextBox, N_("Special WinBoard options:") },\r
   {   0,  0,    0, NULL, (void*) &engineDir, NULL, NULL, PathName, N_("directory:") },\r
   {  95,  0,    0, NULL, NULL, NULL, NULL, Label, N_("(Directory will be derived from engine path when left empty)") },\r
-  {   0,  0,    0, NULL, (void*) &addToList, NULL, NULL, CheckBox, N_("Add this engine to the list") },\r
-  {   0,  0,    0, NULL, (void*) &hasBook, NULL, NULL, CheckBox, N_("Must not use GUI book") },\r
-  {   0,  0,    0, NULL, (void*) &storeVariant, NULL, NULL, CheckBox, N_("Force current variant with this engine") },\r
-  {   0,  0,    0, NULL, (void*) &isUCI, NULL, NULL, CheckBox, N_("UCI") },\r
-  {   0,  0,    0, NULL, (void*) &v1, NULL, NULL, CheckBox, N_("WB protocol v1 (skip waiting for features)") },\r
-  {   0,  0,    0, NULL, (void*) &isUCCI, NULL, NULL, CheckBox, N_("UCCI / USI (uses specified /uxiAdapter)") },\r
   {   0,  1,    0, NULL, (void*) &InstallOK, "", NULL, EndMark , "" }\r
 };\r
 \r
@@ -865,15 +917,20 @@ int MatchOK()
 \r
 void PseudoOK(HWND hDlg)\r
 {\r
-    void (*saveOK)();\r
-    saveOK = okFunc; okFunc = 0;\r
+    if(matchMode) return;\r
+    okFunc = 0;\r
     GetOptionValues(hDlg, activeCps, activeList);\r
     EndDialog( hDlg, 0 );\r
     comboCallback = NULL; activeCps = NULL;\r
 \r
     if(autoinc) appData.loadGameIndex = appData.loadPositionIndex = -(twice + 1); else\r
     if(!appData.loadGameFile[0]) appData.loadGameIndex = -2*twice; // kludge to pass value of "twice" for use in GUI book\r
+    if(!autoinc && !twice) { // prevent auto-inc being remembered in index value if checkboxes not ticked\r
+       if(appData.loadGameIndex < 0) appData.loadGameIndex = 0;\r
+       if(appData.loadPositionIndex < 0) appData.loadPositionIndex = 0;\r
+    }\r
     if(swiss) { appData.defaultMatchGames = 1; appData.tourneyType = -1; }\r
+    ASSIGN(appData.tourneyFile, tfName);\r
 }\r
 \r
 char *GetParticipants(HWND hDlg)\r