A new option -recentEngines specifies how many engines should be listed.
The list of nicknames is stored in the ettings file as -recentEngineList.
The engines are appended to the Engine menu.
{ "icsMenu", ArgString, (void *) &icsTextMenuString, TRUE, (ArgIniType) ICS_TEXT_MENU_DEFAULT },
{ "icsNames", ArgString, (void *) &icsNames, TRUE, (ArgIniType) ICS_NAMES },
{ "singleEngineList", ArgBoolean, (void *) &singleList, !XBOARD, (ArgIniType) FALSE },
+ { "recentEngines", ArgInt, (void *) &appData.recentEngines, TRUE, (ArgIniType) 6 },
+ { "recentEngineList", ArgString, (void *) &appData.recentEngineList, TRUE, (ArgIniType) "" },
{ "firstChessProgramNames", ArgString, (void *) &firstChessProgramNames,
TRUE, (ArgIniType) FCP_NAMES },
{ "secondChessProgramNames", ArgString, (void *) &secondChessProgramNames,
"-firstOptions \"\" -firstNPS -1 -fn \"\"";
void
+FloatToFront(char **list, char *engineLine)
+{
+ char buf[MSG_SIZ], tidy[MSG_SIZ], *p = buf, *q, *r = buf;
+ int i=0;
+ if(appData.recentEngines <= 0) return;
+ TidyProgramName(engineLine, "localhost", tidy+1);
+ tidy[0] = buf[0] = '\n'; strcat(tidy, "\n");
+ strncpy(buf+1, *list, MSG_SIZ-50);
+ if(p = strstr(buf, tidy)) { // tidy name appears in list
+ q = strchr(++p, '\n'); if(q == NULL) return; // malformed, don't touch
+ while(*p++ = *++q); // squeeze out
+ }
+ strcat(tidy, buf+1); // put list behind tidy name
+ p = tidy + 1; while(q = strchr(p, '\n')) i++, r = p, p = q + 1; // count entries in new list
+ if(i > appData.recentEngines) *r = NULLCHAR; // if maximum rached, strip off last
+ ASSIGN(*list, tidy+1);
+}
+
+void
Load (ChessProgramState *cps, int i)
{
char *p, *q, buf[MSG_SIZ], command[MSG_SIZ], buf2[MSG_SIZ];
ParseArgsFromString(buf);
SwapEngines(i);
ReplaceEngine(cps, i);
+ FloatToFront(&appData.recentEngineList, engineLine);
return;
}
p = engineName;
firstChessProgramNames = malloc(len = strlen(q) + strlen(buf) + 1);
snprintf(firstChessProgramNames, len, "%s%s", q, buf);
if(q) free(q);
+ FloatToFront(&appData.recentEngineList, buf);
}
ReplaceEngine(cps, i);
}
free(programVersion);
programVersion = (char*) malloc(8 + strlen(PACKAGE_STRING) + strlen(first.tidy));
sprintf(programVersion, "%s + %s", PACKAGE_STRING, first.tidy);
+ FloatToFront(&appData.recentEngineList, appData.firstChessProgram);
}
if (appData.icsActive) {
SWAP(engOptions, p)
}
-void
-SetPlayer (int player)
+int
+SetPlayer (int player, char *p)
{ // [HGM] find the engine line of the partcipant given by number, and parse its options.
int i;
- char buf[MSG_SIZ], *engineName, *p = appData.participants;
+ char buf[MSG_SIZ], *engineName;
for(i=0; i<player; i++) p = strchr(p, '\n') + 1;
engineName = strdup(p); if(p = strchr(engineName, '\n')) *p = NULLCHAR;
for(i=1; command[i]; i++) if(!strcmp(mnemonic[i], engineName)) break;
ParseArgsFromString(buf);
}
free(engineName);
+ return i;
+}
+
+char *recentEngines;
+
+void
+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
+ 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);
+ FloatToFront(&appData.recentEngineList, command[n]);
+ }
}
int
// redefine engines, engine dir, etc.
NamesToList(firstChessProgramNames, command, mnemonic); // get mnemonics of installed engines
if(first.pr == NoProc || nr < 0) {
- SetPlayer(whitePlayer); // find white player amongst it, and parse its engine line
+ SetPlayer(whitePlayer, appData.participants); // find white player amongst it, and parse its engine line
InitEngine(&first, 0); // initialize ChessProgramStates based on new settings.
}
if(second.pr == NoProc) {
SwapEngines(1);
- SetPlayer(blackPlayer); // find black player amongst it, and parse its engine line
+ SetPlayer(blackPlayer, appData.participants); // find black player amongst it, and parse its engine line
SwapEngines(1); // and make that valid for second engine by swapping
InitEngine(&second, 1);
}
void AnalyzeModeEvent P((void));
void AnalyzeFileEvent P((void));
void MatchEvent P((int mode));
+void RecentEngineEvent P((int nr));
void TypeInEvent P((char first));
void TypeInDoneEvent P((char *move));
void InitPosition P((int redraw));
extern ChessProgramStats programStats;
extern int opponentKibitzes; // used by wengineo.c
extern int errorExitStatus;
+extern char *recentEngines;
void SettingsPopUp P((ChessProgramState *cps)); // [HGM] really in front-end, but CPS not known in frontend.h
int WaitForEngine P((ChessProgramState *cps, DelayedEventCallback x));
void Load P((ChessProgramState *cps, int n));
Boolean scoreWhite;
Boolean pvSAN[ENGINES];
+ int recentEngines;
+ char *recentEngineList;
char *tourneyFile;
char *defName;
char *processes;
info.dwTypeData = buf;\r
info.cch = sizeof(buf);\r
GetMenuItemInfo(subMenu, j, TRUE, &info);\r
- if(i < 10) {
+ if(i < 10) {\r
if(menuText[i][j]) safeStrCpy(buf, menuText[i][j], sizeof(buf)/sizeof(buf[0]) );\r
else menuText[i][j] = strdup(buf); // remember original on first change\r
}\r
\r
#endif\r
\r
+#define IDM_RecentEngines 3000\r
+\r
+void\r
+RecentEngineMenu (char *s)\r
+{\r
+ if(appData.recentEngines > 0 && *s) { // feature is on, and list non-empty\r
+ HMENU mainMenu = GetMenu(hwndMain);\r
+ HMENU subMenu = GetSubMenu(mainMenu, 5); // Engine menu\r
+ int i=IDM_RecentEngines;\r
+ recentEngines = strdup(appData.recentEngineList); // remember them as they are in menu\r
+ AppendMenu(subMenu, MF_SEPARATOR, (UINT_PTR) 0, NULL);\r
+ while(*s) {\r
+ char *p = strchr(s, '\n');\r
+ if(p == NULL) return; // malformed!\r
+ *p = NULLCHAR;\r
+ AppendMenu(subMenu, MF_ENABLED|MF_STRING|MF_UNCHECKED, (UINT_PTR) i++, (LPCTSTR) s);\r
+ *p = '\n';\r
+ s = p+1;\r
+ }\r
+ }\r
+}\r
+\r
+\r
typedef struct {\r
char *name;\r
int squareSize;\r
}\r
\r
InitDrawingSizes(boardSize, 0);\r
+ RecentEngineMenu(appData.recentEngineList);\r
InitMenuChecks();\r
buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);\r
\r
}\r
break;\r
case 2:\r
- SetCapture(hwndMain);
+ SetCapture(hwndMain);\r
break;\r
case 1:\r
hmenu = LoadMenu(hInst, "DropPieceMenu");\r
break;\r
\r
default:\r
+ if(wmId >= IDM_RecentEngines && wmId < IDM_RecentEngines + appData.recentEngines)\r
+ RecentEngineEvent(wmId - 3000);\r
+ else\r
if(wmId > IDM_English && wmId < IDM_English+20) {\r
LoadLanguageFile(languageFile[wmId - IDM_English - 1]);\r
TranslateMenus(0);\r
ParseArgs(StringGet, &p);\r
safeStrCpy(buf, singleList ? "/fcp=" : "/scp=", sizeof(buf)/sizeof(buf[0]) );\r
GetDlgItemText(hDlg, OPT_SecondChessEngineName, buf + strlen(buf), sizeof(buf) - strlen(buf));\r
- p = buf;
+ p = buf;\r
SwapEngines(singleList); // temporarily swap first and second, to load a second 'first', ...\r
ParseArgs(StringGet, &p);\r
SwapEngines(singleList); // ... and then make it 'second'\r
\r
case WM_COMMAND:\r
switch (LOWORD(wParam)) {\r
- case IDOK:
+ case IDOK:\r
\r
shiftKey = GetKeyState(VK_SHIFT) < 0; // [HGM] remember last shift status\r
- GetDlgItemText(hDlg, OPT_Move, move, sizeof(move));
+ GetDlgItemText(hDlg, OPT_Move, move, sizeof(move));\r
TypeInDoneEvent(move);\r
EndDialog(hDlg, TRUE);\r
return TRUE;\r
HFONT oldFont;\r
RECT rect;\r
\r
- if(copyNumber > 1)
+ if(copyNumber > 1)\r
snprintf(buf, sizeof(buf)/sizeof(buf[0]),"%d", copyNumber); else buf[0] = 0;\r
\r
oldFg = SetTextColor(hdc, RGB(255, 255, 255)); /* white */\r
if (len > remain) len = remain;\r
strncat(messageText, str2, len);\r
}\r
- messageText[MESSAGE_TEXT_MAX - 1] = NULLCHAR;
- safeStrCpy(lastMsg, messageText, MSG_SIZ);
+ messageText[MESSAGE_TEXT_MAX - 1] = NULLCHAR;\r
+ safeStrCpy(lastMsg, messageText, MSG_SIZ);\r
\r
if (hwndMain == NULL || IsIconic(hwndMain)) return;\r
\r