Implement Load Engine dialog in WinBoard
authorH.G. Muller <h.g.muller@hccnet.nl>
Wed, 4 May 2011 13:09:33 +0000 (15:09 +0200)
committerH.G. Muller <h.g.muller@hccnet.nl>
Wed, 4 May 2011 18:43:01 +0000 (20:43 +0200)
The Load Engine dialog is implemented for WinBoard, and is invoked by
the menu item Engine->Load, which formerly was Install 2nd. Install 1st
is renamed 'Edit Engine List'. Unlike in XBoard, the dialog has separate
fields for the engine executale and its parameters.
  The dialog is implemented by converting the Engine Settings popup into
a generic dialog generator.

backend.c
winboard/winboard.c
winboard/winboard.rc
winboard/wsettings.c
xoptions.c

index f7b26e5..9e2a6ca 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -858,12 +858,13 @@ ReplaceEngine(ChessProgramState *cps, int n)
     LoadEngine();
 }
 
-extern char *engineName, *engineDir, *engineChoice, *engineLine, *nickName;
+extern char *engineName, *engineDir, *engineChoice, *engineLine, *nickName, *params;
 extern Boolean isUCI, hasBook, storeVariant, v1, addToList;
 
-void Load(ChessProgramState *cps, int i)
+void
+Load(ChessProgramState *cps, int i)
 {
-    char *p, *q, buf[MSG_SIZ];
+    char *p, *q, buf[MSG_SIZ], command[MSG_SIZ];
     if(engineLine[0]) { // an engine was selected from the combo box
        snprintf(buf, MSG_SIZ, "-fcp %s", engineLine);
        SwapEngines(i); // kludge to parse -f* / -first* like it is -s* / -second*
@@ -875,15 +876,19 @@ void Load(ChessProgramState *cps, int i)
     }
     p = engineName;
     while(q = strchr(p, SLASH)) p = q+1;
-    if(*p== NULLCHAR) return;
-    appData.chessProgram[i] = strdup(p);
+    if(*p== NULLCHAR) { DisplayError(_("You did not give an engine executable"), 0); return; }
     if(engineDir[0] != NULLCHAR)
        appData.directory[i] = engineDir;
     else if(p != engineName) { // derive directory from engine path, when not given
        p[-1] = 0;
        appData.directory[i] = strdup(engineName);
-       p[-1] = '/';
+       p[-1] = SLASH;
     } else appData.directory[i] = ".";
+    if(params[0]) {
+       snprintf(command, MSG_SIZ, "%s %s", p, params);
+       p = command;
+    }
+    appData.chessProgram[i] = strdup(p);
     appData.isUCI[i] = isUCI;
     appData.protocolVersion[i] = v1 ? 1 : PROTOVER;
     appData.hasOwnBookUCI[i] = hasBook;
@@ -897,7 +902,6 @@ void Load(ChessProgramState *cps, int i)
                        isUCI ? " -fUCI" : "",
                        storeVariant ? " -variant " : "",
                        storeVariant ? VariantName(gameInfo.variant) : "");
-fprintf(debugFP, "new line: %s", buf);
        firstChessProgramNames = malloc(len = strlen(q) + strlen(buf) + 1);
        snprintf(firstChessProgramNames, len, "%s%s", q, buf);
        if(q)   free(q);
index cec132a..8a16fb4 100644 (file)
@@ -4943,7 +4943,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       break;\r
 \r
     case IDM_EditProgs2:\r
-      EditTagsPopUp(secondChessProgramNames, &secondChessProgramNames);\r
+     LoadEnginePopUp(hwndMain);\r
       break;\r
 \r
     case IDM_EditServers:\r
index 4bc7e20..90a8070 100644 (file)
@@ -1205,8 +1205,8 @@ BEGIN
     END\r
     POPUP "E&ngine"\r
     BEGIN\r
-        MENUITEM "Install 1st...",              IDM_EditProgs1\r
-        MENUITEM "Install 2nd...",              IDM_EditProgs2\r
+        MENUITEM "Edit Engine List...",         IDM_EditProgs1\r
+        MENUITEM "Load Engine...",              IDM_EditProgs2\r
         MENUITEM SEPARATOR\r
         MENUITEM "Engine #&1 Settings...",       IDM_Engine1Options\r
         MENUITEM "Engine #&2 Settings...",       IDM_Engine2Options\r
index caacb0c..43fcd06 100644 (file)
@@ -21,6 +21,7 @@
 #include "backendz.h"\r
 \r
 #define _(s) T_(s)\r
+#define N_(s) s\r
 \r
 int layoutList[2*MAX_OPTIONS];\r
 int checkList[2*MAX_OPTIONS];\r
@@ -30,14 +31,25 @@ int boxList[2*MAX_OPTIONS];
 int groupNameList[2*MAX_OPTIONS];\r
 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
+Boolean isUCI, hasBook, storeVariant, v1, addToList;\r
+extern Option installOptions[], matchOptions[];\r
+char *engineNr[] = { N_("First"), N_("Second"), NULL };\r
+char *engineList[1000] = {" "}, *engineMnemonic[1000] = {""};\r
+void (*okFunc)();\r
+ChessProgramState *activeCps;\r
+Option *activeList;\r
+void InstallOK P((void));\r
+typedef void ButtonCallback(HWND h);\r
 \r
 void\r
-PrintOpt(int i, int right, ChessProgramState *cps)\r
+PrintOpt(int i, int right, Option *optionList)\r
 {\r
     if(i<0) {\r
        if(!right) fprintf(debugFP, "%30s", "");\r
     } else {\r
-       Option opt = cps->option[i];\r
+       Option opt = optionList[i];\r
        switch(opt.type) {\r
            case Slider:\r
            case Spin:\r
@@ -48,6 +60,9 @@ PrintOpt(int i, int right, ChessProgramState *cps)
            case PathName:\r
                fprintf(debugFP, "%20.20s [______________________________________]", opt.name);\r
                break;\r
+           case Label:\r
+               fprintf(debugFP, "%41.41s", opt.name);\r
+               break;\r
            case CheckBox:\r
                fprintf(debugFP, "[x] %-26.25s", opt.name);\r
                break;\r
@@ -67,13 +82,13 @@ PrintOpt(int i, int right, ChessProgramState *cps)
 }\r
 \r
 void\r
-CreateOptionDialogTest(int *list, int nr, ChessProgramState *cps)\r
+CreateOptionDialogTest(int *list, int nr, Option *optionList)\r
 {\r
     int line;\r
 \r
     for(line = 0; line < nr; line+=2) {\r
-       PrintOpt(list[line+1], 0, cps);\r
-       PrintOpt(list[line], 1, cps);\r
+       PrintOpt(list[line+1], 0, optionList);\r
+       PrintOpt(list[line], 1, optionList);\r
     }\r
 }\r
 \r
@@ -99,6 +114,7 @@ LayoutOptions(int firstOption, int endOption, char *groupName, Option *optionLis
                case FileName:\r
                case PathName:\r
                case Slider:\r
+               case Label:\r
                case Spin: stop++;\r
                default:\r
                case Message: ; // cannot happen\r
@@ -109,7 +125,7 @@ LayoutOptions(int firstOption, int endOption, char *groupName, Option *optionLis
        if(!stop)\r
            nextType = Button; // kudge to flush remaining checks and combos undistorted\r
        // Take a new line if a spin follows combos or checks, or when we encounter a textbox\r
-       if((combos+checks || nextType == TextBox || nextType == FileName || nextType == PathName) && layout&1) {\r
+       if((combos+checks || nextType == TextBox || nextType == FileName || nextType == PathName || nextType == Label) && layout&1) {\r
            layoutList[layout++] = -1;\r
        }\r
        // The last check or combo before a spin will be put on the same line as that spin (prefix)\r
@@ -139,7 +155,7 @@ LayoutOptions(int firstOption, int endOption, char *groupName, Option *optionLis
            layoutList[layout++] = -1;\r
            layoutList[layout++] = comboList[2*right];\r
        }\r
-       if(nextType == TextBox || nextType == FileName || nextType == PathName) {\r
+       if(nextType == TextBox || nextType == FileName || nextType == PathName || nextType == Label) {\r
            // A textBox is double width, so must be left-adjusted, and the right column remains empty\r
            breaks[layout/2] = lastType == Button ? 0 : 100;\r
            layoutList[layout++] = -1;\r
@@ -173,44 +189,46 @@ EndMatch(char *s1, char *s2)
 }\r
 \r
 void\r
-DesignOptionDialog(ChessProgramState *cps)\r
+DesignOptionDialog(int nrOpt, Option *optionList)\r
 {\r
     int k=0, n=0;\r
     char buf[MSG_SIZ];\r
 \r
     layout = 0;\r
     buttons = groups = 0;\r
-    while(k < cps->nrOptions) { // k steps through 'solitary' options\r
+    while(k < nrOpt) { // k steps through 'solitary' options\r
        // look if we hit a group of options having names that start with the same word\r
        int groupSize = 1, groupNameLength = 50;\r
-       sscanf(cps->option[k].name, "%s", buf); // get first word of option name\r
-       while(k + groupSize < cps->nrOptions &&\r
-             strstr(cps->option[k+groupSize].name, buf) == cps->option[k+groupSize].name) {\r
+       sscanf(optionList[k].name, "%s", buf); // get first word of option name\r
+       while(k + groupSize < nrOpt &&\r
+             strstr(optionList[k+groupSize].name, buf) == optionList[k+groupSize].name) {\r
                int j;\r
                for(j=0; j<groupNameLength; j++) // determine common initial part of option names\r
-                   if( cps->option[k].name[j] != cps->option[k+groupSize].name[j]) break;\r
+                   if( optionList[k].name[j] != optionList[k+groupSize].name[j]) break;\r
                groupNameLength = j;\r
                groupSize++;\r
 \r
        }\r
        if(groupSize > 3) {\r
                // We found a group to terminates the current section\r
-               LayoutOptions(n, k, "", cps->option); // flush all solitary options appearing before the group\r
+               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
-               LayoutOptions(k, k+groupSize, buf, cps->option); // flush the group\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
        } else k += groupSize; // small groups are grouped with the solitary options\r
     }\r
-    if(n != k) LayoutOptions(n, k, "", cps->option); // flush remaining solitary options\r
+    if(n != k) LayoutOptions(n, k, "", optionList); // flush remaining solitary options\r
     // decide if and where we break into two column pairs\r
 \r
     // Emit buttons and add OK and cancel\r
 //    for(k=0; k<buttons; k++) layoutList[layout++] = buttonList[k];\r
-    // Create the dialog window\r
-    if(appData.debugMode) CreateOptionDialogTest(layoutList, layout, cps);\r
-//    CreateOptionDialog(layoutList, layout, cps);\r
\r
+   // Create the dialog window\r
+    if(appData.debugMode) CreateOptionDialogTest(layoutList, layout, optionList);\r
+//    CreateOptionDialog(layoutList, layout, optionList);\r
+    if(!activeCps) okFunc = optionList[nrOpt].target;\r
 }\r
 \r
 #include <windows.h>\r
@@ -238,44 +256,42 @@ struct {
     0x0000, 0x0000, L"Engine #1 Settings ", 8, L"MS Sans Serif"\r
 };\r
 \r
-ChessProgramState *activeCps;\r
-\r
 void\r
-SetOptionValues(HWND hDlg, ChessProgramState *cps)\r
+SetOptionValues(HWND hDlg, ChessProgramState *cps, Option *optionList)\r
 // Put all current option values in controls, and write option names next to them\r
 {\r
     HANDLE hwndCombo;\r
     int i, k;\r
-    char **choices, title[MSG_SIZ], *name;\r
+    char **choices, *name;\r
 \r
     for(i=0; i<layout+buttons; i++) {\r
        int j=layoutList[i];\r
        if(j == -2) SetDlgItemText( hDlg, 2000+2*i, ". . ." );\r
        if(j<0) continue;\r
-       name = cps->option[j].name;\r
+       name = optionList[j].name;\r
        if(strstr(name, "Polyglot ") == name) name += 9;\r
        SetDlgItemText( hDlg, 2000+2*i, name );\r
-//if(appData.debugMode) fprintf(debugFP, "# %s = %d\n",cps->option[j].name, cps->option[j].value );\r
-       switch(cps->option[j].type) {\r
+//if(appData.debugMode) fprintf(debugFP, "# %s = %d\n",optionList[j].name, optionList[j].value );\r
+       switch(optionList[j].type) {\r
            case Spin:\r
-               SetDlgItemInt( hDlg, 2001+2*i, cps->option[j].value, TRUE );\r
+               SetDlgItemInt( hDlg, 2001+2*i, cps ? optionList[j].value : *(int*)optionList[j].target, TRUE );\r
                break;\r
            case TextBox:\r
            case FileName:\r
            case PathName:\r
-               SetDlgItemText( hDlg, 2001+2*i, cps->option[j].textValue );\r
+               SetDlgItemText( hDlg, 2001+2*i, cps ? optionList[j].textValue : *(char**)optionList[j].target );\r
                break;\r
            case CheckBox:\r
-               CheckDlgButton( hDlg, 2000+2*i, cps->option[j].value != 0);\r
+               CheckDlgButton( hDlg, 2000+2*i, (cps ? optionList[j].value : *(Boolean*)optionList[j].target) != 0);\r
                break;\r
            case ComboBox:\r
-               choices = (char**) cps->option[j].textValue;\r
+               choices = (char**) optionList[j].textValue;\r
                hwndCombo = GetDlgItem(hDlg, 2001+2*i);\r
                SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0);\r
-               for(k=0; k<cps->option[j].max; k++) {\r
+               for(k=0; k<optionList[j].max; k++) {\r
                    SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) choices[k]);\r
                }\r
-               SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) choices[cps->option[j].value]);\r
+               SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) choices[optionList[j].value]);\r
                break;\r
            case Button:\r
            case SaveButton:\r
@@ -285,7 +301,6 @@ SetOptionValues(HWND hDlg, ChessProgramState *cps)
     }\r
     SetDlgItemText( hDlg, IDOK, _("OK") );\r
     SetDlgItemText( hDlg, IDCANCEL, _("Cancel") );\r
-    snprintf(title, MSG_SIZ, _("%s Engine Settings (%s)"), T_(cps->which), cps->tidy);\r
     title[0] &= ~32; // capitalize\r
     SetWindowText( hDlg, title);\r
     for(i=0; i<groups; i+=2) {\r
@@ -293,7 +308,7 @@ SetOptionValues(HWND hDlg, ChessProgramState *cps)
        id = k = boxList[i];\r
        if(layoutList[k] < 0) k++;\r
        if(layoutList[k] < 0) continue;\r
-       for(p=0; p<groupNameList[i]; p++) buf[p] = cps->option[layoutList[k]].name[p];\r
+       for(p=0; p<groupNameList[i]; p++) buf[p] = optionList[layoutList[k]].name[p];\r
        buf[p] = 0;\r
        SetDlgItemText( hDlg, 2000+2*(id+MAX_OPTIONS), buf );\r
     }\r
@@ -301,7 +316,7 @@ SetOptionValues(HWND hDlg, ChessProgramState *cps)
 \r
 \r
 void\r
-GetOptionValues(HWND hDlg, ChessProgramState *cps)\r
+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
@@ -312,50 +327,63 @@ GetOptionValues(HWND hDlg, ChessProgramState *cps)
     for(i=0; i<layout; i++) {\r
        int j=layoutList[i];\r
        if(j<0) continue;\r
-       switch(cps->option[j].type) {\r
+       switch(optionList[j].type) {\r
            case Spin:\r
                new = GetDlgItemInt( hDlg, 2001+2*i, &success, TRUE );\r
                if(!success) break;\r
-               if(new < cps->option[j].min) new = cps->option[j].min;\r
-               if(new > cps->option[j].max) new = cps->option[j].max;\r
-               changed = 2*(cps->option[j].value != new);\r
-               cps->option[j].value = new;\r
+               if(new < optionList[j].min) new = optionList[j].min;\r
+               if(new > optionList[j].max) new = optionList[j].max;\r
+               if(!cps) { *(int*)optionList[j].target = new; break; }\r
+               changed = 2*(optionList[j].value != new);\r
+               optionList[j].value = new;\r
                break;\r
            case TextBox:\r
            case FileName:\r
            case PathName:\r
-               success = GetDlgItemText( hDlg, 2001+2*i, newText, MSG_SIZ - strlen(cps->option[j].name) - 9 );\r
+               success = GetDlgItemText( hDlg, 2001+2*i, newText, MSG_SIZ - strlen(optionList[j].name) - 9 );\r
                if(!success) break;\r
-               changed = strcmp(cps->option[j].textValue, newText) != 0;\r
-               safeStrCpy(cps->option[j].textValue, newText, MSG_SIZ - (cps->option[j].textValue - cps->option[j].name) );\r
+               if(!cps) {\r
+                   if(*(char**)optionList[j].target) free(*(char**)optionList[j].target);\r
+                   *(char**)optionList[j].target = strdup(newText);\r
+                   break;\r
+               }\r
+               changed = strcmp(optionList[j].textValue, newText) != 0;\r
+               safeStrCpy(optionList[j].textValue, newText, MSG_SIZ - (optionList[j].textValue - optionList[j].name) );\r
                break;\r
            case CheckBox:\r
                new = IsDlgButtonChecked( hDlg, 2000+2*i );\r
-               changed = 2*(cps->option[j].value != new);\r
-               cps->option[j].value = new;\r
+               if(!cps) { *(Boolean*)optionList[j].target = new; break; }\r
+               changed = 2*(optionList[j].value != new);\r
+               optionList[j].value = new;\r
                break;\r
            case ComboBox:\r
-               choices = (char**) cps->option[j].textValue;\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<cps->option[j].max; k++) {\r
+               for(k=0; k<optionList[j].max; k++) {\r
                    if(!strcmp(choices[k], newText)) new = k;\r
                }\r
-               changed = new >= 0 && (cps->option[j].value != new);\r
-               if(changed) cps->option[j].value = new;\r
+               if(!cps && new) {\r
+                   if(*(char**)optionList[j].target) free(*(char**)optionList[j].target);\r
+                   *(char**)optionList[j].target = strdup(optionList[j].choice[new]);\r
+                   break;\r
+               }\r
+               changed = new >= 0 && (optionList[j].value != new);\r
+               if(changed) optionList[j].value = new;\r
                break;\r
            case Button:\r
            default:\r
                break; // are treated instantly, so they have been sent already\r
        }\r
        if(changed == 2)\r
-         snprintf(buf, MSG_SIZ, "option %s=%d\n", cps->option[j].name, new); else\r
+         snprintf(buf, MSG_SIZ, "option %s=%d\n", optionList[j].name, new); else\r
        if(changed == 1)\r
-         snprintf(buf, MSG_SIZ, "option %s=%s\n", cps->option[j].name, newText);\r
+         snprintf(buf, MSG_SIZ, "option %s=%s\n", optionList[j].name, newText);\r
        if(changed) SendToProgram(buf, cps);\r
     }\r
+    if(!cps && okFunc) ((ButtonCallback*) okFunc)(0);\r
 }\r
 \r
 LRESULT CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
@@ -368,7 +396,7 @@ LRESULT CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa
     case WM_INITDIALOG:\r
 \r
 //        CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER));\r
-       SetOptionValues(hDlg, activeCps);\r
+       SetOptionValues(hDlg, activeCps, activeList);\r
 \r
 //        SetFocus(GetDlgItem(hDlg, IDC_NFG_Edit));\r
 \r
@@ -377,12 +405,14 @@ LRESULT CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa
     case WM_COMMAND:\r
         switch( LOWORD(wParam) ) {\r
         case IDOK:\r
-           GetOptionValues(hDlg, activeCps);\r
+           GetOptionValues(hDlg, activeCps, activeList);\r
             EndDialog( hDlg, 0 );\r
+           activeCps = NULL;\r
             return TRUE;\r
 \r
         case IDCANCEL:\r
             EndDialog( hDlg, 1 );\r
+           activeCps = NULL;\r
             return TRUE;\r
 \r
        default:\r
@@ -426,10 +456,10 @@ LRESULT CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa
                    }\r
                }\r
                if(j < 0) break;\r
-               if( activeCps->option[j].type  == SaveButton)\r
-                    GetOptionValues(hDlg, activeCps);\r
-               else if( activeCps->option[j].type  != Button) break;\r
-               snprintf(buf, MSG_SIZ, "option %s\n", activeCps->option[j].name);\r
+               if( activeList[j].type  == SaveButton)\r
+                    GetOptionValues(hDlg, activeCps, activeList);\r
+               else if( activeList[j].type  != Button) break;\r
+               snprintf(buf, MSG_SIZ, "option %s\n", activeList[j].name);\r
                SendToProgram(buf, activeCps);\r
            }\r
            break;\r
@@ -471,7 +501,11 @@ void AddOption(int x, int y, Control type, int i)
            break;\r
        case TextBox:\r
            AddControl(x, y+1, 95, 9, 0x0082, SS_ENDELLIPSIS | WS_VISIBLE | WS_CHILD, i);\r
-           AddControl(x+95, y, 190, 11, 0x0081, ES_AUTOHSCROLL | WS_BORDER | WS_VISIBLE | WS_CHILD | WS_TABSTOP, i+1);\r
+           AddControl(x+95, y, 200, 11, 0x0081, ES_AUTOHSCROLL | WS_BORDER | WS_VISIBLE | WS_CHILD | WS_TABSTOP, i+1);\r
+           break;\r
+       case Label:\r
+           extra = activeList[layoutList[i/2]].value;\r
+           AddControl(x+extra, y+1, 290-extra, 9, 0x0082, SS_ENDELLIPSIS | WS_VISIBLE | WS_CHILD, i);\r
            break;\r
        case FileName:\r
        case PathName:\r
@@ -485,7 +519,8 @@ void AddOption(int x, int y, Control type, int i)
            break;\r
        case ComboBox:\r
            AddControl(x, y+1, 95, 9, 0x0082, SS_ENDELLIPSIS | WS_VISIBLE | WS_CHILD, i);\r
-           AddControl(x+95, y-1, 50, 500, 0x0085, CBS_AUTOHSCROLL | CBS_DROPDOWN | WS_VISIBLE | WS_CHILD | WS_TABSTOP, i+1);\r
+           AddControl(x+95, y-1, !activeCps && x<10 ? 120 : 50, 500, 0x0085,\r
+                       CBS_AUTOHSCROLL | CBS_DROPDOWN | WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_VSCROLL, i+1);\r
            break;\r
        case Button:\r
        case ResetButton:\r
@@ -499,7 +534,7 @@ void AddOption(int x, int y, Control type, int i)
 }\r
 \r
 void\r
-CreateDialogTemplate(int *layoutList, int nr, ChessProgramState *cps)\r
+CreateDialogTemplate(int *layoutList, int nr, Option *optionList)\r
 {\r
     int i, j, x=1, y=0, buttonRows, breakPoint = -1, k=0;\r
 \r
@@ -521,7 +556,7 @@ CreateDialogTemplate(int *layoutList, int nr, ChessProgramState *cps)
        }\r
        j = layoutList[i];\r
        if(j >= 0)\r
-           AddOption(x+155-150*(i&1), y+13*(i>>1)+5, cps->option[j].type, 2*i);\r
+           AddOption(x+155-150*(i&1), y+13*(i>>1)+5, optionList[j].type, 2*i);\r
        if(k < groups && i+1 == boxList[k+1]) {\r
            k += 2; y += 4;\r
        }\r
@@ -536,7 +571,7 @@ CreateDialogTemplate(int *layoutList, int nr, ChessProgramState *cps)
        AddControl(x+70*(i%4)+5, y+18*(i/4), 65, 15, 0x0080, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD, 2*(nr+i));\r
        layoutList[nr+i] = buttonList[i];\r
     }\r
-    template.title[8] = cps == &first ? '1' :  '2';\r
+    template.title[8] = optionList == first.option ? '1' :  '2';\r
     template.header.cy = y += 18*buttonRows+2;\r
     template.header.style &= ~WS_VSCROLL;\r
 }\r
@@ -546,9 +581,10 @@ EngineOptionsPopup(HWND hwnd, ChessProgramState *cps)
 {\r
     FARPROC lpProc = MakeProcInstance( (FARPROC) SettingsProc, hInst );\r
 \r
-    activeCps = cps;\r
-    DesignOptionDialog(cps);\r
-    CreateDialogTemplate(layoutList, layout, cps);\r
+    activeCps = cps; activeList = cps->option;\r
+    snprintf(title, MSG_SIZ, _("%s Engine Settings (%s)"), T_(cps->which), cps->tidy);\r
+    DesignOptionDialog(cps->nrOptions, cps->option);\r
+    CreateDialogTemplate(layoutList, layout, cps->option);\r
 \r
 \r
     DialogBoxIndirect( hInst, &template.header, hwnd, (DLGPROC)lpProc );\r
@@ -558,4 +594,59 @@ EngineOptionsPopup(HWND hwnd, ChessProgramState *cps)
     return;\r
 }\r
 \r
+void InstallOK()\r
+{\r
+    if(engineChoice[0] == engineNr[0][0])  Load(&first, 0); else Load(&second, 1);\r
+}\r
 \r
+Option installOptions[] = {\r
+  {   0,  0,    0, NULL, (void*) &engineLine, (char*) engineMnemonic, engineList, ComboBox, N_("Select engine from list:") },\r
+  {   0,  0,    0, NULL, NULL, NULL, NULL, Label, N_("or specify one below:") },\r
+  {   0,  0,    0, NULL, (void*) &nickName, NULL, NULL, TextBox, N_("Nickname (optional):") },\r
+  {   0,  0,    3, NULL, (void*) &engineName, NULL, NULL, FileName, N_("Engine Executable:") },\r
+  {   0,  0,    0, NULL, (void*) &params, NULL, NULL, TextBox, N_("Engine command-line Parameters:") },\r
+  {   0,  0,    0, NULL, (void*) &engineDir, NULL, NULL, PathName, N_("Engine Directory:") },\r
+  {  95,  0,    0, NULL, NULL, NULL, NULL, Label, N_("(Directory will be derived from engine path when empty)") },\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*) &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,    2, NULL, (void*) &engineChoice, (char*) engineNr, engineNr, ComboBox, N_("Load mentioned engine as") },\r
+  {   0,  1,    0, NULL, (void*) &InstallOK, "", NULL, EndMark , "" }\r
+};\r
+\r
+void\r
+GenericPopup(HWND hwnd, Option *optionList)\r
+{\r
+    FARPROC lpProc = MakeProcInstance( (FARPROC) SettingsProc, hInst );\r
+    int n=0;\r
+\r
+    while(optionList[n].type != EndMark) n++;\r
+    activeCps = NULL; activeList = optionList;\r
+    DesignOptionDialog(n, optionList);\r
+    CreateDialogTemplate(layoutList, layout, optionList);\r
+\r
+    DialogBoxIndirect( hInst, &template.header, hwnd, (DLGPROC)lpProc );\r
+\r
+    FreeProcInstance(lpProc);\r
+\r
+    return;\r
+}\r
+\r
+void LoadEnginePopUp(HWND hwnd)\r
+{\r
+    int n=0;\r
+\r
+    isUCI = addToList = storeVariant = v1 = FALSE; hasBook = TRUE; // defaults\r
+    if(engineDir)    free(engineDir);    engineDir = strdup("");\r
+    if(params)       free(params);       params = strdup("");\r
+    if(nickName)     free(nickName);     nickName = strdup("");\r
+    if(engineChoice) free(engineChoice); engineChoice = strdup(engineNr[0]);\r
+    if(engineLine)   free(engineLine);   engineLine = strdup("");\r
+    NamesToList(firstChessProgramNames, engineList, engineMnemonic);\r
+    while(engineList[n]) n++; installOptions[0].max = n;\r
+    snprintf(title, MSG_SIZ, _("Load Engine"));\r
+\r
+    GenericPopup(hwnd, installOptions);\r
+}\r
index 2408184..598019e 100644 (file)
@@ -775,7 +775,7 @@ void GenericPopDown(w, event, prms, nprms)
     PopDown(prms[0][0] - '0');
 }
 
-char *engineName, *engineDir, *engineChoice, *engineLine;
+char *engineName, *engineDir, *engineChoice, *engineLine, *nickName, *params;
 Boolean isUCI, hasBook, storeVariant, v1, addToList;
 extern Option installOptions[], matchOptions[];
 char *engineNr[] = { N_("First Engine"), N_("Second Engine"), NULL };
@@ -2055,7 +2055,7 @@ void LoadEngineProc(w, event, prms, nprms)
      Cardinal *nprms;
 {
    isUCI = addToList = storeVariant = v1 = False; hasBook = True; // defaults
-   engineDir = nickName = ""; 
+   engineDir = nickName = params = ""; 
    if(engineChoice) free(engineChoice); engineChoice = strdup(engineNr[0]);
    if(engineLine)   free(engineLine);   engineLine = strdup("");
    NamesToList(firstChessProgramNames, engineList, engineMnemonic);