X-Git-Url: http://winboard.nl/cgi-bin?p=xboard.git;a=blobdiff_plain;f=dialogs.c;h=9b4870423bd6e816db4495eb8b7eecdf32dc4d8a;hp=03770315e8949fa144633d4f135594341b3034bc;hb=HEAD;hpb=3cc857b122a0529be670b5615f7859c0cd7af947 diff --git a/dialogs.c b/dialogs.c index 0377031..9b48704 100644 --- a/dialogs.c +++ b/dialogs.c @@ -1,7 +1,7 @@ /* * dialogs.c -- platform-independent code for dialogs of XBoard * - * Copyright 2000, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc. + * Copyright 2000, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Free Software Foundation, Inc. * ------------------------------------------------------------------------ * * GNU XBoard is free software: you can redistribute it and/or modify @@ -66,6 +66,7 @@ extern char *getenv(); int values[MAX_OPTIONS]; ChessProgramState *currentCps; +char manDir[MSG_SIZ] = MANDIR; //----------------------------Generic dialog -------------------------------------------- @@ -93,11 +94,13 @@ int SetCurrentComboSelection (Option *opt) { int j; + if(currentCps) ; else if(!opt->textValue) opt->value = *(int*)opt->target; /* numeric */else { for(j=0; opt->choice[j]; j++) // look up actual value in list of possible values, to get selection nr if(*(char**)opt->target && !strcmp(*(char**)opt->target, ((char**)opt->textValue)[j])) break; opt->value = j + (opt->choice[j] == NULL); } + SetComboChoice(opt, opt->value); return opt->value; } @@ -331,8 +334,10 @@ UpgradeParticipant () static void PseudoOK () { + if(matchMode) return; GenericReadout(matchOptions, -2); // read all, but suppress calling of MatchOK ASSIGN(appData.participants, engineName); + ASSIGN(appData.tourneyFile, tfName); PopDown(MasterDlg); // early popdown to prevent FreezeUI called through MatchEvent from causing XtGrab warning } @@ -541,7 +546,7 @@ Pick (int n) } gameInfo.variant = v; - appData.variant = VariantName(v); + ASSIGN(appData.variant, VariantName(v)); shuffleOpenings = FALSE; /* [HGM] shuffle: possible shuffle reset when we switch */ startedFromPositionFile = FALSE; /* [HGM] loadPos: no longer valid in new variant */ @@ -550,8 +555,9 @@ Pick (int n) appData.NrFiles = filesTmp; appData.holdingsSize = sizeTmp; appData.pieceToCharTable = NULL; - appData.pieceNickNames = ""; - appData.colorNickNames = ""; + ASSIGN(appData.pieceNickNames, ""); + ASSIGN(appData.colorNickNames, ""); + ASSIGN(appData.men, ""); PopDown(TransientDlg); Reset(True, True); return; @@ -619,9 +625,9 @@ CommonOptionsOK (int n) static Option commonEngineOptions[] = { { 0, 0, 0, NULL, (void*) &appData.ponderNextMove, "", NULL, CheckBox, N_("Ponder Next Move") }, { 0, 0, 1000, NULL, (void*) &appData.smpCores, "", NULL, Spin, N_("Maximum Number of CPUs per Engine:") }, -{ 0, 0, 0, NULL, (void*) &appData.polyglotDir, "", NULL, PathName, N_("Polygot Directory:") }, +{ 0, 0, 0, NULL, (void*) &appData.polyglotDir, NULL, NULL, PathName, N_("Polygot Directory:") }, { 0, 0,16000, NULL, (void*) &appData.defaultHashSize, "", NULL, Spin, N_("Hash-Table Size (MB):") }, -{ 0, 0, 0, NULL, (void*) &egtPath, "", NULL, PathName, N_("EGTB Path:") }, +{ 0, 0, 0, NULL, (void*) &egtPath, NULL, NULL, PathName, N_("EGTB Path:") }, { 0, 0, 1000, NULL, (void*) &appData.defaultCacheSizeEGTB, "", NULL, Spin, N_("EGTB Cache Size (MB):") }, { 0, 0, 0, NULL, (void*) &appData.usePolyglotBook, "", NULL, CheckBox, N_("Use GUI Book") }, { 0, 0, 0, NULL, (void*) &appData.polyglotBook, ".bin", NULL, FileName, N_("Opening-Book Filename:") }, @@ -935,10 +941,10 @@ static Option boardOptions[] = { { 0, 0, 200, NULL, (void*) &appData.logoSize, "", NULL, Spin, N_("Logo Size (0=off, requires restart):") }, { 0,-1, 5, NULL, (void*) &appData.overrideLineGap, "", NULL, Spin, N_("Line Gap (-1 = default for board size):") }, { 0, 0, 0, NULL, (void*) &appData.useBitmaps, "", NULL, CheckBox, N_("Use Board Textures") }, -{ 0, 0, 0, NULL, (void*) &appData.liteBackTextureFile, ".png", NULL, FileName, N_("Light-Squares Texture File:") }, -{ 0, 0, 0, NULL, (void*) &appData.darkBackTextureFile, ".png", NULL, FileName, N_("Dark-Squares Texture File:") }, +{ 0, 0, 0, NULL, (void*) &appData.darkBackTextureFile, ".png", (char**)(intptr_t) 1, FileName, N_("Dark-Squares Texture File:") }, +{ 0, 0, 0, NULL, (void*) &appData.liteBackTextureFile, ".png", (char**)(intptr_t) 2, FileName, N_("Light-Squares Texture File:") }, { 0, 0, 0, NULL, (void*) &appData.trueColors, "", NULL, CheckBox, N_("Use external piece bitmaps with their own colors") }, -{ 0, 0, 0, NULL, (void*) &appData.pieceDirectory, "", NULL, PathName, N_("Directory with Pieces Images:") }, +{ 0, 0, 0, NULL, (void*) &appData.pieceDirectory, "", (char**)(intptr_t) 3, PathName, N_("Directory with Pieces Images:") }, { 0, 0, 0, NULL, (void*) &BoardOptionsOK, "", NULL, EndMark , "" } }; @@ -1035,6 +1041,7 @@ void SendString (char *p) { char buf[MSG_SIZ], buf2[MSG_SIZ], *q; + if(q = strstr(p, "$name")) { // in Xaw this is already intercepted if(!shellUp[TextMenuDlg] || !clickedWord[0]) return; strncpy(buf2, p, MSG_SIZ); @@ -1217,11 +1224,11 @@ NewMove () addToBookFlag = !addToBookFlag; } -static Option tagsOptions[] = { +Option tagsOptions[] = { { 0, 0, 0, NULL, NULL, NULL, NULL, Label, NULL }, -{ 200, T_VSCRL | T_FILL | T_WRAP | T_TOP, 200, NULL, (void*) &tagsText, NULL, (char **) &TagsClick, TextBox, "", &appData.tagsFont }, +{ 200, T_VSCRL | T_FILL | T_TOP, 200, NULL, (void*) &tagsText, NULL, (char **) &TagsClick, TextBox, "", &appData.tagsFont }, { 0, 0, 100, NULL, (void*) &NewMove, NULL, NULL, Button, N_("add next move") }, -{ 0,SAME_ROW,100,NULL, (void*) &changeTags, NULL, NULL, Button, N_("save changes") }, +{ 0,SAME_ROW,100,NULL, (void*) &changeTags, NULL, NULL, Button, N_("commit changes") }, { 0,SAME_ROW, 0, NULL, (void*) &NewTagsCallback, "", NULL, EndMark , "" } }; @@ -1242,9 +1249,9 @@ changeTags (int n) } void -NewTagsPopup (char *text, char *msg) +NewTagsPopup (char *text, char *msg, char *ttl) { - char *title = bookUp ? _("Edit book") : _("Tags"); + char *title = bookUp ? _("Edit book") : ttl; tagsOptions[2].type = bookUp ? Button : Skip; tagsOptions[3].min = bookUp ? SAME_ROW : 0; @@ -1255,20 +1262,28 @@ NewTagsPopup (char *text, char *msg) if(tagsText) free(tagsText); tagsText = strdup(text); tagsOptions[0].name = msg; MarkMenu("View.Tags", TagsDlg); - GenericPopUp(tagsOptions, title, TagsDlg, BoardWindow, NONMODAL, appData.topLevel); + GenericPopUp(tagsOptions + (msg == NULL), title, TagsDlg, BoardWindow, NONMODAL, appData.topLevel); } void TagsPopUp (char *tags, char *msg) { - NewTagsPopup(tags, cmailMsgLoaded ? msg : NULL); + NewTagsPopup(tags, cmailMsgLoaded ? msg : NULL, _("Tags")); } void EditTagsPopUp (char *tags, char **dest) { // wrapper to preserve old name used in back-end resPtr = dest; - NewTagsPopup(tags, NULL); + NewTagsPopup(tags, NULL, _("Tags")); +} + +void +EditAnyPopUp (char *tags, char **dest, char *title) +{ // wrapper to preserve old name used in back-end + TagsPopDown(); + resPtr = dest; + NewTagsPopup(tags, NULL, title); } void @@ -1298,10 +1313,12 @@ char *icsText; #define HISTORY_SIZE 64 static char *history[HISTORY_SIZE]; static int histIn = 0, histP = 0; +static Boolean noEcho; static void SaveInHistory (char *cmd) { + if(noEcho) return; // do not save password! if (history[histIn] != NULL) { free(history[histIn]); history[histIn] = NULL; @@ -1458,6 +1475,22 @@ SecondSettingsProc () SettingsPopUp(&second); } +void +RefreshSettingsDialog (ChessProgramState *cps, int val) +{ + if(val == 1) { // option values changed + if(shellUp[TransientDlg] && cps == currentCps) { + GenericUpdate(cps->option, -1); // normally update values when dialog is up + } + return; // and be done + } + if(val == 2) { // option list changed + if(!shellUp[TransientDlg] || cps != currentCps) return; // our dialog is not up, so nothing to do + } + PopDown(TransientDlg); // make sure any other dialog closes first + SettingsPopUp(cps); // and popup new one +} + //----------------------------------------------- Load Engine -------------------------------------- char *engineDir, *engineLine, *nickName, *params; @@ -1575,10 +1608,10 @@ static Option shuffleOptions[] = { static void SetRandom (int n) { - int r = n==2 ? -1 : random() & (1<<30)-1; + int r = n==3 ? -1 : random() & (1<<30)-1; char buf[MSG_SIZ]; snprintf(buf, MSG_SIZ, "%d", r); - SetWidgetText(&shuffleOptions[1], buf, TransientDlg); + SetWidgetText(&shuffleOptions[2], buf, TransientDlg); SetWidgetState(&shuffleOptions[0], True); } @@ -1588,10 +1621,158 @@ ShuffleMenuProc () GenericPopUp(shuffleOptions, _("New Shuffle Game"), TransientDlg, BoardWindow, MODAL, 0); } +//--------------------------------------------------- Fonts ------------------------------ + +static void AdjustFont P((int n)); + +static char *oldFont[7]; + +static int +NewFont (int n, int fnr, char *font) +{ // figure out if font changed, and if so, store it in the fonts table as a side effect + if(!strcmp(oldFont[n], font)) return 0; // not changed + ASSIGN(fontTable[fnr][initialSquareSize], font); + fontIsSet[fnr] = fontValid[fnr][initialSquareSize] = True; + return 1; // changed +} + +static int +FontsOK (int n) +{ + int i; + PopDown(TransientDlg); // Early popdown to prevent expose events frommasking each other + LockBoardSize(0); + if(NewFont(0, CLOCK_FONT, appData.clockFont)) DisplayBothClocks(); + if(NewFont(1, MESSAGE_FONT, appData.font)) { + ApplyFont(&mainOptions[W_MESSG], NULL); + for(i=1; i<6; i++) ApplyFont(&mainOptions[W_BUTTON+i], NULL); + } + LockBoardSize(1); // unlock + if(NewFont(3, EDITTAGS_FONT, appData.tagsFont)) ApplyFont(&tagsOptions[1], NULL); + if(NewFont(4, COMMENT_FONT, appData.commentFont)) ApplyFont(&commentOptions[0], NULL); + if(NewFont(5, MOVEHISTORY_FONT, appData.historyFont)) { + ApplyFont(&historyOptions[0], NULL); + ApplyFont(&engoutOptions[5], NULL); + ApplyFont(&engoutOptions[12], NULL); + } + if(NewFont(6, GAMELIST_FONT, appData.gameListFont)) ApplyFont(&gamesOptions[0], NULL); + if(NewFont(2, CONSOLE_FONT, appData.icsFont)) { + ApplyFont(&chatOptions[11], appData.icsFont); + AppendColorized(&chatOptions[6], NULL, 0); // kludge to replace font tag + } + DrawPosition(TRUE, NULL); // for coord font + return 0; // suppress normal popdown because already done +} + +static Option fontOptions[] = { + { 0, 60, 200, NULL, (void*) &appData.clockFont, NULL, NULL, TextBox, N_("Clocks (requires restart):") }, + { 1, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("+") }, + { 2, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("-") }, + { 3, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("B") }, + { 4, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("I") }, + { 666, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("*") }, + { 0, 60, 70, NULL, (void*) &appData.font, NULL, NULL, TextBox, N_("Message (above board):") }, + { 1, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("+") }, + { 2, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("-") }, + { 3, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("B") }, + { 4, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("I") }, + { 666, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("*") }, + { 0, 60, 70, NULL, (void*) &appData.icsFont, NULL, NULL, TextBox, N_("ICS Chat/Console:") }, + { 1, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("+") }, + { 2, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("-") }, + { 3, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("B") }, + { 4, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("I") }, + { 666, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("*") }, + { 0, 60, 70, NULL, (void*) &appData.tagsFont, NULL, NULL, TextBox, N_("Edit tags / book / engine list:") }, + { 1, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("+") }, + { 2, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("-") }, + { 3, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("B") }, + { 4, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("I") }, + { 666, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("*") }, + { 0, 60, 70, NULL, (void*) &appData.commentFont, NULL, NULL, TextBox, N_("Edit comments:") }, + { 1, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("+") }, + { 2, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("-") }, + { 3, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("B") }, + { 4, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("I") }, + { 666, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("*") }, + { 0, 60, 70, NULL, (void*) &appData.historyFont, NULL, NULL, TextBox, N_("Move history / Engine Output:") }, + { 1, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("+") }, + { 2, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("-") }, + { 3, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("B") }, + { 4, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("I") }, + { 666, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("*") }, + { 0, 60, 70, NULL, (void*) &appData.gameListFont, NULL, NULL, TextBox, N_("Game list:") }, + { 1, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("+") }, + { 2, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("-") }, + { 3, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("B") }, + { 4, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("I") }, + { 666, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("*") }, + { 0, 0, 0, NULL, NULL, NULL, NULL, Label, N_("\nThe * buttons will set the font to the one selected below:") }, + { 0, 0, 0, NULL, NULL, NULL, NULL, Button, "fontsel" }, + { 0, 0, 0, NULL, (void*) &FontsOK, "", NULL, EndMark , "" } +}; + +static char name[MSG_SIZ], *bold, *ital, points; + +static void +BreakUp (char *font) +{ + char *p = name, *norm; + safeStrCpy(name, font, MSG_SIZ); + bold = StrCaseStr(name, "bold"); + ital = StrCaseStr(name, "ital"); + norm = StrCaseStr(name, "normal"); + points = 0; + while(p && *p && !(points = atoi(p))) p = strchr(p+1, ' '); + if(points) p[*p == ' '] = 0; + if(bold) *bold = 0; + if(ital) *ital = 0; + if(norm) *norm = 0; +} + +static void +Collect () +{ + if(bold) strcat(name, "Bold "); + if(ital) strcat(name, "Italic "); + if(!ital && !bold && strlen(name) < 2) strncpy(name, "Normal ", MSG_SIZ); + if(points) sprintf(name + strlen(name), "%d", points); else strcat(name, "%d"); +} + +static void +AdjustFont (int n) +{ + int button = fontOptions[n].value, base = n - button; + char *oldFont; + GetWidgetText(&fontOptions[base], &oldFont); + BreakUp(oldFont); // take apart old font name + switch(button) { + case 1: points++; break; + case 2: points--; break; + case 3: if(bold) bold = NULL; else bold = name; break; + case 4: if(ital) ital = NULL; else ital = name; break; + } + Collect(); + SetWidgetText(&fontOptions[base], name, TransientDlg); + ApplyFont(&fontOptions[base], name); +} + +void +FontsProc () +{ + int i; + if(strstr(appData.font, "-*-")) { DisplayNote(_("This only works in the GTK build")); return; } + GenericPopUp(fontOptions, _("Fonts"), TransientDlg, BoardWindow, MODAL, 0); + for(i=0; i<7; i++) { + ApplyFont(&fontOptions[6*i], *(char**)fontOptions[6*i].target); + ASSIGN(oldFont[i], *(char**)fontOptions[6*i].target); + } +} + //------------------------------------------------------ Time Control ----------------------------------- static int TcOK P((int n)); -int tmpMoves, tmpTc, tmpInc, tmpOdds1, tmpOdds2, tcType; +int tmpMoves, tmpTc, tmpInc, tmpOdds1, tmpOdds2, tcType, by60; static void SetTcType P((int n)); @@ -1607,6 +1788,7 @@ static Option tcOptions[] = { { 0, 0, 0, NULL, (void*) &SetTcType, NULL, NULL, Button, N_("classical") }, { 0,SAME_ROW,0,NULL, (void*) &SetTcType, NULL, NULL, Button, N_("incremental") }, { 0,SAME_ROW,0,NULL, (void*) &SetTcType, NULL, NULL, Button, N_("fixed max") }, +{ 0, 0, 0, NULL, (void*) &by60, "", NULL, CheckBox, N_("Divide entered times by 60") }, { 0, 0, 200, NULL, (void*) &tmpMoves, NULL, NULL, Spin, N_("Moves per session:") }, { 0, 0,10000, NULL, (void*) &tmpTc, NULL, NULL, Spin, N_("Initial time (min):") }, { 0, 0, 10000, NULL, (void*) &tmpInc, NULL, NULL, Spin, N_("Increment or max (sec/move):") }, @@ -1619,10 +1801,11 @@ static Option tcOptions[] = { static int TcOK (int n) { - char *tc; + char *tc, buf[MSG_SIZ]; if(tcType == 0 && tmpMoves <= 0) return 0; if(tcType == 2 && tmpInc <= 0) return 0; - GetWidgetText(&tcOptions[4], &tc); // get original text, in case it is min:sec + GetWidgetText(&tcOptions[5], &tc); // get original text, in case it is min:sec + if(by60) snprintf(buf, MSG_SIZ, "%d:%02d", tmpTc/60, tmpTc%60), tc=buf; searchTime = 0; switch(tcType) { case 0: @@ -1634,10 +1817,10 @@ TcOK (int n) case 1: if(!ParseTimeControl(tc, tmpInc, 0)) return 0; ASSIGN(appData.timeControl, tc); - appData.timeIncrement = tmpInc; + appData.timeIncrement = (by60 ? tmpInc/60. : tmpInc); break; case 2: - searchTime = tmpInc; + searchTime = (by60 ? tmpInc/60 : tmpInc); } appData.firstTimeOdds = first.timeOdds = tmpOdds1; appData.secondTimeOdds = second.timeOdds = tmpOdds2; @@ -1650,29 +1833,34 @@ SetTcType (int n) { switch(tcType = n) { case 0: - SetWidgetText(&tcOptions[3], Value(tmpMoves), TransientDlg); - SetWidgetText(&tcOptions[4], Value(tmpTc), TransientDlg); - SetWidgetText(&tcOptions[5], _("Unused"), TransientDlg); + SetWidgetText(&tcOptions[4], Value(tmpMoves), TransientDlg); + SetWidgetText(&tcOptions[5], Value(tmpTc), TransientDlg); + SetWidgetText(&tcOptions[6], _("Unused"), TransientDlg); break; case 1: - SetWidgetText(&tcOptions[3], _("Unused"), TransientDlg); - SetWidgetText(&tcOptions[4], Value(tmpTc), TransientDlg); - SetWidgetText(&tcOptions[5], Value(tmpInc), TransientDlg); + SetWidgetText(&tcOptions[4], _("Unused"), TransientDlg); + SetWidgetText(&tcOptions[5], Value(tmpTc), TransientDlg); + SetWidgetText(&tcOptions[6], Value(tmpInc), TransientDlg); break; case 2: - SetWidgetText(&tcOptions[3], _("Unused"), TransientDlg); SetWidgetText(&tcOptions[4], _("Unused"), TransientDlg); - SetWidgetText(&tcOptions[5], Value(tmpInc), TransientDlg); + SetWidgetText(&tcOptions[5], _("Unused"), TransientDlg); + SetWidgetText(&tcOptions[6], Value(tmpInc), TransientDlg); } } void TimeControlProc () { + if(gameMode != BeginningOfGame) { + DisplayError(_("Changing time control during a game is not implemented"), 0); + return; + } tmpMoves = appData.movesPerSession; tmpInc = appData.timeIncrement; if(tmpInc < 0) tmpInc = 0; tmpOdds1 = tmpOdds2 = 1; tcType = 0; tmpTc = atoi(appData.timeControl); + by60 = 0; GenericPopUp(tcOptions, _("Time Control"), TransientDlg, BoardWindow, MODAL, 0); SetTcType(searchTime ? 2 : appData.timeIncrement < 0 ? 0 : 1); } @@ -1771,7 +1959,7 @@ PromotionPopUp (char choice) { // choice depends on variant: prepare dialog acordingly count = 8; SetPromo(_("Cancel"), --count, -1); // Beware: GenericPopUp cannot handle user buttons named "cancel" (lowe case)! - if(choice != '+') { + if(choice != '+' && !IS_SHOGI(gameInfo.variant)) { if (!appData.testLegality || gameInfo.variant == VariantSuicide || gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove) || gameInfo.variant == VariantGiveaway) { @@ -1923,7 +2111,7 @@ IcsHist (int n, Option *opt, DialogClass dlg) while(!dirty[chat = (chat + 1)%MAX_CHAT]) if(chat == start) break; if(!dirty[chat]) while(!chatPartner[chat = (chat + 1)%MAX_CHAT][0]) if(chat == start) break; - if(chat == start && hidden) chat = 0; // if all unused, start left + if(!chatPartner[chat][0]) break; // if all unused, ignore ChatSwitch(chat + 1); break; case 1: @@ -1944,6 +2132,7 @@ OutputChatMessage (int partner, char *mess) char *p = texts[partner]; int len = strlen(mess) + 1; + if(!DialogExists(ChatDlg)) return; if(p) len += strlen(p); texts[partner] = (char*) malloc(len); snprintf(texts[partner], len, "%s%s", p ? p : "", mess); @@ -1962,11 +2151,12 @@ ChatOK (int n) { // can only be called through in chat-partner text-edit, as there is no OK button char buf[MSG_SIZ]; - if(!hidden && (!partner || strcmp(partner, chatPartner[activePartner]))) { + if(!hidden && (!partner || strcmp(partner, chatPartner[activePartner]) || !*partner)) { safeStrCpy(chatPartner[activePartner], partner, MSG_SIZ); SetWidgetText(&chatOptions[CHAT_OUT], "", -1); // clear text if we alter partner SetWidgetText(&chatOptions[CHAT_IN], "", ChatDlg); // clear text if we alter partner SetWidgetLabel(&chatOptions[activePartner+1], chatPartner[activePartner][0] ? chatPartner[activePartner] : _("New Chat")); + if(!*partner) PaneSwitch(); HardSetFocus(&chatOptions[CHAT_IN], 0); } if(line[0] || hidden) { // something was typed (for ICS commands we also allow empty line!) @@ -1979,6 +2169,10 @@ ChatOK (int n) snprintf(buf, MSG_SIZ, "whisper %s\n", line); // WHISPER box uses "whisper" to send else if(!strcmp("shouts", chatPartner[activePartner])) snprintf(buf, MSG_SIZ, "shout %s\n", line); // SHOUT box uses "shout" to send + else if(!strcmp("c-shouts", chatPartner[activePartner])) + snprintf(buf, MSG_SIZ, "cshout %s\n", line); // C-SHOUT box uses "cshout" to send + else if(!strcmp("kibitzes", chatPartner[activePartner])) + snprintf(buf, MSG_SIZ, "kibitz %s\n", line); // KIBITZ box uses "kibitz" to send else { if(!atoi(chatPartner[activePartner])) { snprintf(buf, MSG_SIZ, "> %s\n", line); // echo only tells to handle, not channel @@ -2075,6 +2269,10 @@ void ConsoleWrite(char *message, int count) { if(shellUp[ChatDlg] && chatOptions[CHAT_ICS].type != Skip) { // in Xaw this is a no-op + if(*message == 7) { + message++; // remove bell + if(strcmp(message, "\n")) return; + } AppendColorized(&chatOptions[CHAT_ICS], message, count); SetInsertPos(&chatOptions[CHAT_ICS], 999999); } @@ -2115,6 +2313,23 @@ ConsoleAutoPopUp (char *buf) } else PopUpMoveDialog(*buf); } +void +EchoOn () +{ + if(!noEcho) return; + system("stty echo"); + WidgetEcho(&chatOptions[CHAT_IN], 1); + noEcho = False; +} + +void +EchoOff () +{ + system("stty -echo"); + WidgetEcho(&chatOptions[CHAT_IN], 0); + noEcho = True; +} + //--------------------------------- Game-List options dialog ------------------------------------------ char *strings[LPUSERGLT_SIZE]; @@ -2236,7 +2451,7 @@ ErrorPopDown () if (errorExitStatus != -1) ExitEvent(errorExitStatus); } -static int +int ErrorOK (int n) { dialogError = errorUp = False; @@ -2258,6 +2473,8 @@ ErrorPopUp (char *title, char *label, int modal) errorOptions[1].name = label; if(dialogError = shellUp[TransientDlg]) GenericPopUp(errorOptions+1, title, FatalDlg, TransientDlg, MODAL, 0); // pop up as daughter of the transient dialog + else if(dialogError = shellUp[MasterDlg]) + GenericPopUp(errorOptions+1, title, FatalDlg, MasterDlg, MODAL, 0); // pop up as daughter of the master dialog else GenericPopUp(errorOptions+modal, title, modal ? FatalDlg: ErrorDlg, BoardWindow, modal, 0); // kludge: option start address indicates modality } @@ -2305,6 +2522,11 @@ DisplayFatalError (String message, int error, int status) { char buf[MSG_SIZ]; + if(status == 666) { // ignore this error when ICS Console window is up + if(shellUp[ChatDlg]) return; + status = 0; + } + errorExitStatus = status; if (error == 0) { fprintf(stderr, "%s: %s\n", programName, message); @@ -2316,6 +2538,7 @@ DisplayFatalError (String message, int error, int status) } if(mainOptions[W_BOARD].handle) { if (appData.popupExitMessage) { + if(appData.icsActive) SendToICS("logout\n"); // [HGM] make sure no new games will be started ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE); } else { ExitEvent(status); @@ -2377,6 +2600,120 @@ DisplayTitle (char *text) SetWindowTitle(text, title, icon); } +char *textPtr; +char *texEscapes[] = { "s-1", "s0", "&", "*(L", "*(R", NULL }; + +int +GetNext(FILE *f) +{ + if(textPtr) return *textPtr ? *textPtr++ : EOF; + return fgetc(f); +} + +static char * +ReadLine (FILE *f) +{ + static char buf[MSG_SIZ]; + int i = 0, c; + while((c = GetNext(f)) != '\n') { if(c == EOF) return NULL; buf[i++] = c; } + buf[i] = NULLCHAR; + return buf; +} + +void +GetHelpText (FILE *f, char *name) +{ + char *line, buf[MSG_SIZ], title[MSG_SIZ], text[10000], *p = text, *q = text; + int len, cnt = 0; + while(*name == '\n') name++; + snprintf(buf, MSG_SIZ, ".B %s", name); + len = strlen(buf); + for(len=3; buf[len] && buf[len] != '(' && buf[len] != ':' && buf[len] != '.' && buf[len] != '?' && buf[len] != '\n'; len++); + buf[len] = NULLCHAR; + while(buf[--len] == ' ') buf[len] = NULLCHAR; len++; + snprintf(title, MSG_SIZ, "Help on '%s'", buf+3); + while((line = ReadLine(f))) { + if(!strncmp(line, buf, len) || !strncmp(line, ".SS ", 4) && !strncmp(line+4, buf+3, len-3) + || !strncmp(line, ".IX Item \"", 10) && !strncmp(line+10, buf+3, len-3)) { + while((line = ReadLine(f)) && (cnt == 0 || strncmp(line, ".B ", 3) && strncmp(line, ".SS ", 4) && strncmp(line, ".IX ", 4))) { + if(!*line) { *p++ = '\n'; *p++ = '\n'; q = p; continue; } + if(*line == '.') continue; + *p++ = ' '; cnt++; + while(*line) { + if(*line < ' ') { line++; continue;} + if(*line == '\\') { + char **esc; + line++; + for(esc = texEscapes; *esc; esc++) { + len = strlen(*esc); + if(!strncmp(*esc, line, len)) { + line += len; + break; + } + } + continue; + } + if(*line == ' ' && p - q > 80) *line = '\n', q = p; + *p++ = *line++; + } + if(p - text > 9900) break; + } + *p = NULLCHAR; + ErrorPopUp(title, text, FALSE); + return; + } + } + snprintf(text, MSG_SIZ, "No help available on '%s'\n", buf+3); + DisplayNote(text); +} + +void +DisplayHelp (char *name) +{ + static char *xboardMan, *manText[2], tidy[MSG_SIZ], engMan[MSG_SIZ]; + char buf[MSG_SIZ], adapter[MSG_SIZ], *eng; + int n = 0; + FILE *f; + if(!xboardMan) { + xboardMan = BufferCommandOutput("man -w xboard", MSG_SIZ); // obtain path to XBoard's man file + if(xboardMan) xboardMan[strlen(xboardMan)-1] = NULLCHAR; // strip off traling linefeed + } + if(currentCps) { // for engine options we have to look in engine manual + snprintf(buf, MSG_SIZ, "man -w "); // get (tidied) engine name in buf + TidyProgramName(currentCps->program, "localhost", adapter); // name of binary we are actually running + TidyProgramName(currentCps == &first ? appData.firstChessProgram : appData.secondChessProgram, "localhost", buf+7); + if(strcmp(buf+7, adapter) && StrCaseStr(name, adapter) == name) { // option starts with name of apparent proxy for engine + safeStrCpy(buf+7, adapter, MSG_SIZ-7); // use adapter manual + name += strlen(adapter); // strip adapter name of option + while(*name == ' ') name++; + } + if(strcmp(buf, tidy)) { // is different engine from last time + FREE(manText[1]); manText[1] = NULL; // so any currently held text is worthless + safeStrCpy(tidy, buf, MSG_SIZ); // remember current engine + eng = BufferCommandOutput(tidy, MSG_SIZ); // obtain path to its man file + if(*eng) + safeStrCpy(engMan, eng, strlen(eng)); // and remember that too + else *engMan = NULLCHAR; + FREE(eng); + } + safeStrCpy(buf, engMan, MSG_SIZ); n = 1; // use engine man + } else snprintf(buf, MSG_SIZ, "%s", xboardMan); // use xboard man + f = fopen(buf, "r"); + if(f) { + char *msg = "Right-clicking menu item or dialog text pops up help on it"; + ASSIGN(appData.suppress, msg); + if(strstr(buf, ".gz")) { // man file is gzipped + if(!manText[n]) { // unzipped text not buffered yet + snprintf(tidy, MSG_SIZ, "gunzip -c %s", buf); + manText[n] = BufferCommandOutput(tidy, 250000); // store unzipped in buffer + } + textPtr = manText[n];// use buffered unzipped text + } else textPtr = NULL; // use plaintext man file directly + GetHelpText(f, name); + fclose(f); + } else if(currentCps) DisplayNote("No manual is installed for this engine"); +} + #define PAUSE_BUTTON "P" #define PIECE_MENU_SIZE 18 static String pieceMenuStrings[2][PIECE_MENU_SIZE+1] = { @@ -2549,7 +2886,7 @@ MenuCallback (int n) static Option * Exp (int n, int x, int y) { - static int but1, but3, oldW, oldH; + static int but1, but3, oldW, oldH, oldX, oldY; int menuNr = -3, sizing, f, r; TimeMark now; extern Boolean right; @@ -2560,6 +2897,7 @@ Exp (int n, int x, int y) } if(n == 0) { // motion + oldX = x; oldY = y; if(SeekGraphClick(Press, x, y, 1)) return NULL; if((but1 || dragging == 2) && !PromoScroll(x, y)) DragPieceMove(x, y); if(but3) MovePV(x, y, lineGap + BOARD_HEIGHT * (squareSize + lineGap)); @@ -2582,8 +2920,8 @@ Exp (int n, int x, int y) case 3: menuNr = RightClick(Press, x, y, &pmFromX, &pmFromY), but3 = 1; break; case -2: shiftKey = !shiftKey; case -3: menuNr = RightClick(Release, x, y, &pmFromX, &pmFromY), but3 = 0; break; - case 4: BackwardEvent(); break; - case 5: ForwardEvent(); break; + case 4: Wheel(-1, oldX, oldY); break; + case 5: Wheel(1, oldX, oldY); break; case 10: sizing = (oldW != x || oldH != y); oldW = x; oldH = y; @@ -2770,6 +3108,7 @@ static char *Extensions[] = { ".trn", ".bin", ".wav", +".png", ".ini", ".log", "", @@ -2977,10 +3316,14 @@ DirSelProc (int n, int sel) void StartDir (char *filter, char *newName) { - static char *gamesDir, *trnDir, *imgDir, *bookDir; + static char *gamesDir, *trnDir, *imgDir, *bookDir, *dirDir; static char curDir[MSG_SIZ]; char **res = NULL; if(!filter || !*filter) return; + if(strstr(filter, "dir")) { + res = &dirDir; + if(!dirDir) dirDir= strdup(dataDir); + } else if(strstr(filter, "pgn")) res = &gamesDir; else if(strstr(filter, "bin")) res = &bookDir; else if(strstr(filter, "png")) res = &imgDir; else @@ -2993,7 +3336,9 @@ StartDir (char *filter, char *newName) ASSIGN(*res, newName); for(p=*res; q=strchr(p, '/');) p = q + 1; *p = NULLCHAR; } - if(*curDir) chdir(curDir); + } + if(*curDir) { + chdir(curDir); *curDir = NULLCHAR; } else { getcwd(curDir, MSG_SIZ);