Fix multi-leg promotions
[xboard.git] / menus.c
diff --git a/menus.c b/menus.c
index 23e09ea..50968c1 100644 (file)
--- a/menus.c
+++ b/menus.c
@@ -5,7 +5,8 @@
  * Massachusetts.
  *
  * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+ * 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:
@@ -87,8 +88,6 @@ extern char *getenv();
 
 #include "frontend.h"
 #include "backend.h"
-#include "xhistory.h"
-#include "xedittags.h"
 #include "menus.h"
 #include "gettext.h"
 
@@ -107,6 +106,7 @@ extern char *getenv();
 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)
@@ -173,12 +173,14 @@ ReloadPositionProc ()
 }
 
 void
-LoadPositionProc() 
+LoadPositionProc()
 {
+    static char buf[MSG_SIZ];
     if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
        Reset(FALSE, TRUE);
     }
-    FileNamePopUp(_("Load position file name?"), "", ".fen .epd .pos", LoadPosition, "rb");
+    snprintf(buf, MSG_SIZ, "%s/", appData.positionDir);
+    FileNamePopUp(_("Load position file name?"), buf, ".fen .epd .pos", LoadPosition, "rb");
 }
 
 void
@@ -217,7 +219,7 @@ 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);
+    selected_fen_position = (char *)PositionToFEN(currentMove, NULL, 1);
     if (!selected_fen_position) return;
     CopySomething(selected_fen_position);
 }
@@ -256,6 +258,8 @@ QuitProc ()
 void
 MatchProc ()
 {
+    static Enables matchOff[] = { { "Mode.MachineMatch", False }, { NULL, False } };
+    if(matchMode) SetMenuEnables(matchOff);
     MatchEvent(2);
 }
 
@@ -312,15 +316,6 @@ SaveSettingsProc ()
 }
 
 void
-InfoProc ()
-{
-    char buf[MSG_SIZ];
-    snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
-           INFODIR, INFOFILE);
-    system(buf);
-}
-
-void
 BugReportProc ()
 {
     char buf[MSG_SIZ];
@@ -361,10 +356,10 @@ AboutProc ()
 #else
     char *zippy = "";
 #endif
-    snprintf(buf, sizeof(buf), 
+    snprintf(buf, sizeof(buf),
 _("%s%s\n\n"
 "Copyright 1991 Digital Equipment Corporation\n"
-"Enhancements Copyright 1992-2012 Free Software Foundation\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"
@@ -390,6 +385,24 @@ DebugProc ()
 }
 
 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
 NothingProc ()
 {
     return;
@@ -569,221 +582,234 @@ HideThinkingProc ()
   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        Ctrl+N"),        "NewGame", ResetGameEvent},
-    {N_("New Shuffle Game ..."),          "NewShuffleGame", ShuffleMenuProc},
-    {N_("New Variant ...   Alt+Shift+V"), "NewVariant", NewVariantProc},      // [HGM] variant: not functional yet
-    {"----", NULL, NothingProc},
-    {N_("Load Game       Ctrl+O"),        "LoadGame", LoadGameProc},
-    {N_("Load Position    Ctrl+Shift+O"), "LoadPosition", LoadPositionProc},
-//    {N_("Load Next Game"), "LoadNextGame", LoadNextGameProc},
-//    {N_("Load Previous Game"), "LoadPreviousGame", LoadPrevGameProc},
-//    {N_("Reload Same Game"), "ReloadSameGame", ReloadGameProc},
-    {N_("Next Position     Shift+PgDn"), "LoadNextPosition", LoadNextPositionProc},
-    {N_("Prev Position     Shift+PgUp"), "LoadPreviousPosition", LoadPrevPositionProc},
-    {"----", NULL, NothingProc},
-//    {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
-    {N_("Save Game       Ctrl+S"),        "SaveGame", SaveGameProc},
-    {N_("Save Position    Ctrl+Shift+S"), "SavePosition", SavePositionProc},
-    {"----", NULL, NothingProc},
-    {N_("Mail Move"),            "MailMove", MailMoveEvent},
-    {N_("Reload CMail Message"), "ReloadCMailMessage", ReloadCmailMsgProc},
-    {"----", NULL, NothingProc},
-    {N_("Quit                 Ctr+Q"), "Quit", QuitProc},
-    {NULL, NULL, NULL}
+  {N_("New Game"),             "<Ctrl>n",          "NewGame",              ResetGameEvent},
+  {N_("New Shuffle Game..."),   NULL,              "NewShuffleGame",       ShuffleMenuProc},
+  {N_("New Variant..."),       "<Alt><Shift>v",    "NewVariant",           NewVariantProc},// [HGM] variant: not functional yet
+  {"----",                      NULL,               NULL,                  NothingProc},
+  {N_("Load Game"),            "<Ctrl>o",          "LoadGame",             LoadGameProc,           CHECK},
+  {N_("Load Position"),        "<Ctrl><Shift>o",   "LoadPosition",         LoadPositionProc},
+  {N_("Next Position"),        "<Shift>Page_Down", "LoadNextPosition",     LoadNextPositionProc},
+  {N_("Prev Position"),        "<Shift>Page_Up",   "LoadPreviousPosition", LoadPrevPositionProc},
+  {"----",                      NULL,               NULL,                  NothingProc},
+  {N_("Save Game"),            "<Ctrl>s",          "SaveGame",             SaveGameProc},
+  {N_("Save Position"),        "<Ctrl><Shift>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 "),                "<Ctrl>q",          "Quit",                 QuitProc},
+  {NULL,                        NULL,               NULL,                  NULL}
 };
 
 MenuItem editMenu[] = {
-    {N_("Copy Game    Ctrl+C"),        "CopyGame", CopyGameProc},
-    {N_("Copy Position Ctrl+Shift+C"), "CopyPosition", CopyPositionProc},
-    {N_("Copy Game List"),        "CopyGameList", CopyGameListProc},
-    {"----", NULL, NothingProc},
-    {N_("Paste Game    Ctrl+V"),        "PasteGame", PasteGameProc},
-    {N_("Paste Position Ctrl+Shift+V"), "PastePosition", PastePositionProc},
-    {"----", NULL, NothingProc},
-    {N_("Edit Game      Ctrl+E"),        "EditGame", EditGameEvent},
-    {N_("Edit Position   Ctrl+Shift+E"), "EditPosition", EditPositionEvent},
-    {N_("Edit Tags"),                    "EditTags", EditTagsProc},
-    {N_("Edit Comment"),                 "EditComment", EditCommentProc},
-    {N_("Edit Book"),                    "EditBook", EditBookEvent},
-    {"----", NULL, NothingProc},
-    {N_("Revert              Home"), "Revert", RevertProc},
-    {N_("Annotate"),                 "Annotate", AnnotateProc},
-    {N_("Truncate Game  End"),       "TruncateGame", TruncateGameEvent},
-    {"----", NULL, NothingProc},
-    {N_("Backward         Alt+Left"),   "Backward", BackwardEvent},
-    {N_("Forward           Alt+Right"), "Forward", ForwardEvent},
-    {N_("Back to Start     Alt+Home"),  "BacktoStart", ToStartEvent},
-    {N_("Forward to End Alt+End"),      "ForwardtoEnd", ToEndEvent},
-    {NULL, NULL, NULL}
+  {N_("Copy Game"),      "<Ctrl>c",        "CopyGame",      CopyGameProc},
+  {N_("Copy Position"),  "<Ctrl><Shift>c", "CopyPosition",  CopyPositionProc},
+  {N_("Copy Game List"),  NULL,            "CopyGameList",  CopyGameListProc},
+  {"----",                NULL,             NULL,           NothingProc},
+  {N_("Paste Game"),     "<Ctrl>v",        "PasteGame",     PasteGameProc},
+  {N_("Paste Position"), "<Ctrl><Shift>v", "PastePosition", PastePositionProc},
+  {"----",                NULL,             NULL,           NothingProc},
+  {N_("Edit Game"),      "<Ctrl>e",        "EditGame",      EditGameEvent},
+  {N_("Edit Position"),  "<Ctrl><Shift>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"),       "<Alt>Left",      "Backward",      BackwardEvent},
+  {N_("Forward"),        "<Alt>Right",     "Forward",       ForwardEvent},
+  {N_("Back to Start"),  "<Alt>Home",      "BacktoStart",   ToStartEvent},
+  {N_("Forward to End"), "<Alt>End",       "ForwardtoEnd",  ToEndEvent},
+  {NULL,                  NULL,             NULL,          NULL}
 };
 
 MenuItem viewMenu[] = {
-    {N_("Flip View             F2"),         "FlipView", FlipViewProc},
-    {"----", NULL, NothingProc},
-    {N_("Engine Output      Alt+Shift+O"),   "EngineOutput", EngineOutputProc},
-    {N_("Move History       Alt+Shift+H"),   "MoveHistory", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
-    {N_("Evaluation Graph  Alt+Shift+E"),    "EvaluationGraph", EvalGraphProc},
-    {N_("Game List            Alt+Shift+G"), "GameList", ShowGameListProc},
-    {N_("ICS text menu"), "ICStextmenu", IcsTextProc},
-    {"----", NULL, NothingProc},
-    {N_("Tags"),             "Tags", EditTagsProc},
-    {N_("Comments"),         "Comments", EditCommentProc},
-    {N_("ICS Input Box"),    "ICSInputBox", IcsInputBoxProc},
-    {N_("Open Chat Window"), "OpenChatWindow", ChatProc},
-    {"----", NULL, NothingProc},
-    {N_("Board..."),          "Board", BoardOptionsProc},
-    {N_("Game List Tags..."), "GameListTags", GameListOptionsProc},
-    {NULL, NULL, NULL}
+  {N_("Flip View"),         "F2",            "FlipView",        FlipViewProc,           CHECK},
+  {"----",                   NULL,            NULL,             NothingProc},
+  {N_("Engine Output"),     "<Alt><Shift>o", "EngineOutput",    EngineOutputProc,       CHECK},
+  {N_("Move History"),      "<Alt><Shift>h", "MoveHistory",     HistoryShowProc,        CHECK}, // [HGM] hist: activate 4.2.7 code
+  {N_("Evaluation Graph"),  "<Alt><Shift>e", "EvaluationGraph", EvalGraphProc,          CHECK},
+  {N_("Game List"),         "<Alt><Shift>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  Ctrl+W"), "MachineWhite", MachineWhiteEvent},
-    {N_("Machine Black  Ctrl+B"), "MachineBlack", MachineBlackEvent},
-    {N_("Two Machines   Ctrl+T"), "TwoMachines", TwoMachinesEvent},
-    {N_("Analysis Mode  Ctrl+A"), "AnalysisMode", (MenuProc*) AnalyzeModeEvent},
-    {N_("Analyze Game   Ctrl+G"), "AnalyzeFile", AnalyzeFileEvent },
-    {N_("Edit Game         Ctrl+E"), "EditGame", EditGameEvent},
-    {N_("Edit Position      Ctrl+Shift+E"), "EditPosition", EditPositionEvent},
-    {N_("Training"),      "Training", TrainingEvent},
-    {N_("ICS Client"),    "ICSClient", IcsClientEvent},
-    {"----", NULL, NothingProc},
-    {N_("Machine Match"),         "MachineMatch", MatchProc},
-    {N_("Pause               Pause"),         "Pause", PauseEvent},
-    {NULL, NULL, NULL}
+  {N_("Machine White"),  "<Ctrl>w",        "MachineWhite",  MachineWhiteEvent,              RADIO },
+  {N_("Machine Black"),  "<Ctrl>b",        "MachineBlack",  MachineBlackEvent,              RADIO },
+  {N_("Two Machines"),   "<Ctrl>t",        "TwoMachines",   TwoMachinesEvent,               RADIO },
+  {N_("Analysis Mode"),  "<Ctrl>a",        "AnalysisMode",  (MenuProc*) AnalyzeModeEvent,   RADIO },
+  {N_("Analyze Game"),   "<Ctrl>g",        "AnalyzeFile",   AnalyzeFileEvent,               RADIO },
+  {N_("Edit Game"),      "<Ctrl>e",        "EditGame",      EditGameEvent,                  RADIO },
+  {N_("Edit Position"),  "<Ctrl><Shift>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, 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, NothingProc},
-    {N_("Stop Observing  F10"), "StopObserving", StopObservingEvent},
-    {N_("Stop Examining  F11"), "StopExamining", StopExaminingEvent},
-    {N_("Upload to Examine"),   "UploadtoExamine", UploadGameEvent},
-    {"----", NULL, NothingProc},
-    {N_("Adjudicate to White"), "AdjudicatetoWhite", AdjuWhiteProc},
-    {N_("Adjudicate to Black"), "AdjudicatetoBlack", AdjuBlackProc},
-    {N_("Adjudicate Draw"),     "AdjudicateDraw", AdjuDrawProc},
-    {NULL, NULL, NULL}
+  {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[] = {
-    {N_("Load New 1st Engine ..."), "LoadNew1stEngine", LoadEngine1Proc},
-    {N_("Load New 2nd Engine ..."), "LoadNew2ndEngine", LoadEngine2Proc},
-    {"----", NULL, NothingProc},
-    {N_("Engine #1 Settings ..."), "Engine#1Settings", FirstSettingsProc},
-    {N_("Engine #2 Settings ..."), "Engine#2Settings", SecondSettingsProc},
-    {"----", NULL, NothingProc},
-    {N_("Hint"), "Hint", HintEvent},
-    {N_("Book"), "Book", BookEvent},
-    {"----", NULL, NothingProc},
-    {N_("Move Now     Ctrl+M"),     "MoveNow", MoveNowEvent},
-    {N_("Retract Move  Ctrl+X"), "RetractMove", RetractMoveEvent},
-    {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..."), "<Alt><Shift>u","CommonEngine",     UciMenuProc},
+  {"----",                         NULL,      NULL,              NothingProc},
+  {N_("Hint"),                     NULL,     "Hint",             HintEvent},
+  {N_("Book"),                     NULL,     "Book",             BookEvent},
+  {"----",                         NULL,      NULL,              NothingProc},
+  {N_("Move Now"),                "<Ctrl>m", "MoveNow",          MoveNowEvent},
+  {N_("Retract Move"),            "<Ctrl>x", "RetractMove",      RetractMoveEvent},
+  {NULL,                           NULL,      NULL,              NULL}
 };
 
 MenuItem optionsMenu[] = {
 #ifdef OPTIONSDIALOG
-    {N_("General ..."), "General", OptionsProc},
+  {N_("General..."),              NULL,             "General",             OptionsProc},
 #endif
-    {N_("Time Control ...       Alt+Shift+T"), "TimeControl", TimeControlProc},
-    {N_("Common Engine ...  Alt+Shift+U"),     "CommonEngine", UciMenuProc},
-    {N_("Adjudications ...      Alt+Shift+J"), "Adjudications", EngineMenuProc},
-    {N_("ICS ..."),    "ICS", IcsOptionsProc},
-    {N_("Match ..."), "Match", MatchOptionsProc},
-    {N_("Load Game ..."),    "LoadGame", LoadOptionsProc},
-    {N_("Save Game ..."),    "SaveGame", SaveOptionsProc},
-//    {N_(" ..."),    "", OptionsProc},
-    {N_("Game List ..."),    "GameList", GameListOptionsProc},
-    {N_("Sounds ..."),    "Sounds", SoundOptionsProc},
-    {"----", NULL, NothingProc},
+  {N_("Time Control..."),        "<Alt><Shift>t",   "TimeControl",         TimeControlProc},
+  {N_("Adjudications..."),       "<Alt><Shift>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        Ctrl+Shift+Q"),   "AlwaysQueen", AlwaysQueenProc},
-    {N_("Animate Dragging"), "AnimateDragging", AnimateDraggingProc},
-    {N_("Animate Moving      Ctrl+Shift+A"),   "AnimateMoving", AnimateMovingProc},
-    {N_("Auto Flag               Ctrl+Shift+F"), "AutoFlag", AutoflagProc},
-    {N_("Auto Flip View"),   "AutoFlipView", AutoflipProc},
-    {N_("Blindfold"),        "Blindfold", BlindfoldProc},
-    {N_("Flash Moves"),      "FlashMoves", FlashMovesProc},
+  {N_("Always Queen"),           "<Ctrl><Shift>q",  "AlwaysQueen",         AlwaysQueenProc},
+  {N_("Animate Dragging"),        NULL,             "AnimateDragging",     AnimateDraggingProc},
+  {N_("Animate Moving"),         "<Ctrl><Shift>a",  "AnimateMoving",       AnimateMovingProc},
+  {N_("Auto Flag"),              "<Ctrl><Shift>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"),    "HighlightDragging", HighlightDraggingProc},
+  {N_("Highlight Dragging"),      NULL,             "HighlightDragging",   HighlightDraggingProc},
 #endif
-    {N_("Highlight Last Move"),   "HighlightLastMove", HighlightLastMoveProc},
-    {N_("Highlight With Arrow"),  "HighlightWithArrow", HighlightArrowProc},
-    {N_("Move Sound"),            "MoveSound", MoveSoundProc},
-//    {N_("ICS Alarm"),             "ICSAlarm", IcsAlarmProc},
-    {N_("One-Click Moving"),      "OneClickMoving", OneClickProc},
-    {N_("Periodic Updates"),      "PeriodicUpdates", PeriodicUpdatesProc},
-    {N_("Ponder Next Move  Ctrl+Shift+P"), "PonderNextMove", PonderNextMoveProc},
-    {N_("Popup Exit Message"),    "PopupExitMessage", PopupExitMessageProc},
-    {N_("Popup Move Errors"),     "PopupMoveErrors", PopupMoveErrorsProc},
-//    {N_("Premove"),               "Premove", PremoveProc},
-    {N_("Show Coords"),           "ShowCoords", ShowCoordsProc},
-    {N_("Hide Thinking        Ctrl+Shift+H"),   "HideThinking", HideThinkingProc},
-    {N_("Test Legality          Ctrl+Shift+L"), "TestLegality", TestLegalityProc},
-    {"----", NULL, NothingProc},
+  {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"),       "<Ctrl><Shift>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"),          "<Ctrl><Shift>h",  "HideThinking",        HideThinkingProc},
+  {N_("Test Legality"),          "<Ctrl><Shift>l",  "TestLegality",        TestLegalityProc},
+  {"----",                        NULL,              NULL,                 NothingProc},
 #endif
-    {N_("Save Settings Now"),     "SaveSettingsNow", SaveSettingsProc},
-    {N_("Save Settings on Exit"), "SaveSettingsonExit", SaveOnExitProc},
-    {NULL, NULL, NULL}
+  {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"),     "InfoXBoard", InfoProc},
-    {N_("Man XBoard   F1"), "ManXBoard", ManProc},
-    {"----", NULL, NothingProc},
-    {N_("XBoard Home Page"), "XBoardHomePage", HomePageProc},
-    {N_("On-line User Guide"), "On-lineUserGuide", GuideProc},
-    {N_("Development News"), "DevelopmentNews", NewsPageProc},
-    {N_("e-Mail Bug Report"), "e-MailBugReport", BugReportProc},
-    {"----", NULL, NothingProc},
-    {N_("About XBoard"), "AboutXBoard", AboutProc},
-    {NULL, NULL, NULL}
+  {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[] = {
-    { "", "LoadNextGame", LoadNextGameProc },
-    { "", "LoadPrevGame", LoadPrevGameProc },
-    { "", "ReloadGame", ReloadGameProc },
-    { "", "ReloadPosition", ReloadPositionProc },
+  { "", "<Alt>Next" ,"LoadNextGame", LoadNextGameProc },
+  { "", "<Alt>Prior" ,"LoadPrevGame", LoadPrevGameProc },
+  { "", NULL,"ReloadGame", ReloadGameProc },
+  { "", NULL,"ReloadPosition", ReloadPositionProc },
 #ifndef OPTIONSDIALOG
-    { "", "AlwaysQueen", AlwaysQueenProc },
-    { "", "AnimateDragging", AnimateDraggingProc },
-    { "", "AnimateMoving", AnimateMovingProc },
-    { "", "Autoflag", AutoflagProc },
-    { "", "Autoflip", AutoflipProc },
-    { "", "Blindfold", BlindfoldProc },
-    { "", "FlashMoves", FlashMovesProc },
+  { "", NULL,"AlwaysQueen", AlwaysQueenProc },
+  { "", NULL,"AnimateDragging", AnimateDraggingProc },
+  { "", NULL,"AnimateMoving", AnimateMovingProc },
+  { "", NULL,"Autoflag", AutoflagProc },
+  { "", NULL,"Autoflip", AutoflipProc },
+  { "", NULL,"Blindfold", BlindfoldProc },
+  { "", NULL,"FlashMoves", FlashMovesProc },
 #if HIGHDRAG
-    { "", "HighlightDragging", HighlightDraggingProc },
+  { "", NULL,"HighlightDragging", HighlightDraggingProc },
 #endif
-    { "", "HighlightLastMove", HighlightLastMoveProc },
-//    { "", "IcsAlarm", IcsAlarmProc },
-    { "", "MoveSound", MoveSoundProc },
-    { "", "PeriodicUpdates", PeriodicUpdatesProc },
-    { "", "PopupExitMessage", PopupExitMessageProc },
-    { "", "PopupMoveErrors", PopupMoveErrorsProc },
-//    { "", "Premove", PremoveProc },
-    { "", "ShowCoords", ShowCoordsProc },
-    { "", "ShowThinking", ShowThinkingProc },
-    { "", "HideThinking", HideThinkingProc },
-    { "", "TestLegality", TestLegalityProc },
+  { "", 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
-    { "", "AboutGame", AboutGameEvent },
-    { "", "DebugProc", DebugProc },
-    { "", "Nothing", NothingProc },
-    {NULL, NULL, NULL}
+  { "", NULL,"AboutGame", AboutGameEvent },
+  { "", "<Ctrl>d" ,"DebugProc", DebugProc },
+  { "", NULL,"Nothing", NothingProc },
+  {NULL, NULL, NULL, NULL}
 };
 
 Menu menuBar[] = {
@@ -795,7 +821,8 @@ Menu menuBar[] = {
     {N_("Engine"),  "Engine", engineMenu},
     {N_("Options"), "Options", optionsMenu},
     {N_("Help"),    "Help", helpMenu},
-    {NULL, NULL, NULL}
+    {NULL, NULL, NULL},
+    {   "",         "None", noMenu}
 };
 
 MenuItem *
@@ -804,7 +831,7 @@ MenuNameToItem (char *menuName)
     int i=0;
     char buf[MSG_SIZ], *p;
     MenuItem *menuTab;
-    static MenuItem a = { NULL, NULL, NothingProc };
+    static MenuItem a = { NULL, NULL, NULL, NothingProc };
     extern Option mainOptions[];
     safeStrCpy(buf, menuName, MSG_SIZ);
     p = strchr(buf, '.');
@@ -821,18 +848,22 @@ MenuNameToItem (char *menuName)
     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) AppendMenuItem("----", 0); // at least one valid item to add
+       if(i == 0) engineMenu[firstEngineItem++].string = "----"; // at least one valid item to add
        *p = 0;
-       AppendMenuItem(list, i);
+       if(firstEngineItem + i < 99)
+           engineMenu[firstEngineItem+i].string = strdup(list); // just set name; MenuProc stays NULL
        i++; *p = '\n'; list = p + 1;
     }
 }
@@ -846,7 +877,7 @@ Enables icsEnables[] = {
     { "Mode.AnalyzeFile", False },
     { "Mode.TwoMachines", False },
     { "Mode.MachineMatch", False },
-#ifndef ZIPPY
+#if !ZIPPY
     { "Engine.Hint", False },
     { "Engine.Book", False },
     { "Engine.MoveNow", False },
@@ -1090,8 +1121,8 @@ SetMachineThinkingEnables ()
 void
 GreyRevert (Boolean grey)
 {
-    MarkMenuItem("Edit.Revert", !grey);
-    MarkMenuItem("Edit.Annotate", !grey);
+    EnableNamedMenuItem("Edit.Revert", !grey);
+    EnableNamedMenuItem("Edit.Annotate", !grey);
 }
 
 char *
@@ -1136,6 +1167,93 @@ ModeToWidgetName (GameMode mode)
     }
 }
 
+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 <dirent.h>
+#else
+#include <sys/dir.h>
+#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()
 {
@@ -1209,6 +1327,8 @@ InitMenuMarkers()
     if (saveSettingsOnExit) {
        MarkMenuItem("Options.SaveSettingsonExit", True);
     }
-}
-
+    EnableNamedMenuItem("File.SaveSelected", False);
 
+    // all XBoard builds get here, but not WinBoard...
+    if(*appData.autoInstall) AutoInstall(settingsFileName);
+}