Fix multi-leg promotions
[xboard.git] / menus.c
diff --git a/menus.c b/menus.c
index a8086b7..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,11 +88,6 @@ extern char *getenv();
 
 #include "frontend.h"
 #include "backend.h"
-#include "backendz.h"
-#include "moves.h"
-#include "xgamelist.h"
-#include "xhistory.h"
-#include "xedittags.h"
 #include "menus.h"
 #include "gettext.h"
 
@@ -110,6 +106,26 @@ 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)
+{
+    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 ()
@@ -157,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
@@ -196,6 +214,17 @@ CopyFENToClipboard ()
 }
 
 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;
@@ -203,14 +232,14 @@ CopyGameProc ()
   ret = SaveGameToFile(gameCopyFilename, FALSE);
   if (!ret) return;
 
-  CopySomething();
+  CopySomething(NULL);
 }
 
 void
 CopyGameListProc ()
 {
   if(!SaveGameListAsText(fopen(gameCopyFilename, "w"))) return;
-  CopySomething();
+  CopySomething(NULL);
 }
 
 void
@@ -227,91 +256,14 @@ QuitProc ()
 }
 
 void
-AnalyzeModeProc ()
-{
-    char buf[MSG_SIZ];
-
-    if (!first.analysisSupport) {
-      snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
-      DisplayError(buf, 0);
-      return;
-    }
-    /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
-    if (appData.icsActive) {
-        if (gameMode != IcsObserving) {
-         snprintf(buf, MSG_SIZ, _("You are not observing a game"));
-            DisplayError(buf, 0);
-            /* secure check */
-            if (appData.icsEngineAnalyze) {
-                if (appData.debugMode)
-                    fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
-                ExitAnalyzeMode();
-                ModeHighlight();
-            }
-            return;
-        }
-        /* if enable, use want disable icsEngineAnalyze */
-        if (appData.icsEngineAnalyze) {
-                ExitAnalyzeMode();
-                ModeHighlight();
-                return;
-        }
-        appData.icsEngineAnalyze = TRUE;
-        if (appData.debugMode)
-            fprintf(debugFP, _("ICS engine analyze starting... \n"));
-    }
-#ifndef OPTIONSDIALOG
-    if (!appData.showThinking)
-      ShowThinkingProc();
-#endif
-
-    AnalyzeModeEvent();
-}
-
-void
-AnalyzeFileProc ()
-{
-    if (!first.analysisSupport) {
-      char buf[MSG_SIZ];
-      snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
-      DisplayError(buf, 0);
-      return;
-    }
-//    Reset(FALSE, TRUE);
-#ifndef OPTIONSDIALOG
-    if (!appData.showThinking)
-      ShowThinkingProc();
-#endif
-    AnalyzeFileEvent();
-//    FileNamePopUp(_("File to analyze"), "", ".pgn .game", LoadGamePopUp, "rb");
-    AnalysisPeriodicEvent(1);
-}
-
-void
 MatchProc ()
 {
+    static Enables matchOff[] = { { "Mode.MachineMatch", False }, { NULL, False } };
+    if(matchMode) SetMenuEnables(matchOff);
     MatchEvent(2);
 }
 
 void
-EditCommentProc ()
-{
-    Arg args[5];
-    int j;
-    if (PopDown(1)) { // popdown succesful
-       MarkMenuItem("Edit Comment", False);
-       MarkMenuItem("Show Comments", False);
-    } else // was not up
-       EditCommentEvent();
-}
-
-void
-IcsInputBoxProc ()
-{
-    if (!PopDown(4)) ICSInputBoxPopUp();
-}
-
-void
 AdjuWhiteProc ()
 {
     UserAdjudicationEvent(+1);
@@ -344,6 +296,7 @@ AnnotateProc ()
 void
 FlipViewProc ()
 {
+    if(twoBoards) { partnerUp = 1; DrawPosition(True, NULL); partnerUp = 0; }
     flipView = !flipView;
     DrawPosition(True, NULL);
 }
@@ -351,32 +304,15 @@ FlipViewProc ()
 void
 SaveOnExitProc ()
 {
-    Arg args[16];
-
-    saveSettingsOnExit = !saveSettingsOnExit;
+  saveSettingsOnExit = !saveSettingsOnExit;
 
-    MarkMenuItem("Save Settings on Exit", saveSettingsOnExit);
+  MarkMenuItem("Options.SaveSettingsonExit", saveSettingsOnExit);
 }
 
 void
 SaveSettingsProc ()
 {
-     SaveSettings(settingsFileName);
-}
-
-void
-InfoProc ()
-{
-    char buf[MSG_SIZ];
-    snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
-           INFODIR, INFOFILE);
-    system(buf);
-}
-
-void
-ManProc ()
-{   // called from menu
-    ManInner(NULL, NULL, NULL, NULL);
+  SaveSettings(settingsFileName);
 }
 
 void
@@ -420,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"
@@ -439,6 +375,31 @@ 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
@@ -456,17 +417,15 @@ NothingProc ()
 void
 PonderNextMoveProc ()
 {
-    Arg args[16];
-
-    PonderNextMoveEvent(!appData.ponderNextMove);
-    MARK_MENU_ITEM("Ponder Next Move", appData.ponderNextMove);
+  PonderNextMoveEvent(!appData.ponderNextMove);
+  MARK_MENU_ITEM("Options.PonderNextMove", appData.ponderNextMove);
 }
 
 void
 AlwaysQueenProc ()
 {
     appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
-    MARK_MENU_ITEM("Always Queen", appData.alwaysPromoteToQueen);
+    MARK_MENU_ITEM("Options.AlwaysQueen", appData.alwaysPromoteToQueen);
 }
 
 void
@@ -475,7 +434,7 @@ AnimateDraggingProc ()
     appData.animateDragging = !appData.animateDragging;
 
     if (appData.animateDragging) CreateAnimVars();
-    MARK_MENU_ITEM("Animate Dragging", appData.animateDragging);
+    MARK_MENU_ITEM("Options.AnimateDragging", appData.animateDragging);
 }
 
 void
@@ -483,28 +442,28 @@ AnimateMovingProc ()
 {
     appData.animate = !appData.animate;
     if (appData.animate) CreateAnimVars();
-    MARK_MENU_ITEM("Animate Moving", appData.animate);
+    MARK_MENU_ITEM("Options.AnimateMoving", appData.animate);
 }
 
 void
 AutoflagProc ()
 {
     appData.autoCallFlag = !appData.autoCallFlag;
-    MARK_MENU_ITEM("Auto Flag", appData.autoCallFlag);
+    MARK_MENU_ITEM("Options.AutoFlag", appData.autoCallFlag);
 }
 
 void
 AutoflipProc ()
 {
     appData.autoFlipView = !appData.autoFlipView;
-    MARK_MENU_ITEM("Auto Flip View", appData.autoFlipView);
+    MARK_MENU_ITEM("Options.AutoFlipView", appData.autoFlipView);
 }
 
 void
 BlindfoldProc ()
 {
     appData.blindfold = !appData.blindfold;
-    MARK_MENU_ITEM("Blindfold", appData.blindfold);
+    MARK_MENU_ITEM("Options.Blindfold", appData.blindfold);
     DrawPosition(True, NULL);
 }
 
@@ -512,7 +471,7 @@ void
 TestLegalityProc ()
 {
     appData.testLegality = !appData.testLegality;
-    MARK_MENU_ITEM("Test Legality", appData.testLegality);
+    MARK_MENU_ITEM("Options.TestLegality", appData.testLegality);
 }
 
 
@@ -524,7 +483,7 @@ FlashMovesProc ()
     } else {
        appData.flashCount = -appData.flashCount;
     }
-    MARK_MENU_ITEM("Flash Moves", appData.flashCount > 0);
+    MARK_MENU_ITEM("Options.FlashMoves", appData.flashCount > 0);
 }
 
 #if HIGHDRAG
@@ -532,7 +491,7 @@ void
 HighlightDraggingProc ()
 {
     appData.highlightDragging = !appData.highlightDragging;
-    MARK_MENU_ITEM("Highlight Dragging", appData.highlightDragging);
+    MARK_MENU_ITEM("Options.HighlightDragging", appData.highlightDragging);
 }
 #endif
 
@@ -540,70 +499,70 @@ void
 HighlightLastMoveProc ()
 {
     appData.highlightLastMove = !appData.highlightLastMove;
-    MARK_MENU_ITEM("Highlight Last Move", appData.highlightLastMove);
+    MARK_MENU_ITEM("Options.HighlightLastMove", appData.highlightLastMove);
 }
 
 void
 HighlightArrowProc ()
 {
     appData.highlightMoveWithArrow = !appData.highlightMoveWithArrow;
-    MARK_MENU_ITEM("Arrow", appData.highlightMoveWithArrow);
+    MARK_MENU_ITEM("Options.HighlightWithArrow", appData.highlightMoveWithArrow);
 }
 
 void
 IcsAlarmProc ()
 {
     appData.icsAlarm = !appData.icsAlarm;
-//    MARK_MENU_ITEM("ICS Alarm", appData.icsAlarm);
+//    MARK_MENU_ITEM("Options.ICSAlarm", appData.icsAlarm);
 }
 
 void
 MoveSoundProc ()
 {
     appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
-    MARK_MENU_ITEM("Move Sound", appData.ringBellAfterMoves);
+    MARK_MENU_ITEM("Options.MoveSound", appData.ringBellAfterMoves);
 }
 
 void
 OneClickProc ()
 {
     appData.oneClick = !appData.oneClick;
-    MARK_MENU_ITEM("OneClick", appData.oneClick);
+    MARK_MENU_ITEM("Options.OneClickMoving", appData.oneClick);
 }
 
 void
 PeriodicUpdatesProc ()
 {
     PeriodicUpdatesEvent(!appData.periodicUpdates);
-    MARK_MENU_ITEM("Periodic Updates", appData.periodicUpdates);
+    MARK_MENU_ITEM("Options.PeriodicUpdates", appData.periodicUpdates);
 }
 
 void
 PopupExitMessageProc ()
 {
     appData.popupExitMessage = !appData.popupExitMessage;
-    MARK_MENU_ITEM("Popup Exit Message", appData.popupExitMessage);
+    MARK_MENU_ITEM("Options.PopupExitMessage", appData.popupExitMessage);
 }
 
 void
 PopupMoveErrorsProc ()
 {
     appData.popupMoveErrors = !appData.popupMoveErrors;
-    MARK_MENU_ITEM("Popup Move Errors", appData.popupMoveErrors);
+    MARK_MENU_ITEM("Options.PopupMoveErrors", appData.popupMoveErrors);
 }
 
 void
 PremoveProc ()
 {
     appData.premove = !appData.premove;
-//    MARK_MENU_ITEM("Premove", appData.premove);
+//    MARK_MENU_ITEM("Options.Premove", appData.premove);
 }
 
 void
 ShowCoordsProc ()
 {
     appData.showCoords = !appData.showCoords;
-    MARK_MENU_ITEM("Show Coords", appData.showCoords);
+    MARK_MENU_ITEM("Options.ShowCoords", appData.showCoords);
     DrawPosition(True, NULL);
 }
 
@@ -617,12 +576,25 @@ ShowThinkingProc ()
 void
 HideThinkingProc ()
 {
-    Arg args[16];
+  appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: taken out of ShowThinkingEvent
+  ShowThinkingEvent();
 
-    appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: taken out of ShowThinkingEvent
-    ShowThinkingEvent();
+  MARK_MENU_ITEM("Options.HideThinking", appData.hideThinkingFromHuman);
+}
 
-    MARK_MENU_ITEM("Hide Thinking", appData.hideThinkingFromHuman);
+void
+CreateBookDelayed ()
+{
+  ScheduleDelayedEvent(CreateBookEvent, 50);
+}
+
+void
+SaveSelectedProc ()
+{
+  FileNamePopUp(_("Save game file name?"),
+                 "",
+                 ".pgn",
+                 SaveSelected, "a");
 }
 
 /*
@@ -630,180 +602,214 @@ HideThinkingProc ()
  */
 
 MenuItem fileMenu[] = {
-    {N_("New Game        Ctrl+N"),        "New Game", ResetGameEvent},
-    {N_("New Shuffle Game ..."),          "New Shuffle Game", ShuffleMenuProc},
-    {N_("New Variant ...   Alt+Shift+V"), "New Variant", NewVariantProc},      // [HGM] variant: not functional yet
-    {"----", NULL, NothingProc},
-    {N_("Load Game       Ctrl+O"),        "Load Game", LoadGameProc},
-    {N_("Load Position    Ctrl+Shift+O"), "Load Position", LoadPositionProc},
-//    {N_("Load Next Game"), "Load Next Game", LoadNextGameProc},
-//    {N_("Load Previous Game"), "Load Previous Game", LoadPrevGameProc},
-//    {N_("Reload Same Game"), "Reload Same Game", ReloadGameProc},
-    {N_("Next Position     Shift+PgDn"), "Load Next Position", LoadNextPositionProc},
-    {N_("Prev Position     Shift+PgUp"), "Load Previous Position", LoadPrevPositionProc},
-    {"----", NULL, NothingProc},
-//    {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
-    {N_("Save Game       Ctrl+S"),        "Save Game", SaveGameProc},
-    {N_("Save Position    Ctrl+Shift+S"), "Save Position", SavePositionProc},
-    {"----", NULL, NothingProc},
-    {N_("Mail Move"),            "Mail Move", MailMoveEvent},
-    {N_("Reload CMail Message"), "Reload CMail Message", ReloadCmailMsgProc},
-    {"----", NULL, NothingProc},
-    {N_("Quit                 Ctr+Q"), "Exit", 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"),        "Copy Game", CopyGameProc},
-    {N_("Copy Position Ctrl+Shift+C"), "Copy Position", CopyPositionProc},
-    {N_("Copy Game List"),        "Copy Game List", CopyGameListProc},
-    {"----", NULL, NothingProc},
-    {N_("Paste Game    Ctrl+V"),        "Paste Game", PasteGameProc},
-    {N_("Paste Position Ctrl+Shift+V"), "Paste Position", PastePositionProc},
-    {"----", NULL, NothingProc},
-    {N_("Edit Game      Ctrl+E"),        "Edit Game 2", EditGameEvent},
-    {N_("Edit Position   Ctrl+Shift+E"), "Edit Position 2", EditPositionEvent},
-    {N_("Edit Tags"),                    "Edit Tags", EditTagsProc},
-    {N_("Edit Comment"),                 "Edit Comment", EditCommentProc},
-    {N_("Edit Book"),                    "Edit Book", EditBookEvent},
-    {"----", NULL, NothingProc},
-    {N_("Revert              Home"), "Revert", RevertProc},
-    {N_("Annotate"),                 "Annotate", AnnotateProc},
-    {N_("Truncate Game  End"),       "Truncate Game", TruncateGameEvent},
-    {"----", NULL, NothingProc},
-    {N_("Backward         Alt+Left"),   "Backward", BackwardEvent},
-    {N_("Forward           Alt+Right"), "Forward", ForwardEvent},
-    {N_("Back to Start     Alt+Home"),  "Back to Start", ToStartEvent},
-    {N_("Forward to End Alt+End"),      "Forward to End", 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"),         "Flip View", FlipViewProc},
-    {"----", NULL, NothingProc},
-    {N_("Engine Output      Alt+Shift+O"),   "Show Engine Output", EngineOutputProc},
-    {N_("Move History       Alt+Shift+H"),   "Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
-    {N_("Evaluation Graph  Alt+Shift+E"),    "Show Evaluation Graph", EvalGraphProc},
-    {N_("Game List            Alt+Shift+G"), "Show Game List", ShowGameListProc},
-    {N_("ICS text menu"), "ICStex", IcsTextProc},
-    {"----", NULL, NothingProc},
-    {N_("Tags"),             "Show Tags", EditTagsProc},
-    {N_("Comments"),         "Show Comments", EditCommentProc},
-    {N_("ICS Input Box"),    "ICS Input Box", IcsInputBoxProc},
-    {"----", NULL, NothingProc},
-    {N_("Board..."),          "Board Options", BoardOptionsProc},
-    {N_("Game List Tags..."), "Game List", GameListOptionsPopUp},
-    {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"), "Machine White", MachineWhiteEvent},
-    {N_("Machine Black  Ctrl+B"), "Machine Black", MachineBlackEvent},
-    {N_("Two Machines   Ctrl+T"), "Two Machines", TwoMachinesEvent},
-    {N_("Analysis Mode  Ctrl+A"), "Analysis Mode", AnalyzeModeProc},
-    {N_("Analyze Game   Ctrl+G"), "Analyze File", AnalyzeFileProc },
-    {N_("Edit Game         Ctrl+E"), "Edit Game", EditGameEvent},
-    {N_("Edit Position      Ctrl+Shift+E"), "Edit Position", EditPositionEvent},
-    {N_("Training"),      "Training", TrainingEvent},
-    {N_("ICS Client"),    "ICS Client", IcsClientEvent},
-    {"----", NULL, NothingProc},
-    {N_("Machine Match"),         "Machine Match", 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"), "Call Flag", 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"), "Stop Observing", StopObservingEvent},
-    {N_("Stop Examining  F11"), "Stop Examining", StopExaminingEvent},
-    {N_("Upload to Examine"),   "Upload to Examine", UploadGameEvent},
-    {"----", NULL, NothingProc},
-    {N_("Adjudicate to White"), "Adjudicate to White", AdjuWhiteProc},
-    {N_("Adjudicate to Black"), "Adjudicate to Black", AdjuBlackProc},
-    {N_("Adjudicate Draw"),     "Adjudicate Draw", 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 Engine ..."), "Load Engine", LoadEngineProc},
-    {"----", NULL, NothingProc},
-    {N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc},
-    {N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc},
-    {"----", NULL, NothingProc},
-    {N_("Hint"), "Hint", HintEvent},
-    {N_("Book"), "Book", BookEvent},
-    {"----", NULL, NothingProc},
-    {N_("Move Now     Ctrl+M"),     "Move Now", MoveNowEvent},
-    {N_("Retract Move  Ctrl+X"), "Retract Move", 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"), "Time Control", TimeControlProc},
-    {N_("Common Engine ...  Alt+Shift+U"),     "Common Engine", UciMenuProc},
-    {N_("Adjudications ...      Alt+Shift+J"), "Adjudications", EngineMenuProc},
-    {N_("ICS ..."),    "ICS", IcsOptionsProc},
-    {N_("Match ..."), "Match", MatchOptionsProc},
-    {N_("Load Game ..."),    "Load Game", LoadOptionsProc},
-    {N_("Save Game ..."),    "Save Game", SaveOptionsProc},
-//    {N_(" ..."),    "", OptionsProc},
-    {N_("Game List ..."),    "Game List", GameListOptionsPopUp},
-    {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"),   "Always Queen", AlwaysQueenProc},
-    {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc},
-    {N_("Animate Moving      Ctrl+Shift+A"),   "Animate Moving", AnimateMovingProc},
-    {N_("Auto Flag               Ctrl+Shift+F"), "Auto Flag", AutoflagProc},
-    {N_("Auto Flip View"),   "Auto Flip View", AutoflipProc},
-    {N_("Blindfold"),        "Blindfold", BlindfoldProc},
-    {N_("Flash Moves"),      "Flash Moves", 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"),    "Highlight Dragging", HighlightDraggingProc},
+  {N_("Highlight Dragging"),      NULL,             "HighlightDragging",   HighlightDraggingProc},
 #endif
-    {N_("Highlight Last Move"),   "Highlight Last Move", HighlightLastMoveProc},
-    {N_("Highlight With Arrow"),  "Arrow", HighlightArrowProc},
-    {N_("Move Sound"),            "Move Sound", MoveSoundProc},
-//    {N_("ICS Alarm"),             "ICS Alarm", IcsAlarmProc},
-    {N_("One-Click Moving"),      "OneClick", OneClickProc},
-    {N_("Periodic Updates"),      "Periodic Updates", PeriodicUpdatesProc},
-    {N_("Ponder Next Move  Ctrl+Shift+P"), "Ponder Next Move", PonderNextMoveProc},
-    {N_("Popup Exit Message"),    "Popup Exit Message", PopupExitMessageProc},
-    {N_("Popup Move Errors"),     "Popup Move Errors", PopupMoveErrorsProc},
-//    {N_("Premove"),               "Premove", PremoveProc},
-    {N_("Show Coords"),           "Show Coords", ShowCoordsProc},
-    {N_("Hide Thinking        Ctrl+Shift+H"),   "Hide Thinking", HideThinkingProc},
-    {N_("Test Legality          Ctrl+Shift+L"), "Test Legality", 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"),     "Save Settings Now", SaveSettingsProc},
-    {N_("Save Settings on Exit"), "Save Settings on Exit", 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"),     "Info XBoard", InfoProc},
-    {N_("Man XBoard   F1"), "Man XBoard", ManProc},
-    {"----", NULL, NothingProc},
-    {N_("XBoard Home Page"), "Home Page", HomePageProc},
-    {N_("On-line User Guide"), "User Guide", GuideProc},
-    {N_("Development News"), "News Page", NewsPageProc},
-    {N_("e-Mail Bug Report"), "Bug Report", BugReportProc},
-    {"----", NULL, NothingProc},
-    {N_("About XBoard"), "About XBoard", 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[] = {
+  { "", "<Alt>Next" ,"LoadNextGame", LoadNextGameProc },
+  { "", "<Alt>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 },
+  { "", "<Ctrl>d" ,"DebugProc", DebugProc },
+  { "", NULL,"Nothing", NothingProc },
+  {NULL, NULL, NULL, NULL}
 };
 
 Menu menuBar[] = {
@@ -815,239 +821,227 @@ Menu menuBar[] = {
     {N_("Engine"),  "Engine", engineMenu},
     {N_("Options"), "Options", optionsMenu},
     {N_("Help"),    "Help", helpMenu},
-    {NULL, NULL, NULL}
+    {NULL, NULL, NULL},
+    {   "",         "None", noMenu}
 };
 
-int
-MenuToNumber(char *menuName)
+MenuItem *
+MenuNameToItem (char *menuName)
 {
-    int i;
-    for(i=0; i<nrOfMenuItems; i++)
-       if(!strcmp(menuName, menuItemList[i].name)) return i;
-    return -1;
+    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) AppendMenuItem("----", "----", NULL); // at least one valid item to add
+       if(i == 0) engineMenu[firstEngineItem++].string = "----"; // at least one valid item to add
        *p = 0;
-       AppendMenuItem(list, "recent", (MenuProc *) i);
+       if(firstEngineItem + i < 99)
+           engineMenu[firstEngineItem+i].string = strdup(list); // just set name; MenuProc stays NULL
        i++; *p = '\n'; list = p + 1;
     }
 }
 
-void
-AddPullDownMenu (char *name, Menu *mb)
-{
-    MenuItem *mi;
-
-    CreateMenuButton(name, mb);
-
-    mi = mb->mi;
-    while (mi->string != NULL) {
-       AppendMenuItem(mi->string, mi->ref, mi->proc);
-       menuItemList[nrOfMenuItems].name = mi->ref;
-       menuItemList[nrOfMenuItems].proc = mi->proc;
-       if(strcmp(mi->string, "----")) nrOfMenuItems++;
-       mi++;
-    }
-
-    if(!strcmp(mb->name, "Engine")) AppendEnginesToMenu(appData.recentEngineList);
-}
-
-void
-CreateMainMenus (Menu *mb)
-{
-    char menuName[MSG_SIZ];
-
-    while(menuItemList[nrOfMenuItems].name) nrOfMenuItems++; // skip any predefined items
-
-    while (mb->name != NULL) {
-        safeStrCpy(menuName, "menu", sizeof(menuName)/sizeof(menuName[0]) );
-       strncat(menuName, mb->ref, MSG_SIZ - strlen(menuName) - 1);
-       AddPullDownMenu(menuName, mb++);
-    }
-}
-
 Enables icsEnables[] = {
-    { "Mail Move", False },
-    { "Reload CMail Message", False },
-    { "Machine Black", False },
-    { "Machine White", False },
-    { "Analysis Mode", False },
-    { "Analyze File", False },
-    { "Two Machines", False },
-    { "Machine Match", False },
-#ifndef ZIPPY
-    { "Hint", False },
-    { "Book", False },
-    { "Move Now", False },
+    { "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
-    { "Periodic Updates", False },
-    { "Hide Thinking", False },
-    { "Ponder Next Move", False },
+    { "PeriodicUpdates", False },
+    { "HideThinking", False },
+    { "PonderNextMove", False },
 #endif
 #endif
-    { "Engine #1 Settings", False },
-    { "Engine #2 Settings", False },
-    { "Load Engine", False },
-    { "Annotate", False },
-    { "Match", False },
+    { "Engine.Engine#1Settings", False },
+    { "Engine.Engine#2Settings", False },
+    { "Engine.Load1stEngine", False },
+    { "Engine.Load2ndEngine", False },
+    { "Edit.Annotate", False },
+    { "Options.Match", False },
     { NULL, False }
 };
 
 Enables ncpEnables[] = {
-    { "Mail Move", False },
-    { "Reload CMail Message", False },
-    { "Machine White", False },
-    { "Machine Black", False },
-    { "Analysis Mode", False },
-    { "Analyze File", False },
-    { "Two Machines", False },
-    { "Machine Match", False },
-    { "ICS Client", False },
-    { "ICStex", False },
-    { "ICS Input Box", False },
-    { "Action", False },
-    { "Revert", False },
-    { "Annotate", False },
-    { "Engine #1 Settings", False },
-    { "Engine #2 Settings", False },
-    { "Move Now", False },
-    { "Retract Move", False },
-    { "ICS", False },
+    { "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
-    { "Auto Flag", False },
-    { "Auto Flip View", False },
-//    { "ICS Alarm", False },
-    { "Move Sound", False },
-    { "Hide Thinking", False },
-    { "Periodic Updates", False },
-    { "Ponder Next Move", False },
+    { "Options.AutoFlag", False },
+    { "Options.AutoFlip View", False },
+//    { "Options.ICSAlarm", False },
+    { "Options.MoveSound", False },
+    { "Options.HideThinking", False },
+    { "Options.PeriodicUpdates", False },
+    { "Options.PonderNextMove", False },
 #endif
-    { "Hint", False },
-    { "Book", False },
+    { "Engine.Hint", False },
+    { "Engine.Book", False },
     { NULL, False }
 };
 
 Enables gnuEnables[] = {
-    { "ICS Client", False },
-    { "ICStex", False },
-    { "ICS Input Box", False },
-    { "Accept", False },
-    { "Decline", False },
-    { "Rematch", False },
-    { "Adjourn", False },
-    { "Stop Examining", False },
-    { "Stop Observing", False },
-    { "Upload to Examine", False },
-    { "Revert", False },
-    { "Annotate", False },
-    { "ICS", False },
+    { "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                                  */
 
-    { "Mail Move", False },
-    { "Reload CMail Message", False },
+    { "File.MailMove", False },
+    { "File.ReloadCMailMessage", False },
     // [HGM] The following have been added to make a switch from ncp to GNU mode possible
-    { "Machine White", True },
-    { "Machine Black", True },
-    { "Analysis Mode", True },
-    { "Analyze File", True },
-    { "Two Machines", True },
-    { "Machine Match", True },
-    { "Engine #1 Settings", True },
-    { "Engine #2 Settings", True },
-    { "Hint", True },
-    { "Book", True },
-    { "Move Now", True },
-    { "Retract Move", True },
-    { "Action", True },
+    { "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 },
-    { "Call Flag", False },
-    { "Draw", True },
-    { "Adjourn", False },
-    { "Abort", False },
-    { "Stop Observing", False },
-    { "Stop Examining", False },
-    { "Mail Move", True },
-    { "Reload CMail Message", True },
+    { "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 Comment", False },
-  { "Pause", False },
-  { "Forward", False },
-  { "Backward", False },
-  { "Forward to End", False },
-  { "Back to Start", False },
-  { "Move Now", False },
-  { "Truncate Game", False },
+  { "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 Comment", True },
-  { "Pause", True },
-  { "Forward", True },
-  { "Backward", True },
-  { "Forward to End", True },
-  { "Back to Start", True },
-  { "Move Now", True },
-  { "Truncate Game", True },
+  { "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[] = {
-  { "Load Game", False },
-//  { "Load Next Game", False },
-//  { "Load Previous Game", False },
-//  { "Reload Same Game", False },
-  { "Paste Game", False },
-  { "Load Position", False },
-//  { "Load Next Position", False },
-//  { "Load Previous Position", False },
-//  { "Reload Same Position", False },
-  { "Paste Position", False },
-  { "Machine White", False },
-  { "Machine Black", False },
-  { "Two Machines", False },
-//  { "Machine Match", False },
-  { "Retract Move", False },
+  { "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[] = {
-  { "Load Game", True },
-//  { "Load Next Game", True },
-//  { "Load Previous Game", True },
-//  { "Reload Same Game", True },
-  { "Paste Game", True },
-  { "Load Position", True },
-//  { "Load Next Position", True },
-//  { "Load Previous Position", True },
-//  { "Reload Same Position", True },
-  { "Paste Position", True },
-  { "Machine White", True },
-  { "Machine Black", True },
-  { "Two Machines", True },
-//  { "Machine Match", True },
-  { "Retract Move", True },
+  { "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 }
 };
 
@@ -1058,8 +1052,8 @@ SetICSMode ()
 
 #if ZIPPY
   if (appData.zippyPlay && !appData.noChessProgram) { /* [DM] icsEngineAnalyze */
-     EnableMenuItem("Analysis Mode", True);
-     EnableMenuItem("Engine #1 Settings", True);
+     EnableNamedMenuItem("Mode.AnalysisMode", True);
+     EnableNamedMenuItem("Engine.Engine#1Settings", True);
   }
 #endif
 }
@@ -1117,7 +1111,7 @@ SetMachineThinkingEnables ()
   case MachinePlaysBlack:
   case MachinePlaysWhite:
   case TwoMachinesPlay:
-    EnableMenuItem(ModeToWidgetName(gameMode), True);
+    EnableNamedMenuItem(ModeToWidgetName(gameMode), True);
     break;
   default:
     break;
@@ -1127,8 +1121,8 @@ SetMachineThinkingEnables ()
 void
 GreyRevert (Boolean grey)
 {
-    MarkMenuItem("Revert", !grey);
-    MarkMenuItem("Annotate", !grey);
+    EnableNamedMenuItem("Edit.Revert", !grey);
+    EnableNamedMenuItem("Edit.Annotate", !grey);
 }
 
 char *
@@ -1137,113 +1131,204 @@ ModeToWidgetName (GameMode mode)
     switch (mode) {
       case BeginningOfGame:
        if (appData.icsActive)
-         return "ICS Client";
+         return "Mode.ICSClient";
        else if (appData.noChessProgram ||
                 *appData.cmailGameName != NULLCHAR)
-         return "Edit Game";
+         return "Mode.EditGame";
        else
-         return "Machine Black";
+         return "Mode.MachineBlack";
       case MachinePlaysBlack:
-       return "Machine Black";
+       return "Mode.MachineBlack";
       case MachinePlaysWhite:
-       return "Machine White";
+       return "Mode.MachineWhite";
       case AnalyzeMode:
-       return "Analysis Mode";
+       return "Mode.AnalysisMode";
       case AnalyzeFile:
-       return "Analyze File";
+       return "Mode.AnalyzeFile";
       case TwoMachinesPlay:
-       return "Two Machines";
+       return "Mode.TwoMachines";
       case EditGame:
-       return "Edit Game";
+       return "Mode.EditGame";
       case PlayFromGameFile:
-       return "Load Game";
+       return "File.LoadGame";
       case EditPosition:
-       return "Edit Position";
+       return "Mode.EditPosition";
       case Training:
-       return "Training";
+       return "Mode.Training";
       case IcsPlayingWhite:
       case IcsPlayingBlack:
       case IcsObserving:
       case IcsIdle:
       case IcsExamining:
-       return "ICS Client";
+       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 <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()
 {
 #ifndef OPTIONSDIALOG
     if (appData.alwaysPromoteToQueen) {
-       MarkMenuItem("Always Queen", True);
+       MarkMenuItem("Options.Always Queen", True);
     }
     if (appData.animateDragging) {
-       MarkMenuItem("Animate Dragging", True);
+       MarkMenuItem("Options.Animate Dragging", True);
     }
     if (appData.animate) {
-       MarkMenuItem("Animate Moving", True);
+       MarkMenuItem("Options.Animate Moving", True);
     }
     if (appData.autoCallFlag) {
-       MarkMenuItem("Auto Flag", True);
+       MarkMenuItem("Options.Auto Flag", True);
     }
     if (appData.autoFlipView) {
-       XtSetValues(XtNameToWidget(menuBarWidget,"Auto Flip View", True);
+       XtSetValues(XtNameToWidget(menuBarWidget,"Options.Auto Flip View", True);
     }
     if (appData.blindfold) {
-       MarkMenuItem("Blindfold", True);
+       MarkMenuItem("Options.Blindfold", True);
     }
     if (appData.flashCount > 0) {
-       MarkMenuItem("Flash Moves", True);
+       MarkMenuItem("Options.Flash Moves", True);
     }
 #if HIGHDRAG
     if (appData.highlightDragging) {
-       MarkMenuItem("Highlight Dragging", True);
+       MarkMenuItem("Options.Highlight Dragging", True);
     }
 #endif
     if (appData.highlightLastMove) {
-       MarkMenuItem("Highlight Last Move", True);
+       MarkMenuItem("Options.Highlight Last Move", True);
     }
     if (appData.highlightMoveWithArrow) {
-       MarkMenuItem("Arrow", True);
+       MarkMenuItem("Options.Arrow", True);
     }
 //    if (appData.icsAlarm) {
-//     MarkMenuItem("ICS Alarm", True);
+//     MarkMenuItem("Options.ICS Alarm", True);
 //    }
     if (appData.ringBellAfterMoves) {
-       MarkMenuItem("Move Sound", True);
+       MarkMenuItem("Options.Move Sound", True);
     }
     if (appData.oneClick) {
-       MarkMenuItem("OneClick", True);
+       MarkMenuItem("Options.OneClick", True);
     }
     if (appData.periodicUpdates) {
-       MarkMenuItem("Periodic Updates", True);
+       MarkMenuItem("Options.Periodic Updates", True);
     }
     if (appData.ponderNextMove) {
-       MarkMenuItem("Ponder Next Move", True);
+       MarkMenuItem("Options.Ponder Next Move", True);
     }
     if (appData.popupExitMessage) {
-       MarkMenuItem("Popup Exit Message", True);
+       MarkMenuItem("Options.Popup Exit Message", True);
     }
     if (appData.popupMoveErrors) {
-       MarkMenuItem("Popup Move Errors", True);
+       MarkMenuItem("Options.Popup Move Errors", True);
     }
 //    if (appData.premove) {
-//     MarkMenuItem("Premove", True);
+//     MarkMenuItem("Options.Premove", True);
 //    }
     if (appData.showCoords) {
-       MarkMenuItem("Show Coords", True);
+       MarkMenuItem("Options.Show Coords", True);
     }
     if (appData.hideThinkingFromHuman) {
-       MarkMenuItem("Hide Thinking", True);
+       MarkMenuItem("Options.Hide Thinking", True);
     }
     if (appData.testLegality) {
-       MarkMenuItem("Test Legality", True);
+       MarkMenuItem("Options.Test Legality", True);
     }
 #endif
     if (saveSettingsOnExit) {
-       MarkMenuItem("Save Settings on Exit", True);
+       MarkMenuItem("Options.SaveSettingsonExit", True);
     }
+    EnableNamedMenuItem("File.SaveSelected", False);
+
+    // all XBoard builds get here, but not WinBoard...
+    if(*appData.autoInstall) AutoInstall(settingsFileName);
 }