From 657beffbe986b3969f625dfe25203dae521ba797 Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Wed, 8 Feb 2012 23:25:31 +0100 Subject: [PATCH] Allow grouping of engines in engine list Lines "# GROUPNAME" and "# end" enclose a group in -firstChessProgramNames. --- backend.c | 33 ++++++++++++++++++---------- backend.h | 2 +- winboard/wsettings.c | 58 +++++++++++++++++++++++++++++++++++++------------- xoptions.c | 4 +- 4 files changed, 67 insertions(+), 30 deletions(-) diff --git a/backend.c b/backend.c index 92a228d..a4564d8 100644 --- a/backend.c +++ b/backend.c @@ -9808,7 +9808,7 @@ Substitute (char *participants, int expunge) 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; @@ -9877,19 +9877,28 @@ CreateTourney (char *name) 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, " ("); @@ -9897,10 +9906,10 @@ NamesToList (char *names, char **engineList, char **engineMnemonic) 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 @@ -9952,7 +9961,7 @@ RecentEngineEvent (int nr) 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); @@ -10063,7 +10072,7 @@ NextTourneyGame (int nr, int *swapColors) 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. diff --git a/backend.h b/backend.h index ce09c98..561a0b3 100644 --- a/backend.h +++ b/backend.h @@ -304,7 +304,7 @@ void InitSearch P((void)); int GameContainsPosition P((FILE *f, ListGame *lg)); void GLT_TagsToList P(( char * tags )); void GLT_ParseList P((void)); -void NamesToList P((char *name, char **engines, char **mnemonics)); +int NamesToList P((char *name, char **engines, char **mnemonics, char *group)); int CreateTourney P((char *name)); char *MakeName P((char *templ)); void SwapEngines P((int n)); diff --git a/winboard/wsettings.c b/winboard/wsettings.c index 83472f5..10bb427 100644 --- a/winboard/wsettings.c +++ b/winboard/wsettings.c @@ -366,7 +366,7 @@ GetOptionValues(HWND hDlg, ChessProgramState *cps, Option *optionList) if(!cps) { char *p; p = (optionList[j].type != FileName ? strdup(text) : InterpretFileName(text, homeDir)); // all files relative to homeDir! - FREE(*(char**)optionList[j].target); *(char**)optionList[j].target = p; + FREE(*(char**)optionList[j].target); *(char**)optionList[j].target = p; free(text); text = p; while(*p++ = *text++) if(p[-1] == '\r') p--; // crush CR break; @@ -480,6 +480,7 @@ LRESULT CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa } if(j < 0) break; if(comboCallback && activeList[j].type == ComboBox && HIWORD(wParam) == CBN_SELCHANGE) { + if(j > 5) break; // Yegh! Must solve problem with more than one ombobox in dialog (*comboCallback)(hDlg); break; } else @@ -628,6 +629,7 @@ EngineOptionsPopup(HWND hwnd, ChessProgramState *cps) int InstallOK() { + if(engineLine[0] == '#') { DisplayError(_("Select single engine from the group"), 0); return 0; } if(isUCCI) isUCI = 2; if(engineChoice[0] == engineNr[0][0]) Load(&first, 0); else Load(&second, 1); return 1; @@ -670,10 +672,27 @@ GenericPopup(HWND hwnd, Option *optionList) return; } -void LoadEnginePopUp(HWND hwnd) +int +EnterGroup(HWND hDlg) { - int n=0; + char buf[MSG_SIZ]; + HANDLE hwndCombo = GetDlgItem(hDlg, 2001+2*1); + int i = ComboBox_GetCurSel(hwndCombo); + if(i == 0) buf[0] = NULLCHAR; // back to top level + else if(engineList[i][0] == '#') safeStrCpy(buf, engineList[i], MSG_SIZ); // group header, open group + else return 0; // normal line, select engine + installOptions[0].max = NamesToList(firstChessProgramNames, engineList, engineMnemonic, buf); // replace list by only the group contents + SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0); + SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) buf); + for(i=1; i