From 407cd1126c6c24d890359f1fe1686f6d90c0ad61 Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Wed, 8 Jun 2011 16:44:16 +0200 Subject: [PATCH] Let XBoard propose name of tourney file Add an option -defaultTourneyName to configure the name that will be proposed in the Tournament Options dialog's tournament-file field. The option can contain %y, %M, %d, %h, %m, %s for year, month, day, hour, mintes, seconds of the curret time in %02d format, or %Y for the year in %04d format. Any tournament -file name is ignored when no participants are given. Participants without a tourney file remains an error. --- args.h | 1 + backend.c | 39 ++++++++++++++++++++++++++++++++++++--- backend.h | 1 + common.h | 1 + winboard/wsettings.c | 9 +++++---- xboard.conf.in | 1 + xoptions.c | 7 ++++--- 7 files changed, 49 insertions(+), 10 deletions(-) diff --git a/args.h b/args.h index faaf63f..b3776ee 100644 --- a/args.h +++ b/args.h @@ -622,6 +622,7 @@ ArgDescriptor argDescriptors[] = { { "sn", ArgString, (void *) &appData.pgnName[1], FALSE, INVALID }, { "absoluteAnalysisScores", ArgBoolean, (void *) &appData.whitePOV, TRUE, FALSE }, { "pairingEngine", ArgFilename, (void *) &appData.pairingEngine, TRUE, "" }, + { "defaultTourneyName", ArgFilename, (void *) &appData.defName, TRUE, "" }, #if ZIPPY { "zippyTalk", ArgBoolean, (void *) &appData.zippyTalk, FALSE, (ArgIniType) ZIPPY_TALK }, diff --git a/backend.c b/backend.c index 51f348e..c73d6e7 100644 --- a/backend.c +++ b/backend.c @@ -9553,6 +9553,35 @@ TwoMachinesEventIfReady P((void)) TwoMachinesEvent(); } +char * +MakeName(char *template) +{ + time_t clock; + struct tm *tm; + static char buf[MSG_SIZ]; + char *p = buf; + int i; + + clock = time((time_t *)NULL); + tm = localtime(&clock); + + while(*p++ = *template++) if(p[-1] == '%') { + switch(*template++) { + case 0: *p = 0; return buf; + case 'Y': i = tm->tm_year+1900; break; + case 'y': i = tm->tm_year-100; break; + case 'M': i = tm->tm_mon+1; break; + case 'd': i = tm->tm_mday; break; + case 'h': i = tm->tm_hour; break; + case 'm': i = tm->tm_min; break; + case 's': i = tm->tm_sec; break; + default: i = 0; + } + snprintf(p-1, MSG_SIZ-10 - (p - buf), "%02d", i); p += strlen(p); + } + return buf; +} + int CountPlayers(char *p) { @@ -9596,17 +9625,21 @@ CreateTourney(char *name) { FILE *f; if(name[0] == NULLCHAR) { - DisplayError(_("You must supply a tournament file,\nfor storing the tourney progress"), 0); + if(appData.participants[0]) + DisplayError(_("You must supply a tournament file,\nfor storing the tourney progress"), 0); return 0; } - f = fopen(appData.tourneyFile, "r"); + f = fopen(name, "r"); if(f) { // file exists + ASSIGN(appData.tourneyFile, name); ParseArgsFromFile(f); // parse it } else { - if(CountPlayers(appData.participants) < appData.tourneyType + (!appData.tourneyType) + 1) { + if(!appData.participants[0]) return 0; // ignore tourney file if non-existing & no participants + if(CountPlayers(appData.participants) < (appData.tourneyType>0 ? appData.tourneyType+1 : 2)) { DisplayError(_("Not enough participants"), 0); return 0; } + ASSIGN(appData.tourneyFile, name); if((f = WriteTourneyFile("")) == NULL) return 0; } fclose(f); diff --git a/backend.h b/backend.h index ebcc74f..c4b6bb2 100644 --- a/backend.h +++ b/backend.h @@ -296,6 +296,7 @@ void GLT_TagsToList P(( char * tags )); void GLT_ParseList P((void)); void NamesToList P((char *name, char **engines, char **mnemonics)); int CreateTourney P((char *name)); +char *MakeName P((char *templ)); void SwapEngines P((int n)); extern char* StripHighlight P((char *)); /* returns static data */ diff --git a/common.h b/common.h index c52cd9f..ad52fb9 100644 --- a/common.h +++ b/common.h @@ -650,6 +650,7 @@ typedef struct { Boolean whitePOV; char *tourneyFile; + char *defName; char *processes; char *results; char *participants; diff --git a/winboard/wsettings.c b/winboard/wsettings.c index 023eb2d..84c02cb 100644 --- a/winboard/wsettings.c +++ b/winboard/wsettings.c @@ -362,7 +362,7 @@ GetOptionValues(HWND hDlg, ChessProgramState *cps, Option *optionList) if(cps) len = MSG_SIZ - strlen(optionList[j].name) - 9, text = newText; else len = GetWindowTextLength(GetDlgItem(hDlg, 2001+2*i)) + 1, text = (char*) malloc(len); success = GetDlgItemText( hDlg, 2001+2*i, text, len ); - if(!success) break; + if(!success) text[0] = NULLCHAR; // empty string can be valid input if(!cps) { char *p; p = (optionList[j].type != FileName ? strdup(text) : InterpretFileName(text, homeDir)); // all files relative to homeDir! @@ -687,17 +687,18 @@ void LoadEnginePopUp(HWND hwnd) } Boolean autoinc, twice, swiss; +char *tfName; int MatchOK() { if(autoinc) appData.loadGameIndex = appData.loadPositionIndex = -(twice + 1); if(swiss) { appData.defaultMatchGames = 1; appData.tourneyType = -1; } - if(CreateTourney(appData.tourneyFile)) MatchEvent(2); else return 0; + if(CreateTourney(tfName)) MatchEvent(2); else return !appData.participants[0]; return 1; } Option tourneyOptions[] = { - { 0, 0, 4, NULL, (void*) &appData.tourneyFile, "", NULL, FileName, N_("Tournament file:") }, + { 0, 0, 4, NULL, (void*) &tfName, "", NULL, FileName, N_("Tournament file:") }, { 30, 0, 0, NULL, NULL, NULL, NULL, Label, N_("If you specify an existing file, the rest of this dialog will be ignored.") }, { 30, 0, 0, NULL, NULL, NULL, NULL, Label, N_("Otherwise, the file will be created, with the settings you specify below:") }, { 0, 1, 0, NULL, (void*) &engineChoice, (char*) (engineMnemonic+1), (engineMnemonic+1), ComboBox, N_("Select Engine:") }, @@ -742,7 +743,7 @@ void TourneyPopup(HWND hwnd) twice = TRUE; swiss = appData.tourneyType < 0; while(engineList[n]) n++; tourneyOptions[3].max = n-1; snprintf(title, MSG_SIZ, _("Tournament and Match Options")); - if(appData.pairingEngine[0]) tourneyOptions[5].min = -19; + ASSIGN(tfName, appData.tourneyFile[0] ? appData.tourneyFile : MakeName(appData.defName)); GenericPopup(hwnd, tourneyOptions); } diff --git a/xboard.conf.in b/xboard.conf.in index edd1cf9..63f56c9 100644 --- a/xboard.conf.in +++ b/xboard.conf.in @@ -48,6 +48,7 @@ -msLoginDelay 0 -delayBeforeQuit 0 -delayAfterQuit 0 +-defaultTourneyName "Tourney_%y%M%d_%h%m.trn" ; ; PGN format & Game List ; diff --git a/xoptions.c b/xoptions.c index b47f9a4..f3e8f67 100644 --- a/xoptions.c +++ b/xoptions.c @@ -780,7 +780,7 @@ void GenericPopDown(w, event, prms, nprms) PopDown(prms[0][0] - '0'); } -char *engineName, *engineDir, *engineChoice, *engineLine, *nickName, *params; +char *engineName, *engineDir, *engineChoice, *engineLine, *nickName, *params, *tfName; Boolean isUCI, hasBook, storeVariant, v1, addToList, useNick; extern Option installOptions[], matchOptions[]; char *engineNr[] = { N_("First Engine"), N_("Second Engine"), NULL }; @@ -803,14 +803,14 @@ int MatchOK(int n) { if(appData.participants && appData.participants[0]) free(appData.participants); appData.participants = strdup(engineName); - if(!CreateTourney(appData.tourneyFile)) return 0; + if(!CreateTourney(tfName)) return !appData.participants[0]; PopDown(0); // early popdown to prevent FreezeUI called through MatchEvent from causing XtGrab warning MatchEvent(2); // start tourney return 1; } Option matchOptions[] = { -{ 0, 0, 0, NULL, (void*) &appData.tourneyFile, ".trn", NULL, FileName, N_("Tournament file:") }, +{ 0, 0, 0, NULL, (void*) &tfName, ".trn", NULL, FileName, N_("Tournament file:") }, { 0, 0, 0, NULL, (void*) &appData.roundSync, "", NULL, CheckBox, N_("Sync after round (for concurrent playing of a single") }, { 0, 0, 0, NULL, (void*) &appData.cycleSync, "", NULL, CheckBox, N_("Sync after cycle tourney with multiple XBoards)") }, { 0xD, 150, 0, NULL, (void*) &engineName, "", NULL, TextBox, "Tourney participants:" }, @@ -1771,6 +1771,7 @@ void MatchOptionsProc(w, event, prms, nprms) NamesToList(firstChessProgramNames, engineList, engineMnemonic); comboCallback = &AddToTourney; matchOptions[5].min = -(appData.pairingEngine[0] != NULLCHAR); // with pairing engine, allow Swiss + ASSIGN(tfName, appData.tourneyFile[0] ? appData.tourneyFile : MakeName(appData.defName)); GenericPopUp(matchOptions, _("Match Options"), 0); } -- 1.7.0.4