2 * menus.c -- platform-indendent menu handling code for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
60 #include <sys/types.h>
68 #else /* not STDC_HEADERS */
69 extern char *getenv();
72 # else /* not HAVE_STRING_H */
74 # endif /* not HAVE_STRING_H */
75 #endif /* not STDC_HEADERS */
85 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
94 # define _(s) gettext (s)
95 # define N_(s) gettext_noop (s)
102 * Button/menu procedures
105 char *gameCopyFilename, *gamePasteFilename;
106 Boolean saveSettingsOnExit;
107 char *settingsFileName;
110 LoadGamePopUp (FILE *f, int gameNumber, char *title)
112 cmailMsgLoaded = FALSE;
113 if (gameNumber == 0) {
114 int error = GameListBuild(f);
116 DisplayError(_("Cannot build game list"), error);
117 } else if (!ListEmpty(&gameList) &&
118 ((ListGame *) gameList.tailPred)->number > 1) {
119 GameListPopUp(f, title);
125 return LoadGame(f, gameNumber, title, FALSE);
131 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
134 FileNamePopUp(_("Load game file name?"), "", ".pgn .game", LoadGamePopUp, "rb");
156 LoadNextPositionProc ()
162 LoadPrevPositionProc ()
168 ReloadPositionProc ()
176 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
179 FileNamePopUp(_("Load position file name?"), "", ".fen .epd .pos", LoadPosition, "rb");
185 FileNamePopUp(_("Save game file name?"),
186 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
187 appData.oldSaveStyle ? ".game" : ".pgn",
194 FileNamePopUp(_("Save position file name?"),
195 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
196 appData.oldSaveStyle ? ".pos" : ".fen",
201 ReloadCmailMsgProc ()
203 ReloadCmailMsgEvent(FALSE);
207 CopyFENToClipboard ()
208 { // wrapper to make call from back-end possible
215 static char *selected_fen_position=NULL;
216 if(gameMode == EditPosition) EditPositionDone(TRUE);
217 if (selected_fen_position) free(selected_fen_position);
218 selected_fen_position = (char *)PositionToFEN(currentMove, NULL, 1);
219 if (!selected_fen_position) return;
220 CopySomething(selected_fen_position);
228 ret = SaveGameToFile(gameCopyFilename, FALSE);
237 if(!SaveGameListAsText(fopen(gameCopyFilename, "w"))) return;
263 UserAdjudicationEvent(+1);
269 UserAdjudicationEvent(-1);
275 UserAdjudicationEvent(0);
293 if(twoBoards) { partnerUp = 1; DrawPosition(True, NULL); partnerUp = 0; }
294 flipView = !flipView;
295 DrawPosition(True, NULL);
301 saveSettingsOnExit = !saveSettingsOnExit;
303 MarkMenuItem("Options.SaveSettingsonExit", saveSettingsOnExit);
309 SaveSettings(settingsFileName);
317 snprintf(buf, MSG_SIZ, "%s ./info.command", appData.sysOpen);
319 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
329 snprintf(buf, MSG_SIZ, "%s mailto:bug-xboard@gnu.org", appData.sysOpen);
337 snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/user_guide/UserGuide.html", appData.sysOpen);
345 snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/", appData.sysOpen);
353 snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/whats_new/portal.html", appData.sysOpen);
360 char buf[2 * MSG_SIZ];
362 char *zippy = _(" (with Zippy code)");
366 snprintf(buf, sizeof(buf),
368 "Copyright 1991 Digital Equipment Corporation\n"
369 "Enhancements Copyright 1992-2014 Free Software Foundation\n"
370 "Enhancements Copyright 2005 Alessandro Scotti\n\n"
371 "%s is free software and carries NO WARRANTY;"
372 "see the file COPYING for more information.\n"
373 "The GTK build of this version is experimental and unstable\n\n"
374 "Visit XBoard on the web at: http://www.gnu.org/software/xboard/\n"
375 "Check out the newest features at: http://www.gnu.org/software/xboard/whats_new.html\n\n"
376 "Report bugs via email at: <bug-xboard@gnu.org>\n\n"
378 programVersion, zippy, PACKAGE);
379 ErrorPopUp(_("About XBoard"), buf, FALSE);
385 appData.debugMode = !appData.debugMode;
386 if(!strcmp(appData.nameOfDebugFile, "stderr")) return; // stderr is already open, and should never be closed
387 if(!appData.debugMode) fclose(debugFP);
389 debugFP = fopen(appData.nameOfDebugFile, "w");
390 if(debugFP == NULL) debugFP = stderr;
391 else setbuf(debugFP, NULL);
398 EditTagsPopUp(firstChessProgramNames, &firstChessProgramNames);
408 # define MARK_MENU_ITEM(X,Y)
410 # define MARK_MENU_ITEM(X,Y) MarkMenuItem(X, Y)
414 PonderNextMoveProc ()
416 PonderNextMoveEvent(!appData.ponderNextMove);
417 MARK_MENU_ITEM("Options.PonderNextMove", appData.ponderNextMove);
423 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
424 MARK_MENU_ITEM("Options.AlwaysQueen", appData.alwaysPromoteToQueen);
428 AnimateDraggingProc ()
430 appData.animateDragging = !appData.animateDragging;
432 if (appData.animateDragging) CreateAnimVars();
433 MARK_MENU_ITEM("Options.AnimateDragging", appData.animateDragging);
439 appData.animate = !appData.animate;
440 if (appData.animate) CreateAnimVars();
441 MARK_MENU_ITEM("Options.AnimateMoving", appData.animate);
447 appData.autoCallFlag = !appData.autoCallFlag;
448 MARK_MENU_ITEM("Options.AutoFlag", appData.autoCallFlag);
454 appData.autoFlipView = !appData.autoFlipView;
455 MARK_MENU_ITEM("Options.AutoFlipView", appData.autoFlipView);
461 appData.blindfold = !appData.blindfold;
462 MARK_MENU_ITEM("Options.Blindfold", appData.blindfold);
463 DrawPosition(True, NULL);
469 appData.testLegality = !appData.testLegality;
470 MARK_MENU_ITEM("Options.TestLegality", appData.testLegality);
477 if (appData.flashCount == 0) {
478 appData.flashCount = 3;
480 appData.flashCount = -appData.flashCount;
482 MARK_MENU_ITEM("Options.FlashMoves", appData.flashCount > 0);
487 HighlightDraggingProc ()
489 appData.highlightDragging = !appData.highlightDragging;
490 MARK_MENU_ITEM("Options.HighlightDragging", appData.highlightDragging);
495 HighlightLastMoveProc ()
497 appData.highlightLastMove = !appData.highlightLastMove;
498 MARK_MENU_ITEM("Options.HighlightLastMove", appData.highlightLastMove);
502 HighlightArrowProc ()
504 appData.highlightMoveWithArrow = !appData.highlightMoveWithArrow;
505 MARK_MENU_ITEM("Options.HighlightWithArrow", appData.highlightMoveWithArrow);
511 appData.icsAlarm = !appData.icsAlarm;
512 // MARK_MENU_ITEM("Options.ICSAlarm", appData.icsAlarm);
518 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
519 MARK_MENU_ITEM("Options.MoveSound", appData.ringBellAfterMoves);
525 appData.oneClick = !appData.oneClick;
526 MARK_MENU_ITEM("Options.OneClickMoving", appData.oneClick);
530 PeriodicUpdatesProc ()
532 PeriodicUpdatesEvent(!appData.periodicUpdates);
533 MARK_MENU_ITEM("Options.PeriodicUpdates", appData.periodicUpdates);
537 PopupExitMessageProc ()
539 appData.popupExitMessage = !appData.popupExitMessage;
540 MARK_MENU_ITEM("Options.PopupExitMessage", appData.popupExitMessage);
544 PopupMoveErrorsProc ()
546 appData.popupMoveErrors = !appData.popupMoveErrors;
547 MARK_MENU_ITEM("Options.PopupMoveErrors", appData.popupMoveErrors);
553 appData.premove = !appData.premove;
554 // MARK_MENU_ITEM("Options.Premove", appData.premove);
560 appData.showCoords = !appData.showCoords;
561 MARK_MENU_ITEM("Options.ShowCoords", appData.showCoords);
562 DrawPosition(True, NULL);
568 appData.showThinking = !appData.showThinking; // [HGM] thinking: taken out of ShowThinkingEvent
575 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: taken out of ShowThinkingEvent
578 MARK_MENU_ITEM("Options.HideThinking", appData.hideThinkingFromHuman);
584 ScheduleDelayedEvent(CreateBookEvent, 50);
590 FileNamePopUp(_("Save game file name?"),
597 * Menu definition tables
600 MenuItem fileMenu[] = {
601 {N_("New Game"), "<Ctrl>n", "NewGame", ResetGameEvent},
602 {N_("New Shuffle Game..."), NULL, "NewShuffleGame", ShuffleMenuProc},
603 {N_("New Variant..."), "<Alt><Shift>v", "NewVariant", NewVariantProc},// [HGM] variant: not functional yet
604 {"----", NULL, NULL, NothingProc},
605 {N_("Load Game"), "<Ctrl>o", "LoadGame", LoadGameProc, CHECK},
606 {N_("Load Position"), "<Ctrl><Shift>o", "LoadPosition", LoadPositionProc},
607 {N_("Next Position"), "<Shift>Page_Down", "LoadNextPosition", LoadNextPositionProc},
608 {N_("Prev Position"), "<Shift>Page_Up", "LoadPreviousPosition", LoadPrevPositionProc},
609 {"----", NULL, NULL, NothingProc},
610 {N_("Save Game"), "<Ctrl>s", "SaveGame", SaveGameProc},
611 {N_("Save Position"), "<Ctrl><Shift>s", "SavePosition", SavePositionProc},
612 {N_("Save Selected Games"), NULL, "SaveSelected", SaveSelectedProc},
613 {N_("Save Games as Book"), NULL, "CreateBook", CreateBookDelayed},
614 {"----", NULL, NULL, NothingProc},
615 {N_("Mail Move"), NULL, "MailMove", MailMoveEvent},
616 {N_("Reload CMail Message"), NULL, "ReloadCMailMessage", ReloadCmailMsgProc},
617 {"----", NULL, NULL, NothingProc},
618 {N_("Quit "), "<Ctrl>q", "Quit", QuitProc},
619 {NULL, NULL, NULL, NULL}
622 MenuItem editMenu[] = {
623 {N_("Copy Game"), "<Ctrl>c", "CopyGame", CopyGameProc},
624 {N_("Copy Position"), "<Ctrl><Shift>c", "CopyPosition", CopyPositionProc},
625 {N_("Copy Game List"), NULL, "CopyGameList", CopyGameListProc},
626 {"----", NULL, NULL, NothingProc},
627 {N_("Paste Game"), "<Ctrl>v", "PasteGame", PasteGameProc},
628 {N_("Paste Position"), "<Ctrl><Shift>v", "PastePosition", PastePositionProc},
629 {"----", NULL, NULL, NothingProc},
630 {N_("Edit Game"), "<Ctrl>e", "EditGame", EditGameEvent},
631 {N_("Edit Position"), "<Ctrl><Shift>e", "EditPosition", EditPositionEvent},
632 {N_("Edit Tags"), NULL, "EditTags", EditTagsProc},
633 {N_("Edit Comment"), NULL, "EditComment", EditCommentProc},
634 {N_("Edit Book"), NULL, "EditBook", EditBookEvent},
635 {"----", NULL, NULL, NothingProc},
636 {N_("Revert"), "Home", "Revert", RevertProc},
637 {N_("Annotate"), NULL, "Annotate", AnnotateProc},
638 {N_("Truncate Game"), "End", "TruncateGame", TruncateGameEvent},
639 {"----", NULL, NULL, NothingProc},
640 {N_("Backward"), "<Alt>Left", "Backward", BackwardEvent},
641 {N_("Forward"), "<Alt>Right", "Forward", ForwardEvent},
642 {N_("Back to Start"), "<Alt>Home", "BacktoStart", ToStartEvent},
643 {N_("Forward to End"), "<Alt>End", "ForwardtoEnd", ToEndEvent},
644 {NULL, NULL, NULL, NULL}
647 MenuItem viewMenu[] = {
648 {N_("Flip View"), "F2", "FlipView", FlipViewProc, CHECK},
649 {"----", NULL, NULL, NothingProc},
650 {N_("Engine Output"), "<Alt><Shift>o", "EngineOutput", EngineOutputProc, CHECK},
651 {N_("Move History"), "<Alt><Shift>h", "MoveHistory", HistoryShowProc, CHECK}, // [HGM] hist: activate 4.2.7 code
652 {N_("Evaluation Graph"), "<Alt><Shift>e", "EvaluationGraph", EvalGraphProc, CHECK},
653 {N_("Game List"), "<Alt><Shift>g", "GameList", ShowGameListProc, CHECK},
654 {N_("ICS text menu"), NULL, "ICStextmenu", IcsTextProc, CHECK},
655 {"----", NULL, NULL, NothingProc},
656 {N_("Tags"), NULL, "Tags", EditTagsProc, CHECK},
657 {N_("Comments"), NULL, "Comments", EditCommentProc, CHECK},
658 {N_("ICS Input Box"), NULL, "ICSInputBox", IcsInputBoxProc, CHECK},
659 {N_("ICS/Chat Console"), NULL, "OpenChatWindow", ChatProc, CHECK},
660 {"----", NULL, NULL, NothingProc},
661 {N_("Board..."), NULL, "Board", BoardOptionsProc},
662 {N_("Game List Tags..."), NULL, "GameListTags", GameListOptionsProc},
663 {NULL, NULL, NULL, NULL}
666 MenuItem modeMenu[] = {
667 {N_("Machine White"), "<Ctrl>w", "MachineWhite", MachineWhiteEvent, RADIO },
668 {N_("Machine Black"), "<Ctrl>b", "MachineBlack", MachineBlackEvent, RADIO },
669 {N_("Two Machines"), "<Ctrl>t", "TwoMachines", TwoMachinesEvent, RADIO },
670 {N_("Analysis Mode"), "<Ctrl>a", "AnalysisMode", (MenuProc*) AnalyzeModeEvent, RADIO },
671 {N_("Analyze Game"), "<Ctrl>g", "AnalyzeFile", AnalyzeFileEvent, RADIO },
672 {N_("Edit Game"), "<Ctrl>e", "EditGame", EditGameEvent, RADIO },
673 {N_("Edit Position"), "<Ctrl><Shift>e", "EditPosition", EditPositionEvent, RADIO },
674 {N_("Training"), NULL, "Training", TrainingEvent, RADIO },
675 {N_("ICS Client"), NULL, "ICSClient", IcsClientEvent, RADIO },
676 {"----", NULL, NULL, NothingProc},
677 {N_("Machine Match"), NULL, "MachineMatch", MatchProc, CHECK },
678 {N_("Pause"), "Pause", "Pause", PauseEvent, CHECK },
679 {NULL, NULL, NULL, NULL}
682 MenuItem actionMenu[] = {
683 {N_("Accept"), "F3", "Accept", AcceptEvent},
684 {N_("Decline"), "F4", "Decline", DeclineEvent},
685 {N_("Rematch"), "F12", "Rematch", RematchEvent},
686 {"----", NULL, NULL, NothingProc},
687 {N_("Call Flag"), "F5", "CallFlag", CallFlagEvent},
688 {N_("Draw"), "F6", "Draw", DrawEvent},
689 {N_("Adjourn"), "F7", "Adjourn", AdjournEvent},
690 {N_("Abort"), "F8", "Abort", AbortEvent},
691 {N_("Resign"), "F9", "Resign", ResignEvent},
692 {"----", NULL, NULL, NothingProc},
693 {N_("Stop Observing"), "F10", "StopObserving", StopObservingEvent},
694 {N_("Stop Examining"), "F11", "StopExamining", StopExaminingEvent},
695 {N_("Upload to Examine"), NULL, "UploadtoExamine", UploadGameEvent},
696 {"----", NULL, NULL, NothingProc},
697 {N_("Adjudicate to White"), NULL, "AdjudicatetoWhite", AdjuWhiteProc},
698 {N_("Adjudicate to Black"), NULL, "AdjudicatetoBlack", AdjuBlackProc},
699 {N_("Adjudicate Draw"), NULL, "AdjudicateDraw", AdjuDrawProc},
700 {NULL, NULL, NULL, NULL}
703 MenuItem engineMenu[100] = {
704 {N_("Edit Engine List..."), NULL, "EditEngList", EditEngineProc},
705 {"----", NULL, NULL, NothingProc},
706 {N_("Load New 1st Engine..."), NULL, "LoadNew1stEngine", LoadEngine1Proc},
707 {N_("Load New 2nd Engine..."), NULL, "LoadNew2ndEngine", LoadEngine2Proc},
708 {"----", NULL, NULL, NothingProc},
709 {N_("Engine #1 Settings..."), NULL, "Engine#1Settings", FirstSettingsProc},
710 {N_("Engine #2 Settings..."), NULL, "Engine#2Settings", SecondSettingsProc},
711 {"----", NULL, NULL, NothingProc},
712 {N_("Hint"), NULL, "Hint", HintEvent},
713 {N_("Book"), NULL, "Book", BookEvent},
714 {"----", NULL, NULL, NothingProc},
715 {N_("Move Now"), "<Ctrl>m", "MoveNow", MoveNowEvent},
716 {N_("Retract Move"), "<Ctrl>x", "RetractMove", RetractMoveEvent},
717 {NULL, NULL, NULL, NULL}
720 MenuItem optionsMenu[] = {
722 {N_("General..."), NULL, "General", OptionsProc},
724 {N_("Time Control..."), "<Alt><Shift>t", "TimeControl", TimeControlProc},
725 {N_("Common Engine..."), "<Alt><Shift>u", "CommonEngine", UciMenuProc},
726 {N_("Adjudications..."), "<Alt><Shift>j", "Adjudications", EngineMenuProc},
727 {N_("ICS..."), NULL, "ICS", IcsOptionsProc},
728 {N_("Tournament..."), NULL, "Match", MatchOptionsProc},
729 {N_("Load Game..."), NULL, "LoadGame", LoadOptionsProc},
730 {N_("Save Game..."), NULL, "SaveGame", SaveOptionsProc},
731 {N_("Game List..."), NULL, "GameList", GameListOptionsProc},
732 {N_("Sounds..."), NULL, "Sounds", SoundOptionsProc},
733 {"----", NULL, NULL, NothingProc},
734 #ifndef OPTIONSDIALOG
735 {N_("Always Queen"), "<Ctrl><Shift>q", "AlwaysQueen", AlwaysQueenProc},
736 {N_("Animate Dragging"), NULL, "AnimateDragging", AnimateDraggingProc},
737 {N_("Animate Moving"), "<Ctrl><Shift>a", "AnimateMoving", AnimateMovingProc},
738 {N_("Auto Flag"), "<Ctrl><Shift>f", "AutoFlag", AutoflagProc},
739 {N_("Auto Flip View"), NULL, "AutoFlipView", AutoflipProc},
740 {N_("Blindfold"), NULL, "Blindfold", BlindfoldProc},
741 {N_("Flash Moves"), NULL, "FlashMoves", FlashMovesProc},
743 {N_("Highlight Dragging"), NULL, "HighlightDragging", HighlightDraggingProc},
745 {N_("Highlight Last Move"), NULL, "HighlightLastMove", HighlightLastMoveProc},
746 {N_("Highlight With Arrow"), NULL, "HighlightWithArrow", HighlightArrowProc},
747 {N_("Move Sound"), NULL, "MoveSound", MoveSoundProc},
748 {N_("One-Click Moving"), NULL, "OneClickMoving", OneClickProc},
749 {N_("Periodic Updates"), NULL, "PeriodicUpdates", PeriodicUpdatesProc},
750 {N_("Ponder Next Move"), "<Ctrl><Shift>p", "PonderNextMove", PonderNextMoveProc},
751 {N_("Popup Exit Message"), NULL, "PopupExitMessage", PopupExitMessageProc},
752 {N_("Popup Move Errors"), NULL, "PopupMoveErrors", PopupMoveErrorsProc},
753 {N_("Show Coords"), NULL, "ShowCoords", ShowCoordsProc},
754 {N_("Hide Thinking"), "<Ctrl><Shift>h", "HideThinking", HideThinkingProc},
755 {N_("Test Legality"), "<Ctrl><Shift>l", "TestLegality", TestLegalityProc},
756 {"----", NULL, NULL, NothingProc},
758 {N_("Save Settings Now"), NULL, "SaveSettingsNow", SaveSettingsProc},
759 {N_("Save Settings on Exit"), NULL, "SaveSettingsonExit", SaveOnExitProc, CHECK },
760 {NULL, NULL, NULL, NULL}
763 MenuItem helpMenu[] = {
764 {N_("Info XBoard"), NULL, "InfoXBoard", InfoProc},
765 {N_("Man XBoard"), "F1", "ManXBoard", ManProc},
766 {"----", NULL, NULL, NothingProc},
767 {N_("XBoard Home Page"), NULL, "XBoardHomePage", HomePageProc},
768 {N_("On-line User Guide"), NULL, "On-lineUserGuide", GuideProc},
769 {N_("Development News"), NULL, "DevelopmentNews", NewsPageProc},
770 {N_("e-Mail Bug Report"), NULL, "e-MailBugReport", BugReportProc},
771 {"----", NULL, NULL, NothingProc},
772 {N_("About XBoard"), NULL, "AboutXBoard", AboutProc},
773 {NULL, NULL, NULL, NULL}
776 MenuItem noMenu[] = {
777 { "", "<Alt>Next" ,"LoadNextGame", LoadNextGameProc },
778 { "", "<Alt>Prior" ,"LoadPrevGame", LoadPrevGameProc },
779 { "", NULL,"ReloadGame", ReloadGameProc },
780 { "", NULL,"ReloadPosition", ReloadPositionProc },
781 #ifndef OPTIONSDIALOG
782 { "", NULL,"AlwaysQueen", AlwaysQueenProc },
783 { "", NULL,"AnimateDragging", AnimateDraggingProc },
784 { "", NULL,"AnimateMoving", AnimateMovingProc },
785 { "", NULL,"Autoflag", AutoflagProc },
786 { "", NULL,"Autoflip", AutoflipProc },
787 { "", NULL,"Blindfold", BlindfoldProc },
788 { "", NULL,"FlashMoves", FlashMovesProc },
790 { "", NULL,"HighlightDragging", HighlightDraggingProc },
792 { "", NULL,"HighlightLastMove", HighlightLastMoveProc },
793 { "", NULL,"MoveSound", MoveSoundProc },
794 { "", NULL,"PeriodicUpdates", PeriodicUpdatesProc },
795 { "", NULL,"PopupExitMessage", PopupExitMessageProc },
796 { "", NULL,"PopupMoveErrors", PopupMoveErrorsProc },
797 { "", NULL,"ShowCoords", ShowCoordsProc },
798 { "", NULL,"ShowThinking", ShowThinkingProc },
799 { "", NULL,"HideThinking", HideThinkingProc },
800 { "", NULL,"TestLegality", TestLegalityProc },
802 { "", NULL,"AboutGame", AboutGameEvent },
803 { "", "<Ctrl>d" ,"DebugProc", DebugProc },
804 { "", NULL,"Nothing", NothingProc },
805 {NULL, NULL, NULL, NULL}
809 {N_("File"), "File", fileMenu},
810 {N_("Edit"), "Edit", editMenu},
811 {N_("View"), "View", viewMenu},
812 {N_("Mode"), "Mode", modeMenu},
813 {N_("Action"), "Action", actionMenu},
814 {N_("Engine"), "Engine", engineMenu},
815 {N_("Options"), "Options", optionsMenu},
816 {N_("Help"), "Help", helpMenu},
818 { "", "None", noMenu}
822 MenuNameToItem (char *menuName)
825 char buf[MSG_SIZ], *p;
827 static MenuItem a = { NULL, NULL, NULL, NothingProc };
828 extern Option mainOptions[];
829 safeStrCpy(buf, menuName, MSG_SIZ);
830 p = strchr(buf, '.');
831 if(!p) menuTab = noMenu, p = menuName; else {
833 for(i=0; menuBar[i].name; i++)
834 if(!strcmp(buf, menuBar[i].name)) break;
835 if(!menuBar[i].name) return NULL; // main menu not found
836 menuTab = menuBar[i].mi;
838 if(*p == NULLCHAR) { a.handle = mainOptions[i+1].handle; return &a; } // main menu bar
839 for(i=0; menuTab[i].string; i++)
840 if(menuTab[i].ref && !strcmp(p, menuTab[i].ref)) return menuTab + i;
841 return NULL; // item not found
847 AppendEnginesToMenu (char *list)
851 if(appData.icsActive || appData.recentEngines <= 0) return;
852 for(firstEngineItem=0; engineMenu[firstEngineItem].string; firstEngineItem++);
853 recentEngines = strdup(list);
855 p = strchr(list, '\n'); if(p == NULL) break;
856 if(i == 0) engineMenu[firstEngineItem++].string = "----"; // at least one valid item to add
858 if(firstEngineItem + i < 99)
859 engineMenu[firstEngineItem+i].string = strdup(list); // just set name; MenuProc stays NULL
860 i++; *p = '\n'; list = p + 1;
864 Enables icsEnables[] = {
865 { "File.MailMove", False },
866 { "File.ReloadCMailMessage", False },
867 { "Mode.MachineBlack", False },
868 { "Mode.MachineWhite", False },
869 { "Mode.AnalysisMode", False },
870 { "Mode.AnalyzeFile", False },
871 { "Mode.TwoMachines", False },
872 { "Mode.MachineMatch", False },
874 { "Engine.Hint", False },
875 { "Engine.Book", False },
876 { "Engine.MoveNow", False },
877 #ifndef OPTIONSDIALOG
878 { "PeriodicUpdates", False },
879 { "HideThinking", False },
880 { "PonderNextMove", False },
883 { "Engine.Engine#1Settings", False },
884 { "Engine.Engine#2Settings", False },
885 { "Engine.Load1stEngine", False },
886 { "Engine.Load2ndEngine", False },
887 { "Edit.Annotate", False },
888 { "Options.Match", False },
892 Enables ncpEnables[] = {
893 { "File.MailMove", False },
894 { "File.ReloadCMailMessage", False },
895 { "Mode.MachineWhite", False },
896 { "Mode.MachineBlack", False },
897 { "Mode.AnalysisMode", False },
898 { "Mode.AnalyzeFile", False },
899 { "Mode.TwoMachines", False },
900 { "Mode.MachineMatch", False },
901 { "Mode.ICSClient", False },
902 { "View.ICStextmenu", False },
903 { "View.ICSInputBox", False },
904 { "View.OpenChatWindow", False },
905 { "Action.", False },
906 { "Edit.Revert", False },
907 { "Edit.Annotate", False },
908 { "Engine.Engine#1Settings", False },
909 { "Engine.Engine#2Settings", False },
910 { "Engine.MoveNow", False },
911 { "Engine.RetractMove", False },
912 { "Options.ICS", False },
913 #ifndef OPTIONSDIALOG
914 { "Options.AutoFlag", False },
915 { "Options.AutoFlip View", False },
916 // { "Options.ICSAlarm", False },
917 { "Options.MoveSound", False },
918 { "Options.HideThinking", False },
919 { "Options.PeriodicUpdates", False },
920 { "Options.PonderNextMove", False },
922 { "Engine.Hint", False },
923 { "Engine.Book", False },
927 Enables gnuEnables[] = {
928 { "Mode.ICSClient", False },
929 { "View.ICStextmenu", False },
930 { "View.ICSInputBox", False },
931 { "View.OpenChatWindow", False },
932 { "Action.Accept", False },
933 { "Action.Decline", False },
934 { "Action.Rematch", False },
935 { "Action.Adjourn", False },
936 { "Action.StopExamining", False },
937 { "Action.StopObserving", False },
938 { "Action.UploadtoExamine", False },
939 { "Edit.Revert", False },
940 { "Edit.Annotate", False },
941 { "Options.ICS", False },
943 /* The next two options rely on SetCmailMode being called *after* */
944 /* SetGNUMode so that when GNU is being used to give hints these */
945 /* menu options are still available */
947 { "File.MailMove", False },
948 { "File.ReloadCMailMessage", False },
949 // [HGM] The following have been added to make a switch from ncp to GNU mode possible
950 { "Mode.MachineWhite", True },
951 { "Mode.MachineBlack", True },
952 { "Mode.AnalysisMode", True },
953 { "Mode.AnalyzeFile", True },
954 { "Mode.TwoMachines", True },
955 { "Mode.MachineMatch", True },
956 { "Engine.Engine#1Settings", True },
957 { "Engine.Engine#2Settings", True },
958 { "Engine.Hint", True },
959 { "Engine.Book", True },
960 { "Engine.MoveNow", True },
961 { "Engine.RetractMove", True },
966 Enables cmailEnables[] = {
968 { "Action.CallFlag", False },
969 { "Action.Draw", True },
970 { "Action.Adjourn", False },
971 { "Action.Abort", False },
972 { "Action.StopObserving", False },
973 { "Action.StopExamining", False },
974 { "File.MailMove", True },
975 { "File.ReloadCMailMessage", True },
979 Enables trainingOnEnables[] = {
980 { "Edit.EditComment", False },
981 { "Mode.Pause", False },
982 { "Edit.Forward", False },
983 { "Edit.Backward", False },
984 { "Edit.ForwardtoEnd", False },
985 { "Edit.BacktoStart", False },
986 { "Engine.MoveNow", False },
987 { "Edit.TruncateGame", False },
991 Enables trainingOffEnables[] = {
992 { "Edit.EditComment", True },
993 { "Mode.Pause", True },
994 { "Edit.Forward", True },
995 { "Edit.Backward", True },
996 { "Edit.ForwardtoEnd", True },
997 { "Edit.BacktoStart", True },
998 { "Engine.MoveNow", True },
999 { "Engine.TruncateGame", True },
1003 Enables machineThinkingEnables[] = {
1004 { "File.LoadGame", False },
1005 // { "LoadNextGame", False },
1006 // { "LoadPreviousGame", False },
1007 // { "ReloadSameGame", False },
1008 { "Edit.PasteGame", False },
1009 { "File.LoadPosition", False },
1010 // { "LoadNextPosition", False },
1011 // { "LoadPreviousPosition", False },
1012 // { "ReloadSamePosition", False },
1013 { "Edit.PastePosition", False },
1014 { "Mode.MachineWhite", False },
1015 { "Mode.MachineBlack", False },
1016 { "Mode.TwoMachines", False },
1017 // { "MachineMatch", False },
1018 { "Engine.RetractMove", False },
1022 Enables userThinkingEnables[] = {
1023 { "File.LoadGame", True },
1024 // { "LoadNextGame", True },
1025 // { "LoadPreviousGame", True },
1026 // { "ReloadSameGame", True },
1027 { "Edit.PasteGame", True },
1028 { "File.LoadPosition", True },
1029 // { "LoadNextPosition", True },
1030 // { "LoadPreviousPosition", True },
1031 // { "ReloadSamePosition", True },
1032 { "Edit.PastePosition", True },
1033 { "Mode.MachineWhite", True },
1034 { "Mode.MachineBlack", True },
1035 { "Mode.TwoMachines", True },
1036 // { "MachineMatch", True },
1037 { "Engine.RetractMove", True },
1044 SetMenuEnables(icsEnables);
1047 if (appData.zippyPlay && !appData.noChessProgram) { /* [DM] icsEngineAnalyze */
1048 EnableNamedMenuItem("Mode.AnalysisMode", True);
1049 EnableNamedMenuItem("Engine.Engine#1Settings", True);
1057 SetMenuEnables(ncpEnables);
1063 SetMenuEnables(gnuEnables);
1069 SetMenuEnables(cmailEnables);
1073 SetTrainingModeOn ()
1075 SetMenuEnables(trainingOnEnables);
1076 if (appData.showButtonBar) {
1077 EnableButtonBar(False);
1083 SetTrainingModeOff ()
1085 SetMenuEnables(trainingOffEnables);
1086 if (appData.showButtonBar) {
1087 EnableButtonBar(True);
1092 SetUserThinkingEnables ()
1094 if (appData.noChessProgram) return;
1095 SetMenuEnables(userThinkingEnables);
1099 SetMachineThinkingEnables ()
1101 if (appData.noChessProgram) return;
1102 SetMenuEnables(machineThinkingEnables);
1104 case MachinePlaysBlack:
1105 case MachinePlaysWhite:
1106 case TwoMachinesPlay:
1107 EnableNamedMenuItem(ModeToWidgetName(gameMode), True);
1115 GreyRevert (Boolean grey)
1117 EnableNamedMenuItem("Edit.Revert", !grey);
1118 EnableNamedMenuItem("Edit.Annotate", !grey);
1122 ModeToWidgetName (GameMode mode)
1125 case BeginningOfGame:
1126 if (appData.icsActive)
1127 return "Mode.ICSClient";
1128 else if (appData.noChessProgram ||
1129 *appData.cmailGameName != NULLCHAR)
1130 return "Mode.EditGame";
1132 return "Mode.MachineBlack";
1133 case MachinePlaysBlack:
1134 return "Mode.MachineBlack";
1135 case MachinePlaysWhite:
1136 return "Mode.MachineWhite";
1138 return "Mode.AnalysisMode";
1140 return "Mode.AnalyzeFile";
1141 case TwoMachinesPlay:
1142 return "Mode.TwoMachines";
1144 return "Mode.EditGame";
1145 case PlayFromGameFile:
1146 return "File.LoadGame";
1148 return "Mode.EditPosition";
1150 return "Mode.Training";
1151 case IcsPlayingWhite:
1152 case IcsPlayingBlack:
1156 return "Mode.ICSClient";
1164 InstallNewEngine (char *command, char *dir, char *variants, char *protocol)
1165 { // install the given engine in XBoard's -firstChessProgramNames
1166 char buf[MSG_SIZ], *quote = "";
1167 if(strchr(command, ' ')) { // quoting needed
1168 if(!strchr(command, '"')) quote = "\""; else
1169 if(!strchr(command, '\'')) quote = "'"; else {
1170 printf("Could not auto-install %s\n", command); // too complex
1173 // construct engine line, with optional -fd and -fUCI arguments
1174 snprintf(buf, MSG_SIZ, "%s%s%s", quote, command, quote);
1175 if(strcmp(dir, "") && strcmp(dir, "."))
1176 snprintf(buf + strlen(buf), MSG_SIZ - strlen(buf), " -fd %s", dir);
1177 if(!strcmp(protocol, "uci"))
1178 snprintf(buf + strlen(buf), MSG_SIZ - strlen(buf), " -fUCI");
1180 quote = malloc(strlen(firstChessProgramNames) + strlen(buf) + 2);
1181 sprintf(quote, "%s%s\n", firstChessProgramNames, buf);
1182 FREE(firstChessProgramNames); firstChessProgramNames = quote;
1185 #ifdef HAVE_DIRENT_H
1188 #include <sys/dir.h>
1189 #define dirent direct
1193 InstallFromDir (char *dirName, char *protocol, char *settingsFile)
1194 { // scan system for new plugin specs in given directory
1197 struct stat statBuf;
1198 time_t lastSaved = 0;
1201 if(!stat(settingsFile, &statBuf)) lastSaved = statBuf.st_mtime;
1202 snprintf(buf, 1024, "%s/%s", dirName, protocol);
1204 if(!(dir = opendir(buf))) return;
1205 while( (dp = readdir(dir))) {
1206 time_t installed = 0;
1207 if(!strstr(dp->d_name, ".eng")) continue; // to suppress . and ..
1208 snprintf(buf, 1024, "%s/%s/%s", dirName, protocol, dp->d_name);
1209 if(!stat(buf, &statBuf)) installed = statBuf.st_mtime;
1210 if(lastSaved == 0 || (int) (installed - lastSaved) > 0) { // first time we see it
1211 FILE *f = fopen(buf, "r");
1212 if(f) { // read the plugin-specs
1213 char engineCommand[1024], engineDir[1024], variants[1024];
1214 char bad=0, dummy, *engineCom = engineCommand;
1216 if(fscanf(f, "plugin spec %d.%d%c", &major, &minor, &dummy) != 3 ||
1217 fscanf(f, "%[^\n]%c", engineCommand, &dummy) != 2 ||
1218 fscanf(f, "%[^\n]%c", variants, &dummy) != 2) bad = 1;
1221 // uncomment following two lines for chess-only installs
1222 // if(!(p = strstr(variants, "chess")) ||
1223 // p != variants && p[-1] != ',' || p[5] && p[5] != ',') continue;
1224 // split off engine working directory (if any)
1225 strcpy(engineDir, "");
1226 if(sscanf(engineCommand, "cd %[^;];%c", engineDir, &dummy) == 2)
1227 engineCom = engineCommand + strlen(engineDir) + 4;
1228 InstallNewEngine(engineCom, engineDir, variants, protocol);
1236 AutoInstallProtocol (char *settingsFile, char *protocol)
1237 { // install new engines for given protocol (both from package and source)
1238 InstallFromDir("/usr/local/share/games/plugins", protocol, settingsFile);
1239 InstallFromDir("/usr/share/games/plugins", protocol, settingsFile);
1243 AutoInstall (char *settingsFile)
1244 { // install all new XBoard and UCI engines
1245 AutoInstallProtocol(settingsFile, "xboard");
1246 AutoInstallProtocol(settingsFile, "uci");
1252 #ifndef OPTIONSDIALOG
1253 if (appData.alwaysPromoteToQueen) {
1254 MarkMenuItem("Options.Always Queen", True);
1256 if (appData.animateDragging) {
1257 MarkMenuItem("Options.Animate Dragging", True);
1259 if (appData.animate) {
1260 MarkMenuItem("Options.Animate Moving", True);
1262 if (appData.autoCallFlag) {
1263 MarkMenuItem("Options.Auto Flag", True);
1265 if (appData.autoFlipView) {
1266 XtSetValues(XtNameToWidget(menuBarWidget,"Options.Auto Flip View", True);
1268 if (appData.blindfold) {
1269 MarkMenuItem("Options.Blindfold", True);
1271 if (appData.flashCount > 0) {
1272 MarkMenuItem("Options.Flash Moves", True);
1275 if (appData.highlightDragging) {
1276 MarkMenuItem("Options.Highlight Dragging", True);
1279 if (appData.highlightLastMove) {
1280 MarkMenuItem("Options.Highlight Last Move", True);
1282 if (appData.highlightMoveWithArrow) {
1283 MarkMenuItem("Options.Arrow", True);
1285 // if (appData.icsAlarm) {
1286 // MarkMenuItem("Options.ICS Alarm", True);
1288 if (appData.ringBellAfterMoves) {
1289 MarkMenuItem("Options.Move Sound", True);
1291 if (appData.oneClick) {
1292 MarkMenuItem("Options.OneClick", True);
1294 if (appData.periodicUpdates) {
1295 MarkMenuItem("Options.Periodic Updates", True);
1297 if (appData.ponderNextMove) {
1298 MarkMenuItem("Options.Ponder Next Move", True);
1300 if (appData.popupExitMessage) {
1301 MarkMenuItem("Options.Popup Exit Message", True);
1303 if (appData.popupMoveErrors) {
1304 MarkMenuItem("Options.Popup Move Errors", True);
1306 // if (appData.premove) {
1307 // MarkMenuItem("Options.Premove", True);
1309 if (appData.showCoords) {
1310 MarkMenuItem("Options.Show Coords", True);
1312 if (appData.hideThinkingFromHuman) {
1313 MarkMenuItem("Options.Hide Thinking", True);
1315 if (appData.testLegality) {
1316 MarkMenuItem("Options.Test Legality", True);
1319 if (saveSettingsOnExit) {
1320 MarkMenuItem("Options.SaveSettingsonExit", True);
1322 EnableNamedMenuItem("File.SaveSelected", False);
1324 // all XBoard builds get here, but not WinBoard...
1325 if(*appData.autoInstall) AutoInstall(settingsFileName);