X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=backend.c;h=37929713badf534efd4f20f21392efc44d98aaeb;hb=d1638304f504ca6cbfa36eb7a951b530f374bd10;hp=c3a68e72b03232424323358a132a81e75e42178d;hpb=e30a78284219ac19697175114c16740c7aab850b;p=xboard.git diff --git a/backend.c b/backend.c index c3a68e7..3792971 100644 --- a/backend.c +++ b/backend.c @@ -981,13 +981,14 @@ FloatToFront(char **list, char *engineLine) ASSIGN(*list, tidy+1); } -char *insert, *wbOptions; // point in ChessProgramNames were we should insert new engine +char *insert, *wbOptions, *currentEngine[2]; // point in ChessProgramNames were we should insert new engine void Load (ChessProgramState *cps, int i) { char *p, *q, buf[MSG_SIZ], command[MSG_SIZ], buf2[MSG_SIZ], buf3[MSG_SIZ], jar; if(engineLine && engineLine[0]) { // an engine was selected from the combo box + ASSIGN(currentEngine[i], engineLine); snprintf(buf, MSG_SIZ, "-fcp %s", engineLine); SwapEngines(i); // kludge to parse -f* / -first* like it is -s* / -second* ParseArgsFromString(resetOptions); appData.pvSAN[0] = FALSE; @@ -1030,7 +1031,7 @@ Load (ChessProgramState *cps, int i) q = firstChessProgramNames; if(nickName[0]) snprintf(buf, MSG_SIZ, "\"%s\" -fcp ", nickName); else buf[0] = NULLCHAR; quote = strchr(p, '"') ? '\'' : '"'; // use single quotes around engine command if it contains double quotes - snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), "%c%s%c -fd \"%s\"%s%s%s%s%s%s%s%s\n", + snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), "%c%s%c -fd \"%s\"%s%s%s%s%s%s%s%s", quote, p, quote, appData.directory[i], useNick ? " -fn \"" : "", useNick ? nickName : "", @@ -1040,12 +1041,13 @@ Load (ChessProgramState *cps, int i) isUCI ? (isUCI == TRUE ? " -fUCI" : gameInfo.variant == VariantShogi ? " -fUSI" : " -fUCCI") : "", storeVariant ? " -variant " : "", storeVariant ? VariantName(gameInfo.variant) : ""); - if(wbOptions && wbOptions[0]) snprintf(buf+strlen(buf)-1, MSG_SIZ-strlen(buf), " %s\n", wbOptions); - firstChessProgramNames = malloc(len = strlen(q) + strlen(buf) + 1); + if(wbOptions && wbOptions[0]) snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " %s", wbOptions); + firstChessProgramNames = malloc(len = strlen(q) + strlen(buf) + 2); if(insert != q) insert[-1] = NULLCHAR; - snprintf(firstChessProgramNames, len, "%s\n%s%s", q, buf, insert); + snprintf(firstChessProgramNames, len, "%s\n%s\n%s", q, buf, insert); if(q) free(q); FloatToFront(&appData.recentEngineList, buf); + ASSIGN(currentEngine[i], buf); } ReplaceEngine(cps, i); } @@ -1591,8 +1593,6 @@ MatchEvent (int mode) NextMatchGame(); } -char *comboLine = NULL; // [HGM] recent: WinBoard's first-engine combobox line - void InitBackEnd3 P((void)) { @@ -1624,7 +1624,7 @@ InitBackEnd3 P((void)) free(programVersion); programVersion = (char*) malloc(8 + strlen(PACKAGE_STRING) + strlen(first.tidy)); sprintf(programVersion, "%s + %s", PACKAGE_STRING, first.tidy); - FloatToFront(&appData.recentEngineList, comboLine ? comboLine : appData.firstChessProgram); + FloatToFront(&appData.recentEngineList, currentEngine[0] ? currentEngine[0] : appData.firstChessProgram); } if (appData.icsActive) { @@ -10928,31 +10928,47 @@ InitChessProgram (ChessProgramState *cps, int setup) } -void -ResendOptions (ChessProgramState *cps) +char * +ResendOptions (ChessProgramState *cps, int toEngine) { // send the stored value of the options int i; - char buf[MSG_SIZ]; + static char buf2[MSG_SIZ*10]; + char buf[MSG_SIZ], *p = buf2; Option *opt = cps->option; + *p = NULLCHAR; for(i=0; inrOptions; i++, opt++) { + *buf = NULLCHAR; switch(opt->type) { case Spin: case Slider: case CheckBox: - snprintf(buf, MSG_SIZ, "option %s=%d\n", opt->name, opt->value); + if(opt->value != *(int*) (opt->name + MSG_SIZ - 104)) + snprintf(buf, MSG_SIZ, "%s=%d", opt->name, opt->value); break; case ComboBox: - snprintf(buf, MSG_SIZ, "option %s=%s\n", opt->name, opt->choice[opt->value]); + if(opt->value != *(int*) (opt->name + MSG_SIZ - 104)) + snprintf(buf, MSG_SIZ, "%s=%s", opt->name, opt->choice[opt->value]); break; default: - snprintf(buf, MSG_SIZ, "option %s=%s\n", opt->name, opt->textValue); + if(strcmp(opt->textValue, opt->name + MSG_SIZ - 100)) + snprintf(buf, MSG_SIZ, "%s=%s", opt->name, opt->textValue); break; case Button: case SaveButton: continue; } - SendToProgram(buf, cps); + if(*buf) { + if(toEngine) { + snprintf(buf2, MSG_SIZ, "option %s\n", buf); + SendToProgram(buf2, cps); + } else { + if(p != buf2) *p++ = ','; + strncpy(p, buf, 10*MSG_SIZ-1 - (p - buf2)); + while(*p) p++; + } + } } + return buf2; } void @@ -11000,7 +11016,7 @@ StartChessProgram (ChessProgramState *cps) cps->comboCnt = 0; // and values of combo boxes } SendToProgram(buf, cps); - if(cps->reload) ResendOptions(cps); + if(cps->reload) ResendOptions(cps, TRUE); } else { SendToProgram("xboard\n", cps); } @@ -11254,6 +11270,32 @@ NamesToList (char *names, char **engineList, char **engineMnemonic, char *group) return i; } +void +SaveEngineSettings (int n) +{ + int len; char *p, *q, *s, buf[MSG_SIZ], *optionSettings; + if(!currentEngine[n] || !currentEngine[n][0]) { DisplayMessage("saving failed: engine not from list", ""); return; } // no engine from list is loaded + p = strstr(firstChessProgramNames, currentEngine[n]); + if(!p) { DisplayMessage("saving failed: engine not found in list", ""); return; } // sanity check; engine could be deleted from list after loading + optionSettings = ResendOptions(n ? &second : &first, FALSE); + len = strlen(currentEngine[n]); + q = p + len; *p = 0; // cut list into head and tail piece + s = strstr(currentEngine[n], "firstOptions"); + if(s && (s[-1] == '-' || s[-1] == '/') && (s[12] == ' ' || s[12] == '=') && (s[13] == '"' || s[13] == '\'')) { + char *r = s + 14; + while(*r && *r != s[13]) r++; + s[14] = 0; // cut currentEngine into head and tail part, removing old settings + snprintf(buf, MSG_SIZ, "%s%s%s", currentEngine[n], optionSettings, *r ? r : "\""); // synthesize new engine line + } else if(*optionSettings) { + snprintf(buf, MSG_SIZ, "%s -firstOptions \"%s\"", currentEngine[n], optionSettings); + } + ASSIGN(currentEngine[n], buf); // updated engine line + len = p - firstChessProgramNames + strlen(q) + strlen(currentEngine[n]) + 1; + s = malloc(len); + snprintf(s, len, "%s%s%s", firstChessProgramNames, currentEngine[n], q); + FREE(firstChessProgramNames); firstChessProgramNames = s; // new list +} + // following implemented as macro to avoid type limitations #define SWAP(item, temp) temp = appData.item[0]; appData.item[0] = appData.item[n]; appData.item[n] = temp; @@ -11301,6 +11343,7 @@ GetEngineLine (char *s, int n) if(n == 1) SwapEngines(n); ParseArgsFromString(buf); if(n == 1) SwapEngines(n); + if(n < 2) { ASSIGN(currentEngine[n], command[i]); } if(n == 0 && *appData.secondChessProgram == NULLCHAR) { SwapEngines(1); // set second same as first if not yet set (to suppress WB startup dialog) ParseArgsFromString(buf); @@ -15032,7 +15075,7 @@ WaitForEngine (ChessProgramState *cps, DelayedEventCallback retry) void TwoMachinesEvent P((void)) { - int i; + int i, move = forwardMostMove; char buf[MSG_SIZ]; ChessProgramState *onmove; char *bookHit = NULL; @@ -15149,8 +15192,8 @@ TwoMachinesEvent P((void)) } } - ResetClocks(); - if (!first.sendTime || !second.sendTime) { + if (!first.sendTime || !second.sendTime || move == 0) { // [HGM] first engine changed sides from Reset, so recalc time odds + ResetClocks(); timeRemaining[0][forwardMostMove] = whiteTimeRemaining; timeRemaining[1][forwardMostMove] = blackTimeRemaining; } @@ -17176,8 +17219,10 @@ StringFeature (char **p, char *name, char **loc, ChessProgramState *cps) if (strncmp((*p), name, len) == 0 && (*p)[len] == '=' && (*p)[len+1] == '\"') { (*p) += len + 2; - ASSIGN(*loc, *p); // kludge alert: assign rest of line just to be sure allocation is large enough so that sscanf below always fits - sscanf(*p, "%[^\"]", *loc); + len = strlen(*p) + 1; if(len < MSG_SIZ && !strcmp(name, "option")) len = MSG_SIZ; // make sure string options have enough space to change their value + FREE(*loc); *loc = malloc(len); + strncpy(*loc, *p, len); + sscanf(*p, "%[^\"]", *loc); // should always fit, because we allocated at least strlen(*p) while (**p && **p != '\"') (*p)++; if (**p == '\"') (*p)++; snprintf(buf, MSG_SIZ, "accepted %s\n", name); @@ -17279,6 +17324,8 @@ ParseOption (Option *opt, ChessProgramState *cps) strcat(buf, "\n"); SendToProgram(buf, cps); } + *(int*) (opt->name + MSG_SIZ - 104) = opt->value; // hide default values somewhere + if(opt->target == &opt->textValue) strncpy(opt->name + MSG_SIZ - 100, opt->textValue, 99); return TRUE; } @@ -17359,6 +17406,7 @@ ParseFeatures (char *args, ChessProgramState *cps) if (StringFeature(&p, "egt", &cps->egtFormats, cps)) continue; if (StringFeature(&p, "option", &q, cps)) { // read to freshly allocated temp buffer first if(cps->reload) { FREE(q); q = NULL; continue; } // we are reloading because of xreuse + if(cps->nrOptions == 0) { ASSIGN(cps->option[0].name, _("Make Persistent -save")); ParseOption(&(cps->option[cps->nrOptions++]), cps); } FREE(cps->option[cps->nrOptions].name); cps->option[cps->nrOptions].name = q; q = NULL; if(!ParseOption(&(cps->option[cps->nrOptions++]), cps)) { // [HGM] options: add option feature