q = r; while(*q) nPlayers += (*q++ == '\n');
p = buf; while(*r && (*p = *r++) != '\n') p++;
*p = NULLCHAR;
- NamesToList(firstChessProgramNames, command, mnemonic);
+ NamesToList(firstChessProgramNames, command, mnemonic, "all");
for(i=1; mnemonic[i]; i++) if(!strcmp(buf, mnemonic[i])) break;
if(mnemonic[i]) { // The substitute is valid
FILE *f;
return 1;
}
-void
-NamesToList (char *names, char **engineList, char **engineMnemonic)
+int
+NamesToList (char *names, char **engineList, char **engineMnemonic, char *group)
{
char buf[MSG_SIZ], *p, *q;
- int i=1;
- while(*names) {
- p = names; q = buf;
+ int i=1, header, skip, all = !strcmp(group, "all"), depth = 0;
+ skip = !all && group[0]; // if group requested, we start in skip mode
+ for(;*names && depth >= 0 && i < MAXENGINES-1; names = p) {
+ p = names; q = buf; header = 0;
while(*p && *p != '\n') *q++ = *p++;
*q = 0;
+ if(*p == '\n') p++;
+ if(buf[0] == '#') {
+ if(strstr(buf, "# end") == buf) { depth--; continue; } // leave group, and suppress printing label
+ depth++; // we must be entering a new group
+ if(all) continue; // suppress printing group headers when complete list requested
+ header = 1;
+ if(skip && !strcmp(group, buf)) { depth = 0; skip = FALSE; } // start when we reach requested group
+ }
+ if(depth != header && !all || skip) continue; // skip contents of group (but print first-level header)
if(engineList[i]) free(engineList[i]);
engineList[i] = strdup(buf);
- if(*p == '\n') p++;
- TidyProgramName(engineList[i], "localhost", buf);
+ if(buf[0] != '#') TidyProgramName(engineList[i], "localhost", buf); // group headers not tidied
if(engineMnemonic[i]) free(engineMnemonic[i]);
if((q = strstr(engineList[i]+2, "variant")) && q[-2]== ' ' && (q[-1]=='/' || q[-1]=='-') && (q[7]==' ' || q[7]=='=')) {
strcat(buf, " (");
strcat(buf, ")");
}
engineMnemonic[i] = strdup(buf);
- names = p; i++;
- if(i > MAXENGINES - 2) break;
+ i++;
}
engineList[i] = engineMnemonic[i] = NULL;
+ return i;
}
// following implemented as macro to avoid type limitations
int n;
// SwapEngines(1); // bump first to second
// ReplaceEngine(&second, 1); // and load it there
- NamesToList(firstChessProgramNames, command, mnemonic); // get mnemonics of installed engines
+ NamesToList(firstChessProgramNames, command, mnemonic, "all"); // get mnemonics of installed engines
n = SetPlayer(nr, recentEngines); // select new (using original menu order!)
if(mnemonic[n]) { // if somehow the engine with the selected nickname is no longer found in the list, we skip
ReplaceEngine(&first, 0);
if(first.pr != NoProc && second.pr != NoProc) return 1; // engines already loaded
// redefine engines, engine dir, etc.
- NamesToList(firstChessProgramNames, command, mnemonic); // get mnemonics of installed engines
+ NamesToList(firstChessProgramNames, command, mnemonic, "all"); // get mnemonics of installed engines
if(first.pr == NoProc || nr < 0) {
SetPlayer(whitePlayer, appData.participants); // find white player amongst it, and parse its engine line
InitEngine(&first, 0); // initialize ChessProgramStates based on new settings.
if(!cps) {\r
char *p;\r
p = (optionList[j].type != FileName ? strdup(text) : InterpretFileName(text, homeDir)); // all files relative to homeDir!\r
- FREE(*(char**)optionList[j].target); *(char**)optionList[j].target = p;
+ FREE(*(char**)optionList[j].target); *(char**)optionList[j].target = p;\r
free(text); text = p;\r
while(*p++ = *text++) if(p[-1] == '\r') p--; // crush CR\r
break;\r
}\r
if(j < 0) break;\r
if(comboCallback && activeList[j].type == ComboBox && HIWORD(wParam) == CBN_SELCHANGE) {\r
+ if(j > 5) break; // Yegh! Must solve problem with more than one ombobox in dialog\r
(*comboCallback)(hDlg);\r
break;\r
} else\r
\r
int InstallOK()\r
{\r
+ if(engineLine[0] == '#') { DisplayError(_("Select single engine from the group"), 0); return 0; }\r
if(isUCCI) isUCI = 2;\r
if(engineChoice[0] == engineNr[0][0]) Load(&first, 0); else Load(&second, 1);\r
return 1;\r
return;\r
}\r
\r
-void LoadEnginePopUp(HWND hwnd)\r
+int\r
+EnterGroup(HWND hDlg)\r
{\r
- int n=0;\r
+ char buf[MSG_SIZ];\r
+ HANDLE hwndCombo = GetDlgItem(hDlg, 2001+2*1);\r
+ int i = ComboBox_GetCurSel(hwndCombo);\r
+ if(i == 0) buf[0] = NULLCHAR; // back to top level\r
+ else if(engineList[i][0] == '#') safeStrCpy(buf, engineList[i], MSG_SIZ); // group header, open group\r
+ else return 0; // normal line, select engine\r
+ installOptions[0].max = NamesToList(firstChessProgramNames, engineList, engineMnemonic, buf); // replace list by only the group contents\r
+ SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0);\r
+ SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) buf);\r
+ for(i=1; i<installOptions[0].max; i++) {\r
+ SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) engineMnemonic[i]);\r
+ }\r
+ SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) 0, (LPARAM) buf);\r
+ return 0;\r
+}\r
\r
+void LoadEnginePopUp(HWND hwnd)\r
+{\r
isUCI = isUCCI = storeVariant = v1 = useNick = FALSE; addToList = hasBook = TRUE; // defaults\r
if(engineDir) free(engineDir); engineDir = strdup("");\r
if(params) free(params); params = strdup("");\r
if(engineChoice) free(engineChoice); engineChoice = strdup(engineNr[0]);\r
if(engineLine) free(engineLine); engineLine = strdup("");\r
if(engineName) free(engineName); engineName = strdup("");\r
- NamesToList(firstChessProgramNames, engineList, engineMnemonic);\r
- while(engineList[n]) n++; installOptions[0].max = n;\r
+ installOptions[0].max = NamesToList(firstChessProgramNames, engineList, engineMnemonic, ""); // only top level\r
snprintf(title, MSG_SIZ, _("Load Engine"));\r
+ comboCallback = &EnterGroup;\r
\r
GenericPopup(hwnd, installOptions);\r
}\r
{ 0, 0, 4, NULL, (void*) &tfName, "", NULL, FileName, N_("Tournament file:") },\r
{ 30, 0, 0, NULL, NULL, NULL, NULL, Label, N_("If you specify an existing file, the rest of this dialog will be ignored.") },\r
{ 30, 0, 0, NULL, NULL, NULL, NULL, Label, N_("Otherwise, the file will be created, with the settings you specify below:") },\r
- { 0, 1, 0, NULL, (void*) &engineChoice, (char*) (engineMnemonic+1), (engineMnemonic+1), ComboBox, N_("Select Engine:") },\r
+ { 0, 1, 0, NULL, (void*) &engineChoice, (char*) engineMnemonic, engineMnemonic, ComboBox, N_("Select Engine:") },\r
{ 0xD, 7, 0, NULL, (void*) &appData.participants, "", NULL, TextBox, N_("Tourney participants:") },\r
{ 0, 0, 0, NULL, (void*) &swiss, "", NULL, CheckBox, N_("Use Swiss pairing engine (cycles = rounds)") },\r
{ 0, 0, 10, NULL, (void*) &appData.tourneyType, "", NULL, Spin, N_("Tourney type (0=RR, 1=gauntlet):") },\r
\r
int AddToTourney(HWND hDlg)\r
{\r
- char buf[MSG_SIZ];\r
-// GetDlgItemText( hDlg, 2001+2*7, buf, MSG_SIZ-3 ); // this gives the previous selection !!!\r
-// strncat(buf, "\r\n", MSG_SIZ);\r
- int i = ComboBox_GetCurSel(GetDlgItem(hDlg, 2001+2*7));\r
- snprintf(buf, MSG_SIZ, "%s\r\n", engineMnemonic[i+1]);\r
+ char buf[MSG_SIZ];\r
+ HANDLE hwndCombo = GetDlgItem(hDlg, 2001+2*7);\r
+ int i = ComboBox_GetCurSel(hwndCombo);\r
+ if(i == 0) buf[0] = NULLCHAR; // back to top level\r
+ else if(engineList[i][0] == '#') safeStrCpy(buf, engineList[i], MSG_SIZ); // group header, open group\r
+ else { // normal line, select engine\r
+ snprintf(buf, MSG_SIZ, "%s\r\n", engineMnemonic[i]);\r
SendMessage( GetDlgItem(hDlg, 2001+2*9), EM_SETSEL, 99999, 99999 );\r
SendMessage( GetDlgItem(hDlg, 2001+2*9), EM_REPLACESEL, (WPARAM) FALSE, (LPARAM) buf );\r
return 0;\r
+ }\r
+ installOptions[0].max = NamesToList(firstChessProgramNames, engineList, engineMnemonic, buf); // replace list by only the group contents\r
+ SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0);\r
+ SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) buf);\r
+ for(i=1; i<installOptions[0].max; i++) {\r
+ SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) engineMnemonic[i]);\r
+ }\r
+ SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) 0, (LPARAM) buf);\r
+ return 0;\r
}\r
\r
void TourneyPopup(HWND hwnd)\r
{\r
- int n=0;\r
-\r
- NamesToList(firstChessProgramNames, engineList, engineMnemonic);\r
+ int n = NamesToList(firstChessProgramNames, engineList, engineMnemonic, "");\r
comboCallback = &AddToTourney;\r
autoinc = appData.loadGameIndex < 0 || appData.loadPositionIndex < 0;\r
twice = FALSE; swiss = appData.tourneyType < 0;\r
- while(engineList[n]) n++; tourneyOptions[3].max = n-1;\r
+ tourneyOptions[3].max = n;\r
snprintf(title, MSG_SIZ, _("Tournament and Match Options"));\r
ASSIGN(tfName, appData.tourneyFile[0] ? appData.tourneyFile : MakeName(appData.defName));\r
\r