/* * menus.c -- platform-indendent menu handling code for XBoard * * Copyright 1991 by Digital Equipment Corporation, Maynard, * Massachusetts. * * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006, * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Free * Software Foundation, Inc. * * The following terms apply to Digital Equipment Corporation's copyright * interest in XBoard: * ------------------------------------------------------------------------ * All Rights Reserved * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation, and that the name of Digital not be * used in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * ------------------------------------------------------------------------ * * The following terms apply to the enhanced version of XBoard * distributed by the Free Software Foundation: * ------------------------------------------------------------------------ * * GNU XBoard is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or (at * your option) any later version. * * GNU XBoard is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * *------------------------------------------------------------------------ ** See the file ChangeLog for a revision history. */ #define HIGHDRAG 1 #include "config.h" #include #include #include #include #include #include #include #include #if STDC_HEADERS # include # include #else /* not STDC_HEADERS */ extern char *getenv(); # if HAVE_STRING_H # include # else /* not HAVE_STRING_H */ # include # endif /* not HAVE_STRING_H */ #endif /* not STDC_HEADERS */ #if HAVE_UNISTD_H # include #endif #if ENABLE_NLS #include #endif // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are. #include "common.h" #include "frontend.h" #include "backend.h" #include "menus.h" #include "gettext.h" #ifdef ENABLE_NLS # define _(s) gettext (s) # define N_(s) gettext_noop (s) #else # define _(s) (s) # define N_(s) s #endif /* * Button/menu procedures */ char *gameCopyFilename, *gamePasteFilename; Boolean saveSettingsOnExit; char *settingsFileName; char gamesDir[MSG_SIZ], positionsDir[MSG_SIZ], textureDir[MSG_SIZ], bookDir[MSG_SIZ], piecesDir[MSG_SIZ]; static int LoadGamePopUp (FILE *f, int gameNumber, char *title) { cmailMsgLoaded = FALSE; if (gameNumber == 0) { int error = GameListBuild(f); if (error) { DisplayError(_("Cannot build game list"), error); } else if (!ListEmpty(&gameList) && ((ListGame *) gameList.tailPred)->number > 1) { GameListPopUp(f, title); return TRUE; } GameListDestroy(); gameNumber = 1; } return LoadGame(f, gameNumber, title, FALSE); } void LoadGameProc () { if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) { Reset(FALSE, TRUE); } FileNamePopUp(_("Load game file name?"), "", ".pgn .game", LoadGamePopUp, "rb"); } void LoadNextGameProc () { ReloadGame(1); } void LoadPrevGameProc () { ReloadGame(-1); } void ReloadGameProc () { ReloadGame(0); } void LoadNextPositionProc () { ReloadPosition(1); } void LoadPrevPositionProc () { ReloadPosition(-1); } void ReloadPositionProc () { ReloadPosition(0); } void LoadPositionProc() { static char buf[MSG_SIZ]; if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) { Reset(FALSE, TRUE); } snprintf(buf, MSG_SIZ, "%s/", appData.positionDir); FileNamePopUp(_("Load position file name?"), buf, ".fen .epd .pos", LoadPosition, "rb"); } void SaveGameProc () { FileNamePopUp(_("Save game file name?"), DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"), appData.oldSaveStyle ? ".game" : ".pgn", SaveGame, "a"); } void SavePositionProc () { FileNamePopUp(_("Save position file name?"), DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"), appData.oldSaveStyle ? ".pos" : ".fen", SavePosition, "a"); } void ReloadCmailMsgProc () { ReloadCmailMsgEvent(FALSE); } void CopyFENToClipboard () { // wrapper to make call from back-end possible CopyPositionProc(); } void CopyPositionProc () { static char *selected_fen_position=NULL; if(gameMode == EditPosition) EditPositionDone(TRUE); if (selected_fen_position) free(selected_fen_position); selected_fen_position = (char *)PositionToFEN(currentMove, NULL, 1); if (!selected_fen_position) return; CopySomething(selected_fen_position); } void CopyGameProc () { int ret; ret = SaveGameToFile(gameCopyFilename, FALSE); if (!ret) return; CopySomething(NULL); } void CopyGameListProc () { if(!SaveGameListAsText(fopen(gameCopyFilename, "w"))) return; CopySomething(NULL); } void AutoSaveGame () { SaveGameProc(); } void QuitProc () { ExitEvent(0); } void MatchProc () { static Enables matchOff[] = { { "Mode.MachineMatch", False }, { NULL, False } }; if(matchMode) SetMenuEnables(matchOff); MatchEvent(2); } void AdjuWhiteProc () { UserAdjudicationEvent(+1); } void AdjuBlackProc () { UserAdjudicationEvent(-1); } void AdjuDrawProc () { UserAdjudicationEvent(0); } void RevertProc () { RevertEvent(False); } void AnnotateProc () { RevertEvent(True); } void FlipViewProc () { if(twoBoards) { partnerUp = 1; DrawPosition(True, NULL); partnerUp = 0; } flipView = !flipView; DrawPosition(True, NULL); } void SaveOnExitProc () { saveSettingsOnExit = !saveSettingsOnExit; MarkMenuItem("Options.SaveSettingsonExit", saveSettingsOnExit); } void SaveSettingsProc () { SaveSettings(settingsFileName); } void BugReportProc () { char buf[MSG_SIZ]; snprintf(buf, MSG_SIZ, "%s mailto:bug-xboard@gnu.org", appData.sysOpen); system(buf); } void GuideProc () { char buf[MSG_SIZ]; snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/user_guide/UserGuide.html", appData.sysOpen); system(buf); } void HomePageProc () { char buf[MSG_SIZ]; snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/", appData.sysOpen); system(buf); } void NewsPageProc () { char buf[MSG_SIZ]; snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/whats_new/portal.html", appData.sysOpen); system(buf); } void AboutProc () { char buf[2 * MSG_SIZ]; #if ZIPPY char *zippy = _(" (with Zippy code)"); #else char *zippy = ""; #endif snprintf(buf, sizeof(buf), _("%s%s\n\n" "Copyright 1991 Digital Equipment Corporation\n" "Enhancements Copyright 1992-2016 Free Software Foundation\n" "Enhancements Copyright 2005 Alessandro Scotti\n\n" "%s is free software and carries NO WARRANTY;" "see the file COPYING for more information.\n\n" "Visit XBoard on the web at: http://www.gnu.org/software/xboard/\n" "Check out the newest features at: http://www.gnu.org/software/xboard/whats_new.html\n\n" "Report bugs via email at: \n\n" ), programVersion, zippy, PACKAGE); ErrorPopUp(_("About XBoard"), buf, FALSE); } void DebugProc () { appData.debugMode = !appData.debugMode; if(!strcmp(appData.nameOfDebugFile, "stderr")) return; // stderr is already open, and should never be closed if(!appData.debugMode) fclose(debugFP); else { debugFP = fopen(appData.nameOfDebugFile, "w"); if(debugFP == NULL) debugFP = stderr; else setbuf(debugFP, NULL); } } void EditEngineProc () { EditAnyPopUp(firstChessProgramNames, &firstChessProgramNames, _("Registered Engines")); } void EditThemesProc () { EditAnyPopUp(appData.themeNames, &appData.themeNames, _("Predefined Themes")); } void EditMenuProc () { EditAnyPopUp(icsTextMenuString, &icsTextMenuString, _("ICS Text-Menu Definition")); } void MuteProc () { mute = !mute; MarkMenuItem("Options.Mute", mute); } void NothingProc () { return; } #ifdef OPTIONSDIALOG # define MARK_MENU_ITEM(X,Y) #else # define MARK_MENU_ITEM(X,Y) MarkMenuItem(X, Y) #endif void PonderNextMoveProc () { PonderNextMoveEvent(!appData.ponderNextMove); MARK_MENU_ITEM("Options.PonderNextMove", appData.ponderNextMove); } void AlwaysQueenProc () { appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen; MARK_MENU_ITEM("Options.AlwaysQueen", appData.alwaysPromoteToQueen); } void AnimateDraggingProc () { appData.animateDragging = !appData.animateDragging; if (appData.animateDragging) CreateAnimVars(); MARK_MENU_ITEM("Options.AnimateDragging", appData.animateDragging); } void AnimateMovingProc () { appData.animate = !appData.animate; if (appData.animate) CreateAnimVars(); MARK_MENU_ITEM("Options.AnimateMoving", appData.animate); } void AutoflagProc () { appData.autoCallFlag = !appData.autoCallFlag; MARK_MENU_ITEM("Options.AutoFlag", appData.autoCallFlag); } void AutoflipProc () { appData.autoFlipView = !appData.autoFlipView; MARK_MENU_ITEM("Options.AutoFlipView", appData.autoFlipView); } void BlindfoldProc () { appData.blindfold = !appData.blindfold; MARK_MENU_ITEM("Options.Blindfold", appData.blindfold); DrawPosition(True, NULL); } void TestLegalityProc () { appData.testLegality = !appData.testLegality; MARK_MENU_ITEM("Options.TestLegality", appData.testLegality); } void FlashMovesProc () { if (appData.flashCount == 0) { appData.flashCount = 3; } else { appData.flashCount = -appData.flashCount; } MARK_MENU_ITEM("Options.FlashMoves", appData.flashCount > 0); } #if HIGHDRAG void HighlightDraggingProc () { appData.highlightDragging = !appData.highlightDragging; MARK_MENU_ITEM("Options.HighlightDragging", appData.highlightDragging); } #endif void HighlightLastMoveProc () { appData.highlightLastMove = !appData.highlightLastMove; MARK_MENU_ITEM("Options.HighlightLastMove", appData.highlightLastMove); } void HighlightArrowProc () { appData.highlightMoveWithArrow = !appData.highlightMoveWithArrow; MARK_MENU_ITEM("Options.HighlightWithArrow", appData.highlightMoveWithArrow); } void IcsAlarmProc () { appData.icsAlarm = !appData.icsAlarm; // MARK_MENU_ITEM("Options.ICSAlarm", appData.icsAlarm); } void MoveSoundProc () { appData.ringBellAfterMoves = !appData.ringBellAfterMoves; MARK_MENU_ITEM("Options.MoveSound", appData.ringBellAfterMoves); } void OneClickProc () { appData.oneClick = !appData.oneClick; MARK_MENU_ITEM("Options.OneClickMoving", appData.oneClick); } void PeriodicUpdatesProc () { PeriodicUpdatesEvent(!appData.periodicUpdates); MARK_MENU_ITEM("Options.PeriodicUpdates", appData.periodicUpdates); } void PopupExitMessageProc () { appData.popupExitMessage = !appData.popupExitMessage; MARK_MENU_ITEM("Options.PopupExitMessage", appData.popupExitMessage); } void PopupMoveErrorsProc () { appData.popupMoveErrors = !appData.popupMoveErrors; MARK_MENU_ITEM("Options.PopupMoveErrors", appData.popupMoveErrors); } void PremoveProc () { appData.premove = !appData.premove; // MARK_MENU_ITEM("Options.Premove", appData.premove); } void ShowCoordsProc () { appData.showCoords = !appData.showCoords; MARK_MENU_ITEM("Options.ShowCoords", appData.showCoords); DrawPosition(True, NULL); } void ShowThinkingProc () { appData.showThinking = !appData.showThinking; // [HGM] thinking: taken out of ShowThinkingEvent ShowThinkingEvent(); } void HideThinkingProc () { appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: taken out of ShowThinkingEvent ShowThinkingEvent(); MARK_MENU_ITEM("Options.HideThinking", appData.hideThinkingFromHuman); } void CreateBookDelayed () { ScheduleDelayedEvent(CreateBookEvent, 50); } void SaveSelectedProc () { FileNamePopUp(_("Save game file name?"), "", ".pgn", SaveSelected, "a"); } /* * Menu definition tables */ MenuItem fileMenu[] = { {N_("New Game"), "n", "NewGame", ResetGameEvent}, {N_("New Shuffle Game..."), NULL, "NewShuffleGame", ShuffleMenuProc}, {N_("New Variant..."), "v", "NewVariant", NewVariantProc},// [HGM] variant: not functional yet {"----", NULL, NULL, NothingProc}, {N_("Load Game"), "o", "LoadGame", LoadGameProc, CHECK}, {N_("Load Position"), "o", "LoadPosition", LoadPositionProc}, {N_("Next Position"), "Page_Down", "LoadNextPosition", LoadNextPositionProc}, {N_("Prev Position"), "Page_Up", "LoadPreviousPosition", LoadPrevPositionProc}, {"----", NULL, NULL, NothingProc}, {N_("Save Game"), "s", "SaveGame", SaveGameProc}, {N_("Save Position"), "s", "SavePosition", SavePositionProc}, {N_("Save Selected Games"), NULL, "SaveSelected", SaveSelectedProc}, {N_("Save Games as Book"), NULL, "CreateBook", CreateBookDelayed}, {"----", NULL, NULL, NothingProc}, {N_("Mail Move"), NULL, "MailMove", MailMoveEvent}, {N_("Reload CMail Message"), NULL, "ReloadCMailMessage", ReloadCmailMsgProc}, {"----", NULL, NULL, NothingProc}, {N_("Quit "), "q", "Quit", QuitProc}, {NULL, NULL, NULL, NULL} }; MenuItem editMenu[] = { {N_("Copy Game"), "c", "CopyGame", CopyGameProc}, {N_("Copy Position"), "c", "CopyPosition", CopyPositionProc}, {N_("Copy Game List"), NULL, "CopyGameList", CopyGameListProc}, {"----", NULL, NULL, NothingProc}, {N_("Paste Game"), "v", "PasteGame", PasteGameProc}, {N_("Paste Position"), "v", "PastePosition", PastePositionProc}, {"----", NULL, NULL, NothingProc}, {N_("Edit Game"), "e", "EditGame", EditGameEvent}, {N_("Edit Position"), "e", "EditPosition", EditPositionEvent}, {N_("Edit Tags"), NULL, "EditTags", EditTagsProc}, {N_("Edit Comment"), NULL, "EditComment", EditCommentProc}, {N_("Edit Book"), NULL, "EditBook", EditBookEvent}, {"----", NULL, NULL, NothingProc}, {N_("Revert"), "Home", "Revert", RevertProc}, {N_("Annotate"), NULL, "Annotate", AnnotateProc}, {N_("Truncate Game"), "End", "TruncateGame", TruncateGameEvent}, {"----", NULL, NULL, NothingProc}, {N_("Backward"), "Left", "Backward", BackwardEvent}, {N_("Forward"), "Right", "Forward", ForwardEvent}, {N_("Back to Start"), "Home", "BacktoStart", ToStartEvent}, {N_("Forward to End"), "End", "ForwardtoEnd", ToEndEvent}, {NULL, NULL, NULL, NULL} }; MenuItem viewMenu[] = { {N_("Flip View"), "F2", "FlipView", FlipViewProc, CHECK}, {"----", NULL, NULL, NothingProc}, {N_("Engine Output"), "o", "EngineOutput", EngineOutputProc, CHECK}, {N_("Move History"), "h", "MoveHistory", HistoryShowProc, CHECK}, // [HGM] hist: activate 4.2.7 code {N_("Evaluation Graph"), "e", "EvaluationGraph", EvalGraphProc, CHECK}, {N_("Game List"), "g", "GameList", ShowGameListProc, CHECK}, {"----", NULL, NULL, NothingProc}, {N_("Tags"), NULL, "Tags", EditTagsProc, CHECK}, {N_("Comments"), NULL, "Comments", EditCommentProc, CHECK}, {N_("ICS Input Box"), NULL, "ICSInputBox", IcsInputBoxProc, CHECK}, {N_("ICS/Chat Console"), NULL, "OpenChatWindow", ChatProc, CHECK}, {N_("ICS text menu"), NULL, "ICStextmenu", IcsTextProc, CHECK}, {N_("Edit ICS menu..."), NULL, "EditTextMenu", EditMenuProc}, {"----", NULL, NULL, NothingProc}, {N_("Edit Theme List..."), NULL, "EditThemeList", EditThemesProc}, {N_("Board..."), NULL, "Board", BoardOptionsProc}, {N_("Fonts..."), NULL, "Fonts", FontsProc}, {N_("Game List Tags..."), NULL, "GameListTags", GameListOptionsProc}, {NULL, NULL, NULL, NULL} }; MenuItem modeMenu[] = { {N_("Machine White"), "w", "MachineWhite", MachineWhiteEvent, RADIO }, {N_("Machine Black"), "b", "MachineBlack", MachineBlackEvent, RADIO }, {N_("Two Machines"), "t", "TwoMachines", TwoMachinesEvent, RADIO }, {N_("Analysis Mode"), "a", "AnalysisMode", (MenuProc*) AnalyzeModeEvent, RADIO }, {N_("Analyze Game"), "g", "AnalyzeFile", AnalyzeFileEvent, RADIO }, {N_("Edit Game"), "e", "EditGame", EditGameEvent, RADIO }, {N_("Edit Position"), "e", "EditPosition", EditPositionEvent, RADIO }, {N_("Training"), NULL, "Training", TrainingEvent, RADIO }, {N_("ICS Client"), NULL, "ICSClient", IcsClientEvent, RADIO }, {"----", NULL, NULL, NothingProc}, {N_("Machine Match"), NULL, "MachineMatch", MatchProc, CHECK }, {N_("Pause"), "Pause", "Pause", PauseEvent, CHECK }, {NULL, NULL, NULL, NULL} }; MenuItem actionMenu[] = { {N_("Accept"), "F3", "Accept", AcceptEvent}, {N_("Decline"), "F4", "Decline", DeclineEvent}, {N_("Rematch"), "F12", "Rematch", RematchEvent}, {"----", NULL, NULL, NothingProc}, {N_("Call Flag"), "F5", "CallFlag", CallFlagEvent}, {N_("Draw"), "F6", "Draw", DrawEvent}, {N_("Adjourn"), "F7", "Adjourn", AdjournEvent}, {N_("Abort"), "F8", "Abort", AbortEvent}, {N_("Resign"), "F9", "Resign", ResignEvent}, {"----", NULL, NULL, NothingProc}, {N_("Stop Observing"), "F10", "StopObserving", StopObservingEvent}, {N_("Stop Examining"), "F11", "StopExamining", StopExaminingEvent}, {N_("Upload to Examine"), NULL, "UploadtoExamine", UploadGameEvent}, {"----", NULL, NULL, NothingProc}, {N_("Adjudicate to White"), NULL, "AdjudicatetoWhite", AdjuWhiteProc}, {N_("Adjudicate to Black"), NULL, "AdjudicatetoBlack", AdjuBlackProc}, {N_("Adjudicate Draw"), NULL, "AdjudicateDraw", AdjuDrawProc}, {NULL, NULL, NULL, NULL} }; MenuItem engineMenu[100] = { {N_("Edit Engine List..."), NULL, "EditEngList", EditEngineProc}, {"----", NULL, NULL, NothingProc}, {N_("Load New 1st Engine..."), NULL, "LoadNew1stEngine", LoadEngine1Proc}, {N_("Load New 2nd Engine..."), NULL, "LoadNew2ndEngine", LoadEngine2Proc}, {"----", NULL, NULL, NothingProc}, {N_("Engine #1 Settings..."), NULL, "Engine#1Settings", FirstSettingsProc}, {N_("Engine #2 Settings..."), NULL, "Engine#2Settings", SecondSettingsProc}, {N_("Common Settings..."), "u","CommonEngine", UciMenuProc}, {"----", NULL, NULL, NothingProc}, {N_("Hint"), NULL, "Hint", HintEvent}, {N_("Book"), NULL, "Book", BookEvent}, {"----", NULL, NULL, NothingProc}, {N_("Move Now"), "m", "MoveNow", MoveNowEvent}, {N_("Retract Move"), "x", "RetractMove", RetractMoveEvent}, {NULL, NULL, NULL, NULL} }; MenuItem optionsMenu[] = { {N_("Mute all Sounds"), NULL, "Mute", MuteProc, CHECK}, {"----", NULL, NULL, NothingProc}, #ifdef OPTIONSDIALOG {N_("General..."), NULL, "General", OptionsProc}, #endif {N_("Time Control..."), "t", "TimeControl", TimeControlProc}, {N_("Adjudications..."), "j", "Adjudications", EngineMenuProc}, {N_("ICS..."), NULL, "ICS", IcsOptionsProc}, {N_("Tournament..."), NULL, "Match", MatchOptionsProc}, {N_("Load Game..."), NULL, "LoadGame", LoadOptionsProc}, {N_("Save Game..."), NULL, "SaveGame", SaveOptionsProc}, {N_("Game List..."), NULL, "GameList", GameListOptionsProc}, {N_("Sounds..."), NULL, "Sounds", SoundOptionsProc}, {"----", NULL, NULL, NothingProc}, #ifndef OPTIONSDIALOG {N_("Always Queen"), "q", "AlwaysQueen", AlwaysQueenProc}, {N_("Animate Dragging"), NULL, "AnimateDragging", AnimateDraggingProc}, {N_("Animate Moving"), "a", "AnimateMoving", AnimateMovingProc}, {N_("Auto Flag"), "f", "AutoFlag", AutoflagProc}, {N_("Auto Flip View"), NULL, "AutoFlipView", AutoflipProc}, {N_("Blindfold"), NULL, "Blindfold", BlindfoldProc}, {N_("Flash Moves"), NULL, "FlashMoves", FlashMovesProc}, #if HIGHDRAG {N_("Highlight Dragging"), NULL, "HighlightDragging", HighlightDraggingProc}, #endif {N_("Highlight Last Move"), NULL, "HighlightLastMove", HighlightLastMoveProc}, {N_("Highlight With Arrow"), NULL, "HighlightWithArrow", HighlightArrowProc}, {N_("Move Sound"), NULL, "MoveSound", MoveSoundProc}, {N_("One-Click Moving"), NULL, "OneClickMoving", OneClickProc}, {N_("Periodic Updates"), NULL, "PeriodicUpdates", PeriodicUpdatesProc}, {N_("Ponder Next Move"), "p", "PonderNextMove", PonderNextMoveProc}, {N_("Popup Exit Message"), NULL, "PopupExitMessage", PopupExitMessageProc}, {N_("Popup Move Errors"), NULL, "PopupMoveErrors", PopupMoveErrorsProc}, {N_("Show Coords"), NULL, "ShowCoords", ShowCoordsProc}, {N_("Hide Thinking"), "h", "HideThinking", HideThinkingProc}, {N_("Test Legality"), "l", "TestLegality", TestLegalityProc}, {"----", NULL, NULL, NothingProc}, #endif {N_("Save Settings Now"), NULL, "SaveSettingsNow", SaveSettingsProc}, {N_("Save Settings on Exit"), NULL, "SaveSettingsonExit", SaveOnExitProc, CHECK }, {NULL, NULL, NULL, NULL} }; MenuItem helpMenu[] = { {N_("Info XBoard"), NULL, "InfoXBoard", InfoProc}, {N_("Man XBoard"), "F1", "ManXBoard", ManProc}, {"----", NULL, NULL, NothingProc}, {N_("XBoard Home Page"), NULL, "XBoardHomePage", HomePageProc}, {N_("On-line User Guide"), NULL, "On-lineUserGuide", GuideProc}, {N_("Development News"), NULL, "DevelopmentNews", NewsPageProc}, {N_("e-Mail Bug Report"), NULL, "e-MailBugReport", BugReportProc}, {"----", NULL, NULL, NothingProc}, {N_("About XBoard"), NULL, "AboutXBoard", AboutProc}, {NULL, NULL, NULL, NULL} }; MenuItem noMenu[] = { { "", "Next" ,"LoadNextGame", LoadNextGameProc }, { "", "Prior" ,"LoadPrevGame", LoadPrevGameProc }, { "", NULL,"ReloadGame", ReloadGameProc }, { "", NULL,"ReloadPosition", ReloadPositionProc }, #ifndef OPTIONSDIALOG { "", NULL,"AlwaysQueen", AlwaysQueenProc }, { "", NULL,"AnimateDragging", AnimateDraggingProc }, { "", NULL,"AnimateMoving", AnimateMovingProc }, { "", NULL,"Autoflag", AutoflagProc }, { "", NULL,"Autoflip", AutoflipProc }, { "", NULL,"Blindfold", BlindfoldProc }, { "", NULL,"FlashMoves", FlashMovesProc }, #if HIGHDRAG { "", NULL,"HighlightDragging", HighlightDraggingProc }, #endif { "", NULL,"HighlightLastMove", HighlightLastMoveProc }, { "", NULL,"MoveSound", MoveSoundProc }, { "", NULL,"PeriodicUpdates", PeriodicUpdatesProc }, { "", NULL,"PopupExitMessage", PopupExitMessageProc }, { "", NULL,"PopupMoveErrors", PopupMoveErrorsProc }, { "", NULL,"ShowCoords", ShowCoordsProc }, { "", NULL,"ShowThinking", ShowThinkingProc }, { "", NULL,"HideThinking", HideThinkingProc }, { "", NULL,"TestLegality", TestLegalityProc }, #endif { "", NULL,"AboutGame", AboutGameEvent }, { "", "d" ,"DebugProc", DebugProc }, { "", NULL,"Nothing", NothingProc }, {NULL, NULL, NULL, NULL} }; Menu menuBar[] = { {N_("File"), "File", fileMenu}, {N_("Edit"), "Edit", editMenu}, {N_("View"), "View", viewMenu}, {N_("Mode"), "Mode", modeMenu}, {N_("Action"), "Action", actionMenu}, {N_("Engine"), "Engine", engineMenu}, {N_("Options"), "Options", optionsMenu}, {N_("Help"), "Help", helpMenu}, {NULL, NULL, NULL}, { "", "None", noMenu} }; MenuItem * MenuNameToItem (char *menuName) { int i=0; char buf[MSG_SIZ], *p; MenuItem *menuTab; static MenuItem a = { NULL, NULL, NULL, NothingProc }; extern Option mainOptions[]; safeStrCpy(buf, menuName, MSG_SIZ); p = strchr(buf, '.'); if(!p) menuTab = noMenu, p = menuName; else { *p++ = NULLCHAR; for(i=0; menuBar[i].name; i++) if(!strcmp(buf, menuBar[i].name)) break; if(!menuBar[i].name) return NULL; // main menu not found menuTab = menuBar[i].mi; } if(*p == NULLCHAR) { a.handle = mainOptions[i+1].handle; return &a; } // main menu bar for(i=0; menuTab[i].string; i++) if(menuTab[i].ref && !strcmp(p, menuTab[i].ref)) return menuTab + i; return NULL; // item not found } int firstEngineItem; void AppendEnginesToMenu (char *list) { int i=0; char *p; if(appData.icsActive || appData.recentEngines <= 0) return; for(firstEngineItem=0; engineMenu[firstEngineItem].string; firstEngineItem++); recentEngines = strdup(list); while (*list) { p = strchr(list, '\n'); if(p == NULL) break; if(i == 0) engineMenu[firstEngineItem++].string = "----"; // at least one valid item to add *p = 0; if(firstEngineItem + i < 99) engineMenu[firstEngineItem+i].string = strdup(list); // just set name; MenuProc stays NULL i++; *p = '\n'; list = p + 1; } } Enables icsEnables[] = { { "File.MailMove", False }, { "File.ReloadCMailMessage", False }, { "Mode.MachineBlack", False }, { "Mode.MachineWhite", False }, { "Mode.AnalysisMode", False }, { "Mode.AnalyzeFile", False }, { "Mode.TwoMachines", False }, { "Mode.MachineMatch", False }, #if !ZIPPY { "Engine.Hint", False }, { "Engine.Book", False }, { "Engine.MoveNow", False }, #ifndef OPTIONSDIALOG { "PeriodicUpdates", False }, { "HideThinking", False }, { "PonderNextMove", False }, #endif #endif { "Engine.Engine#1Settings", False }, { "Engine.Engine#2Settings", False }, { "Engine.Load1stEngine", False }, { "Engine.Load2ndEngine", False }, { "Edit.Annotate", False }, { "Options.Match", False }, { NULL, False } }; Enables ncpEnables[] = { { "File.MailMove", False }, { "File.ReloadCMailMessage", False }, { "Mode.MachineWhite", False }, { "Mode.MachineBlack", False }, { "Mode.AnalysisMode", False }, { "Mode.AnalyzeFile", False }, { "Mode.TwoMachines", False }, { "Mode.MachineMatch", False }, { "Mode.ICSClient", False }, { "View.ICStextmenu", False }, { "View.ICSInputBox", False }, { "View.OpenChatWindow", False }, { "Action.", False }, { "Edit.Revert", False }, { "Edit.Annotate", False }, { "Engine.Engine#1Settings", False }, { "Engine.Engine#2Settings", False }, { "Engine.MoveNow", False }, { "Engine.RetractMove", False }, { "Options.ICS", False }, #ifndef OPTIONSDIALOG { "Options.AutoFlag", False }, { "Options.AutoFlip View", False }, // { "Options.ICSAlarm", False }, { "Options.MoveSound", False }, { "Options.HideThinking", False }, { "Options.PeriodicUpdates", False }, { "Options.PonderNextMove", False }, #endif { "Engine.Hint", False }, { "Engine.Book", False }, { NULL, False } }; Enables gnuEnables[] = { { "Mode.ICSClient", False }, { "View.ICStextmenu", False }, { "View.ICSInputBox", False }, { "View.OpenChatWindow", False }, { "Action.Accept", False }, { "Action.Decline", False }, { "Action.Rematch", False }, { "Action.Adjourn", False }, { "Action.StopExamining", False }, { "Action.StopObserving", False }, { "Action.UploadtoExamine", False }, { "Edit.Revert", False }, { "Edit.Annotate", False }, { "Options.ICS", False }, /* The next two options rely on SetCmailMode being called *after* */ /* SetGNUMode so that when GNU is being used to give hints these */ /* menu options are still available */ { "File.MailMove", False }, { "File.ReloadCMailMessage", False }, // [HGM] The following have been added to make a switch from ncp to GNU mode possible { "Mode.MachineWhite", True }, { "Mode.MachineBlack", True }, { "Mode.AnalysisMode", True }, { "Mode.AnalyzeFile", True }, { "Mode.TwoMachines", True }, { "Mode.MachineMatch", True }, { "Engine.Engine#1Settings", True }, { "Engine.Engine#2Settings", True }, { "Engine.Hint", True }, { "Engine.Book", True }, { "Engine.MoveNow", True }, { "Engine.RetractMove", True }, { "Action.", True }, { NULL, False } }; Enables cmailEnables[] = { { "Action.", True }, { "Action.CallFlag", False }, { "Action.Draw", True }, { "Action.Adjourn", False }, { "Action.Abort", False }, { "Action.StopObserving", False }, { "Action.StopExamining", False }, { "File.MailMove", True }, { "File.ReloadCMailMessage", True }, { NULL, False } }; Enables trainingOnEnables[] = { { "Edit.EditComment", False }, { "Mode.Pause", False }, { "Edit.Forward", False }, { "Edit.Backward", False }, { "Edit.ForwardtoEnd", False }, { "Edit.BacktoStart", False }, { "Engine.MoveNow", False }, { "Edit.TruncateGame", False }, { NULL, False } }; Enables trainingOffEnables[] = { { "Edit.EditComment", True }, { "Mode.Pause", True }, { "Edit.Forward", True }, { "Edit.Backward", True }, { "Edit.ForwardtoEnd", True }, { "Edit.BacktoStart", True }, { "Engine.MoveNow", True }, { "Engine.TruncateGame", True }, { NULL, False } }; Enables machineThinkingEnables[] = { { "File.LoadGame", False }, // { "LoadNextGame", False }, // { "LoadPreviousGame", False }, // { "ReloadSameGame", False }, { "Edit.PasteGame", False }, { "File.LoadPosition", False }, // { "LoadNextPosition", False }, // { "LoadPreviousPosition", False }, // { "ReloadSamePosition", False }, { "Edit.PastePosition", False }, { "Mode.MachineWhite", False }, { "Mode.MachineBlack", False }, { "Mode.TwoMachines", False }, // { "MachineMatch", False }, { "Engine.RetractMove", False }, { NULL, False } }; Enables userThinkingEnables[] = { { "File.LoadGame", True }, // { "LoadNextGame", True }, // { "LoadPreviousGame", True }, // { "ReloadSameGame", True }, { "Edit.PasteGame", True }, { "File.LoadPosition", True }, // { "LoadNextPosition", True }, // { "LoadPreviousPosition", True }, // { "ReloadSamePosition", True }, { "Edit.PastePosition", True }, { "Mode.MachineWhite", True }, { "Mode.MachineBlack", True }, { "Mode.TwoMachines", True }, // { "MachineMatch", True }, { "Engine.RetractMove", True }, { NULL, False } }; void SetICSMode () { SetMenuEnables(icsEnables); #if ZIPPY if (appData.zippyPlay && !appData.noChessProgram) { /* [DM] icsEngineAnalyze */ EnableNamedMenuItem("Mode.AnalysisMode", True); EnableNamedMenuItem("Engine.Engine#1Settings", True); } #endif } void SetNCPMode () { SetMenuEnables(ncpEnables); } void SetGNUMode () { SetMenuEnables(gnuEnables); } void SetCmailMode () { SetMenuEnables(cmailEnables); } void SetTrainingModeOn () { SetMenuEnables(trainingOnEnables); if (appData.showButtonBar) { EnableButtonBar(False); } CommentPopDown(); } void SetTrainingModeOff () { SetMenuEnables(trainingOffEnables); if (appData.showButtonBar) { EnableButtonBar(True); } } void SetUserThinkingEnables () { if (appData.noChessProgram) return; SetMenuEnables(userThinkingEnables); } void SetMachineThinkingEnables () { if (appData.noChessProgram) return; SetMenuEnables(machineThinkingEnables); switch (gameMode) { case MachinePlaysBlack: case MachinePlaysWhite: case TwoMachinesPlay: EnableNamedMenuItem(ModeToWidgetName(gameMode), True); break; default: break; } } void GreyRevert (Boolean grey) { EnableNamedMenuItem("Edit.Revert", !grey); EnableNamedMenuItem("Edit.Annotate", !grey); } char * ModeToWidgetName (GameMode mode) { switch (mode) { case BeginningOfGame: if (appData.icsActive) return "Mode.ICSClient"; else if (appData.noChessProgram || *appData.cmailGameName != NULLCHAR) return "Mode.EditGame"; else return "Mode.MachineBlack"; case MachinePlaysBlack: return "Mode.MachineBlack"; case MachinePlaysWhite: return "Mode.MachineWhite"; case AnalyzeMode: return "Mode.AnalysisMode"; case AnalyzeFile: return "Mode.AnalyzeFile"; case TwoMachinesPlay: return "Mode.TwoMachines"; case EditGame: return "Mode.EditGame"; case PlayFromGameFile: return "File.LoadGame"; case EditPosition: return "Mode.EditPosition"; case Training: return "Mode.Training"; case IcsPlayingWhite: case IcsPlayingBlack: case IcsObserving: case IcsIdle: case IcsExamining: return "Mode.ICSClient"; default: case EndOfGame: return NULL; } } static void InstallNewEngine (char *command, char *dir, char *variants, char *protocol) { // install the given engine in XBoard's -firstChessProgramNames char buf[MSG_SIZ], *quote = ""; if(strchr(command, ' ')) { // quoting needed if(!strchr(command, '"')) quote = "\""; else if(!strchr(command, '\'')) quote = "'"; else { printf("Could not auto-install %s\n", command); // too complex } } // construct engine line, with optional -fd and -fUCI arguments snprintf(buf, MSG_SIZ, "%s%s%s", quote, command, quote); if(strcmp(dir, "") && strcmp(dir, ".")) snprintf(buf + strlen(buf), MSG_SIZ - strlen(buf), " -fd %s", dir); if(!strcmp(protocol, "uci")) snprintf(buf + strlen(buf), MSG_SIZ - strlen(buf), " -fUCI"); if(strstr(firstChessProgramNames, buf)) return; // avoid duplicats // append line quote = malloc(strlen(firstChessProgramNames) + strlen(buf) + 2); sprintf(quote, "%s%s\n", firstChessProgramNames, buf); FREE(firstChessProgramNames); firstChessProgramNames = quote; } #ifdef HAVE_DIRENT_H #include #else #include #define dirent direct #endif static void InstallFromDir (char *dirName, char *protocol, char *settingsFile) { // scan system for new plugin specs in given directory DIR *dir; struct dirent *dp; struct stat statBuf; time_t lastSaved = 0; char buf[1024]; if(!stat(settingsFile, &statBuf)) lastSaved = statBuf.st_mtime; snprintf(buf, 1024, "%s/%s", dirName, protocol); if(!(dir = opendir(buf))) return; while( (dp = readdir(dir))) { time_t installed = 0; if(!strstr(dp->d_name, ".eng")) continue; // to suppress . and .. snprintf(buf, 1024, "%s/%s/%s", dirName, protocol, dp->d_name); if(!stat(buf, &statBuf)) installed = statBuf.st_mtime; if(lastSaved == 0 || (int) (installed - lastSaved) > 0) { // first time we see it FILE *f = fopen(buf, "r"); if(f) { // read the plugin-specs char engineCommand[1024], engineDir[1024], variants[1024]; char bad=0, dummy, *engineCom = engineCommand; int major, minor; if(fscanf(f, "plugin spec %d.%d%c", &major, &minor, &dummy) != 3 || fscanf(f, "%[^\n]%c", engineCommand, &dummy) != 2 || fscanf(f, "%[^\n]%c", variants, &dummy) != 2) bad = 1; fclose(f); if(bad) continue; // uncomment following two lines for chess-only installs // if(!(p = strstr(variants, "chess")) || // p != variants && p[-1] != ',' || p[5] && p[5] != ',') continue; // split off engine working directory (if any) strcpy(engineDir, ""); if(sscanf(engineCommand, "cd %[^;];%c", engineDir, &dummy) == 2) engineCom = engineCommand + strlen(engineDir) + 4; InstallNewEngine(engineCom, engineDir, variants, protocol); } } } closedir(dir); } static void AutoInstallProtocol (char *settingsFile, char *protocol) { // install new engines for given protocol (both from package and source) InstallFromDir("/usr/local/share/games/plugins", protocol, settingsFile); InstallFromDir("/usr/share/games/plugins", protocol, settingsFile); } void AutoInstall (char *settingsFile) { // install all new XBoard and UCI engines AutoInstallProtocol(settingsFile, "xboard"); AutoInstallProtocol(settingsFile, "uci"); } void InitMenuMarkers() { #ifndef OPTIONSDIALOG if (appData.alwaysPromoteToQueen) { MarkMenuItem("Options.Always Queen", True); } if (appData.animateDragging) { MarkMenuItem("Options.Animate Dragging", True); } if (appData.animate) { MarkMenuItem("Options.Animate Moving", True); } if (appData.autoCallFlag) { MarkMenuItem("Options.Auto Flag", True); } if (appData.autoFlipView) { XtSetValues(XtNameToWidget(menuBarWidget,"Options.Auto Flip View", True); } if (appData.blindfold) { MarkMenuItem("Options.Blindfold", True); } if (appData.flashCount > 0) { MarkMenuItem("Options.Flash Moves", True); } #if HIGHDRAG if (appData.highlightDragging) { MarkMenuItem("Options.Highlight Dragging", True); } #endif if (appData.highlightLastMove) { MarkMenuItem("Options.Highlight Last Move", True); } if (appData.highlightMoveWithArrow) { MarkMenuItem("Options.Arrow", True); } // if (appData.icsAlarm) { // MarkMenuItem("Options.ICS Alarm", True); // } if (appData.ringBellAfterMoves) { MarkMenuItem("Options.Move Sound", True); } if (appData.oneClick) { MarkMenuItem("Options.OneClick", True); } if (appData.periodicUpdates) { MarkMenuItem("Options.Periodic Updates", True); } if (appData.ponderNextMove) { MarkMenuItem("Options.Ponder Next Move", True); } if (appData.popupExitMessage) { MarkMenuItem("Options.Popup Exit Message", True); } if (appData.popupMoveErrors) { MarkMenuItem("Options.Popup Move Errors", True); } // if (appData.premove) { // MarkMenuItem("Options.Premove", True); // } if (appData.showCoords) { MarkMenuItem("Options.Show Coords", True); } if (appData.hideThinkingFromHuman) { MarkMenuItem("Options.Hide Thinking", True); } if (appData.testLegality) { MarkMenuItem("Options.Test Legality", True); } #endif if (saveSettingsOnExit) { MarkMenuItem("Options.SaveSettingsonExit", True); } EnableNamedMenuItem("File.SaveSelected", False); // all XBoard builds get here, but not WinBoard... if(*appData.autoInstall) AutoInstall(settingsFileName); }