Make system open command configurable
[xboard.git] / xboard.c
index d505eb5..80db398 100644 (file)
--- a/xboard.c
+++ b/xboard.c
@@ -2,10 +2,10 @@
  * xboard.c -- X front end for XBoard
  *
  * Copyright 1991 by Digital Equipment Corporation, Maynard,
- * Massachusetts. 
+ * Massachusetts.
  *
  * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
  *
  * The following terms apply to Digital Equipment Corporation's copyright
  * interest in XBoard:
@@ -49,6 +49,8 @@
  *------------------------------------------------------------------------
  ** See the file ChangeLog for a revision history.  */
 
+#define HIGHDRAG 1
+
 #include "config.h"
 
 #include <stdio.h>
@@ -58,6 +60,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <pwd.h>
+#include <math.h>
 
 #if !OMIT_SOCKETS
 # if HAVE_SYS_SOCKET_H
@@ -139,6 +142,10 @@ extern char *getenv();
 # endif
 #endif
 
+#if ENABLE_NLS
+#include <locale.h>
+#endif
+
 #include <X11/Intrinsic.h>
 #include <X11/StringDefs.h>
 #include <X11/Shell.h>
@@ -189,6 +196,7 @@ extern char *getenv();
 
 #include "frontend.h"
 #include "backend.h"
+#include "backendz.h"
 #include "moves.h"
 #include "xboard.h"
 #include "childio.h"
@@ -200,7 +208,9 @@ extern char *getenv();
 // must be moved to xengineoutput.h
 
 void EngineOutputProc P((Widget w, XEvent *event,
- String *prms, Cardinal *nprms));
+                        String *prms, Cardinal *nprms));
+void EvalGraphProc P((Widget w, XEvent *event,
+                     String *prms, Cardinal *nprms));
 
 
 #ifdef __EMX__
@@ -220,26 +230,39 @@ void EngineOutputProc P((Widget w, XEvent *event,
 
 typedef struct {
     String string;
+    String ref;
     XtActionProc proc;
 } MenuItem;
 
 typedef struct {
     String name;
+    String ref;
     MenuItem *mi;
+    int textWidth;
+    Widget subMenu;
 } Menu;
 
 int main P((int argc, char **argv));
+FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
+               char *init_path, char *filter, char *mode, int (*show_entry)(), char **name_return));
 RETSIGTYPE CmailSigHandler P((int sig));
 RETSIGTYPE IntSigHandler P((int sig));
 RETSIGTYPE TermSizeSigHandler P((int sig));
-void CreateGCs P((void));
+void CreateGCs P((int redo));
+void CreateAnyPieces P((void));
 void CreateXIMPieces P((void));
 void CreateXPMPieces P((void));
+void CreateXPMBoard P((char *s, int n));
 void CreatePieces P((void));
 void CreatePieceMenus P((void));
-Widget CreateMenuBar P((Menu *mb));
+Widget CreateMenuBar P((Menu *mb, int boardWidth));
 Widget CreateButtonBar P ((MenuItem *mi));
+#if ENABLE_NLS
+char *InsertPxlSize P((char *pattern, int targetPxlSize));
+XFontSet CreateFontSet P((char *base_fnt_lst));
+#else
 char *FindFont P((char *pattern, int targetPxlSize));
+#endif
 void PieceMenuPopup P((Widget w, XEvent *event,
                       String *params, Cardinal *num_params));
 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
@@ -250,10 +273,18 @@ void CreateGrid P((void));
 int EventToSquare P((int x, int limit));
 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
+void DelayedDrag P((void));
+void MoveTypeInProc P((Widget widget, caddr_t unused, XEvent *event));
 void HandleUserMove P((Widget w, XEvent *event,
                     String *prms, Cardinal *nprms));
 void AnimateUserMove P((Widget w, XEvent * event,
                     String * params, Cardinal * nParams));
+void HandlePV P((Widget w, XEvent * event,
+                    String * params, Cardinal * nParams));
+void SelectPV P((Widget w, XEvent * event,
+                    String * params, Cardinal * nParams));
+void StopPV P((Widget w, XEvent * event,
+                    String * params, Cardinal * nParams));
 void WhiteClock P((Widget w, XEvent *event,
                   String *prms, Cardinal *nprms));
 void BlackClock P((Widget w, XEvent *event,
@@ -262,13 +293,13 @@ void DrawPositionProc P((Widget w, XEvent *event,
                     String *prms, Cardinal *nprms));
 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
                     Board board));
+void CommentClick P((Widget w, XEvent * event,
+                  String * params, Cardinal * nParams));
 void CommentPopUp P((char *title, char *label));
 void CommentPopDown P((void));
-void CommentCallback P((Widget w, XtPointer client_data,
-                       XtPointer call_data));
 void ICSInputBoxPopUp P((void));
 void ICSInputBoxPopDown P((void));
-void FileNamePopUp P((char *label, char *def,
+void FileNamePopUp P((char *label, char *def, char *filter,
                      FileProc proc, char *openMode));
 void FileNamePopDown P((void));
 void FileNameCallback P((Widget w, XtPointer client_data,
@@ -283,9 +314,6 @@ void AskQuestionPopDown P((void));
 void PromotionPopDown P((void));
 void PromotionCallback P((Widget w, XtPointer client_data,
                          XtPointer call_data));
-void EditCommentPopDown P((void));
-void EditCommentCallback P((Widget w, XtPointer client_data,
-                           XtPointer call_data));
 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
@@ -308,6 +336,7 @@ void CopyPositionProc P((Widget w, XEvent *event, String *prms,
 void PastePositionProc P((Widget w, XEvent *event, String *prms,
                          Cardinal *nprms));
 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void CopyGameListProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void SavePositionProc P((Widget w, XEvent *event,
@@ -327,6 +356,8 @@ void AnalyzeFileProc P((Widget w, XEvent *event,
                         String *prms, Cardinal *nprms));
 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
                        Cardinal *nprms));
+void MatchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void MatchOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void IcsClientProc P((Widget w, XEvent *event, String *prms,
                      Cardinal *nprms));
 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
@@ -348,16 +379,24 @@ void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void TypeInProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void StopObservingProc P((Widget w, XEvent *event, String *prms,
                          Cardinal *nprms));
 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
                          Cardinal *nprms));
+void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void TempBackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void TempForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+Boolean TempBackwardActive = False;
 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
                         Cardinal *nprms));
 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
@@ -369,28 +408,21 @@ void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
                         Cardinal *nprms));
 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
                         Cardinal *nprms));
-void AutocommProc P((Widget w, XEvent *event, String *prms,
-                    Cardinal *nprms));
 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
-void AutobsProc P((Widget w, XEvent *event, String *prms,
-                       Cardinal *nprms));
-void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
-void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
                       Cardinal *nprms));
 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
-void GetMoveListProc P((Widget w, XEvent *event, String *prms,
-                       Cardinal *nprms));
 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
                              Cardinal *nprms));
 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
                              Cardinal *nprms));
+void HighlightArrowProc P((Widget w, XEvent *event, String *prms,
+                             Cardinal *nprms));
 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
-void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
-void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
-                        Cardinal *nprms));
+//void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void OneClickProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
                         Cardinal *nprms));
 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
@@ -399,8 +431,7 @@ void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
                        Cardinal *nprms));
 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
                             Cardinal *nprms));
-void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
-void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+//void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
                       Cardinal *nprms));
 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
@@ -413,13 +444,16 @@ void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)
 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void GuideProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void HomePageProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void NewsPageProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void BugReportProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
-void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void DisplayMove P((int moveNumber));
 void DisplayTitle P((char *title));
 void ICSInitScript P((void));
@@ -435,17 +469,28 @@ void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms))
 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void OptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void IcsTextProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void LoadEngineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
-void ShufflePopDown P(());
-void EnginePopDown P(());
-void UciPopDown P(());
-void TimeControlPopDown P(());
-void NewVariantPopDown P(());
-void SettingsPopDown P(());
+void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void IcsOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void SoundOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void BoardOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void LoadOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void SaveOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void EditBookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void SelectMove P((Widget w, XEvent * event, String * params, Cardinal * nParams));
+void GameListOptionsPopDown P(());
+void GenericPopDown P(());
 void update_ics_width P(());
 int get_term_width P(());
+int CopyMemoProc P(());
+void DrawArrowHighlight P((int fromX, int fromY, int toX,int toY));
+Boolean IsDrawArrowEnabled P(());
+
 /*
 * XBoard depends on Xt R4 or higher
 */
@@ -467,10 +512,18 @@ Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
   menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
   ICSInputShell, fileNameShell, askQuestionShell;
 Widget historyShell, evalGraphShell, gameListShell;
+int hOffset; // [HGM] dual
+XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
-Font clockFontID, coordFontID, countFontID;
-XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
+#if ENABLE_NLS
+XFontSet fontSet, clockFontSet;
+#else
+Font clockFontID;
+XFontStruct *clockFontStruct;
+#endif
+Font coordFontID, countFontID;
+XFontStruct *coordFontStruct, *countFontStruct;
 XtAppContext appContext;
 char *layoutName;
 char *oldICSInteractionTitle;
@@ -491,7 +544,8 @@ int squareSize, smallLayout = 0, tinyLayout = 0,
   fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
   ICSInputBoxUp = False, askQuestionUp = False,
   filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
-  editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
+  errorUp = False, errorExitStatus = -1, lineGap, defaultLineGap;
+Dimension textHeight;
 Pixel timerForegroundPixel, timerBackgroundPixel;
 Pixel buttonForegroundPixel, buttonBackgroundPixel;
 char *chessDir, *programName, *programVersion,
@@ -513,6 +567,9 @@ WindowPlacement wpEngineOutput;
 WindowPlacement wpGameList;
 WindowPlacement wpTags;
 
+extern Widget shells[];
+extern Boolean shellUp[];
+
 #define SOLID 0
 #define OUTLINE 1
 Pixmap pieceBitmap[2][(int)BlackPawn];
@@ -520,7 +577,8 @@ Pixmap pieceBitmap2[2][(int)BlackPawn+4];       /* [HGM] pieces */
 Pixmap xpmPieceBitmap[4][(int)BlackPawn];      /* LL, LD, DL, DD actually used*/
 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4];   /* LL, LD, DL, DD set to select from */
 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
-int useImages, useImageSqs;
+Pixmap xpmBoardBitmap[2];
+int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
 XImage *ximPieceBitmap[4][(int)BlackPawn+4];   /* LL, LD, DL, DD */
 Pixmap ximMaskPm[(int)BlackPawn];               /* clipmasks, used for XIM pieces */
 Pixmap ximMaskPm2[(int)BlackPawn+4];            /* clipmasks, used for XIM pieces */
@@ -564,185 +622,225 @@ static Pixmap xpmMask[BlackKing + 1];
 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
 
 MenuItem fileMenu[] = {
-    {N_("New Game"), ResetProc},
-    {N_("New Shuffle Game ..."), ShuffleMenuProc},
-    {N_("New Variant ..."), NewVariantProc},      // [HGM] variant: not functional yet
-    {"----", NothingProc},
-    {N_("Load Game"), LoadGameProc},
-    {N_("Load Next Game"), LoadNextGameProc},
-    {N_("Load Previous Game"), LoadPrevGameProc},
-    {N_("Reload Same Game"), ReloadGameProc},
-    {N_("Save Game"), SaveGameProc},
-    {"----", NothingProc},
-    {N_("Copy Game"), CopyGameProc},
-    {N_("Paste Game"), PasteGameProc},
-    {"----", NothingProc},
-    {N_("Load Position"), LoadPositionProc},
-    {N_("Load Next Position"), LoadNextPositionProc},
-    {N_("Load Previous Position"), LoadPrevPositionProc},
-    {N_("Reload Same Position"), ReloadPositionProc},
-    {N_("Save Position"), SavePositionProc},
-    {"----", NothingProc},
-    {N_("Copy Position"), CopyPositionProc},
-    {N_("Paste Position"), PastePositionProc},
-    {"----", NothingProc},
-    {N_("Mail Move"), MailMoveProc},
-    {N_("Reload CMail Message"), ReloadCmailMsgProc},
-    {"----", NothingProc},
-    {N_("Exit"), QuitProc},
-    {NULL, NULL}
+    {N_("New Game        Ctrl+N"),        "New Game", ResetProc},
+    {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", MailMoveProc},
+    {N_("Reload CMail Message"), "Reload CMail Message", ReloadCmailMsgProc},
+    {"----", NULL, NothingProc},
+    {N_("Quit                 Ctr+Q"), "Exit", QuitProc},
+    {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", EditGameProc},
+    {N_("Edit Position   Ctrl+Shift+E"), "Edit Position", EditPositionProc},
+    {N_("Edit Tags"),                    "Edit Tags", EditTagsProc},
+    {N_("Edit Comment"),                 "Edit Comment", EditCommentProc},
+    {N_("Edit Book"),                    "Edit Book", EditBookProc},
+    {"----", NULL, NothingProc},
+    {N_("Revert              Home"), "Revert", RevertProc},
+    {N_("Annotate"),                 "Annotate", AnnotateProc},
+    {N_("Truncate Game  End"),       "Truncate Game", TruncateGameProc},
+    {"----", NULL, NothingProc},
+    {N_("Backward         Alt+Left"),   "Backward", BackwardProc},
+    {N_("Forward           Alt+Right"), "Forward", ForwardProc},
+    {N_("Back to Start     Alt+Home"),  "Back to Start", ToStartProc},
+    {N_("Forward to End Alt+End"),      "Forward to End", ToEndProc},
+    {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}
 };
 
 MenuItem modeMenu[] = {
-    {N_("Machine White"), MachineWhiteProc},
-    {N_("Machine Black"), MachineBlackProc},
-    {N_("Two Machines"), TwoMachinesProc},
-    {N_("Analysis Mode"), AnalyzeModeProc},
-    {N_("Analyze File"), AnalyzeFileProc },
-    {N_("ICS Client"), IcsClientProc},
-    {N_("Edit Game"), EditGameProc},
-    {N_("Edit Position"), EditPositionProc},
-    {N_("Training"), TrainingProc},
-    {"----", NothingProc},
-    {N_("Show Engine Output"), EngineOutputProc},
-    {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
-    {N_("Show Game List"), ShowGameListProc},
-    {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
-    {"----", NothingProc},
-    {N_("Edit Tags"), EditTagsProc},
-    {N_("Edit Comment"), EditCommentProc},
-    {N_("ICS Input Box"), IcsInputBoxProc},
-    {N_("Pause"), PauseProc},
-    {NULL, NULL}
+    {N_("Machine White  Ctrl+W"), "Machine White", MachineWhiteProc},
+    {N_("Machine Black  Ctrl+B"), "Machine Black", MachineBlackProc},
+    {N_("Two Machines   Ctrl+T"), "Two Machines", TwoMachinesProc},
+    {N_("Analysis Mode  Ctrl+A"), "Analysis Mode", AnalyzeModeProc},
+    {N_("Analyze Game   Ctrl+G"), "Analyze File", AnalyzeFileProc },
+    {N_("Edit Game         Ctrl+E"), "Edit Game", EditGameProc},
+    {N_("Edit Position      Ctrl+Shift+E"), "Edit Position", EditPositionProc},
+    {N_("Training"),      "Training", TrainingProc},
+    {N_("ICS Client"),    "ICS Client", IcsClientProc},
+    {"----", NULL, NothingProc},
+    {N_("Machine Match"),         "Machine Match", MatchProc},
+    {N_("Pause               Pause"),         "Pause", PauseProc},
+    {NULL, NULL, NULL}
 };
 
 MenuItem actionMenu[] = {
-    {N_("Accept"), AcceptProc},
-    {N_("Decline"), DeclineProc},
-    {N_("Rematch"), RematchProc},
-    {"----", NothingProc},
-    {N_("Call Flag"), CallFlagProc},
-    {N_("Draw"), DrawProc},
-    {N_("Adjourn"), AdjournProc},
-    {N_("Abort"), AbortProc},
-    {N_("Resign"), ResignProc},
-    {"----", NothingProc},
-    {N_("Stop Observing"), StopObservingProc},
-    {N_("Stop Examining"), StopExaminingProc},
-    {"----", NothingProc},
-    {N_("Adjudicate to White"), AdjuWhiteProc},
-    {N_("Adjudicate to Black"), AdjuBlackProc},
-    {N_("Adjudicate Draw"), AdjuDrawProc},
-    {NULL, NULL}
+    {N_("Accept             F3"), "Accept", AcceptProc},
+    {N_("Decline            F4"), "Decline", DeclineProc},
+    {N_("Rematch           F12"), "Rematch", RematchProc},
+    {"----", NULL, NothingProc},
+    {N_("Call Flag          F5"), "Call Flag", CallFlagProc},
+    {N_("Draw                F6"), "Draw", DrawProc},
+    {N_("Adjourn            F7"),  "Adjourn", AdjournProc},
+    {N_("Abort                F8"),"Abort", AbortProc},
+    {N_("Resign              F9"), "Resign", ResignProc},
+    {"----", NULL, NothingProc},
+    {N_("Stop Observing  F10"), "Stop Observing", StopObservingProc},
+    {N_("Stop Examining  F11"), "Stop Examining", StopExaminingProc},
+    {N_("Upload to Examine"),   "Upload to Examine", UploadProc},
+    {"----", 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}
 };
 
-MenuItem stepMenu[] = {
-    {N_("Backward"), BackwardProc},
-    {N_("Forward"), ForwardProc},
-    {N_("Back to Start"), ToStartProc},
-    {N_("Forward to End"), ToEndProc},
-    {N_("Revert"), RevertProc},
-    {N_("Truncate Game"), TruncateGameProc},
-    {"----", NothingProc},
-    {N_("Move Now"), MoveNowProc},
-    {N_("Retract Move"), RetractMoveProc},
-    {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", HintProc},
+    {N_("Book"), "Book", BookProc},
+    {"----", NULL, NothingProc},
+    {N_("Move Now     Ctrl+M"),     "Move Now", MoveNowProc},
+    {N_("Retract Move  Ctrl+X"), "Retract Move", RetractMoveProc},
+    {NULL, NULL, NULL}
 };
 
 MenuItem optionsMenu[] = {
-    {N_("Flip View"), FlipViewProc},
-    {"----", NothingProc},
-    {N_("Adjudications ..."), EngineMenuProc},
-    {N_("General Settings ..."), UciMenuProc},
-    {N_("Engine #1 Settings ..."), FirstSettingsProc},
-    {N_("Engine #2 Settings ..."), SecondSettingsProc},
-    {N_("Time Control ..."), TimeControlProc},
-    {"----", NothingProc},
-    {N_("Always Queen"), AlwaysQueenProc},
-    {N_("Animate Dragging"), AnimateDraggingProc},
-    {N_("Animate Moving"), AnimateMovingProc},
-    {N_("Auto Comment"), AutocommProc},
-    {N_("Auto Flag"), AutoflagProc},
-    {N_("Auto Flip View"), AutoflipProc},
-    {N_("Auto Observe"), AutobsProc},
-    {N_("Auto Raise Board"), AutoraiseProc},
-    {N_("Auto Save"), AutosaveProc},
-    {N_("Blindfold"), BlindfoldProc},
-    {N_("Flash Moves"), FlashMovesProc},
-    {N_("Get Move List"), GetMoveListProc},
+#define OPTIONSDIALOG
+#ifdef OPTIONSDIALOG
+    {N_("General ..."), "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},
+#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},
 #if HIGHDRAG
-    {N_("Highlight Dragging"), HighlightDraggingProc},
+    {N_("Highlight Dragging"),    "Highlight Dragging", 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},
 #endif
-    {N_("Highlight Last Move"), HighlightLastMoveProc},
-    {N_("Move Sound"), MoveSoundProc},
-    {N_("ICS Alarm"), IcsAlarmProc},
-    {N_("Old Save Style"), OldSaveStyleProc},
-    {N_("Periodic Updates"), PeriodicUpdatesProc},
-    {N_("Ponder Next Move"), PonderNextMoveProc},
-    {N_("Popup Exit Message"), PopupExitMessageProc},
-    {N_("Popup Move Errors"), PopupMoveErrorsProc},
-    {N_("Premove"), PremoveProc},
-    {N_("Quiet Play"), QuietPlayProc},
-    {N_("Show Coords"), ShowCoordsProc},
-    {N_("Hide Thinking"), HideThinkingProc},
-    {N_("Test Legality"), TestLegalityProc},
-    {"----", NothingProc},
-    {N_("Save Settings Now"), SaveSettingsProc},
-    {N_("Save Settings on Exit"), SaveOnExitProc},
-    {NULL, NULL}
+    {N_("Save Settings Now"),     "Save Settings Now", SaveSettingsProc},
+    {N_("Save Settings on Exit"), "Save Settings on Exit", SaveOnExitProc},
+    {NULL, NULL, NULL}
 };
 
 MenuItem helpMenu[] = {
-    {N_("Info XBoard"), InfoProc},
-    {N_("Man XBoard"), ManProc},
-    {"----", NothingProc},
-    {N_("Hint"), HintProc},
-    {N_("Book"), BookProc},
-    {"----", NothingProc},
-    {N_("About XBoard"), AboutProc},
-    {NULL, NULL}
+    {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}
 };
 
 Menu menuBar[] = {
-    {N_("File"), fileMenu},
-    {N_("Mode"), modeMenu},
-    {N_("Action"), actionMenu},
-    {N_("Step"), stepMenu},
-    {N_("Options"), optionsMenu},
-    {N_("Help"), helpMenu},
-    {NULL, NULL}
+    {N_("File"),    "File", fileMenu},
+    {N_("Edit"),    "Edit", editMenu},
+    {N_("View"),    "View", viewMenu},
+    {N_("Mode"),    "Mode", modeMenu},
+    {N_("Action"),  "Action", actionMenu},
+    {N_("Engine"),  "Engine", engineMenu},
+    {N_("Options"), "Options", optionsMenu},
+    {N_("Help"),    "Help", helpMenu},
+    {NULL, NULL, NULL}
 };
 
-#define PAUSE_BUTTON N_("P")
+#define PAUSE_BUTTON "P"
 MenuItem buttonBar[] = {
-    {"<<", ToStartProc},
-    {"<", BackwardProc},
-    {PAUSE_BUTTON, PauseProc},
-    {">", ForwardProc},
-    {">>", ToEndProc},
-    {NULL, NULL}
+    {"<<", "<<", ToStartProc},
+    {"<", "<", BackwardProc},
+    {N_(PAUSE_BUTTON), PAUSE_BUTTON, PauseProc},
+    {">", ">", ForwardProc},
+    {">>", ">>", ToEndProc},
+    {NULL, NULL, NULL}
 };
 
 #define PIECE_MENU_SIZE 18
 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
     { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
-      N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"), 
-      N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"), 
+      N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
+      N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
       N_("Empty square"), N_("Clear board") },
     { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
-      N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"), 
-      N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"), 
+      N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
+      N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
       N_("Empty square"), N_("Clear board") }
 };
-/* must be in same order as PieceMenuStrings! */
+/* must be in same order as pieceMenuStrings! */
 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
     { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
        WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
-       WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0, 
+       WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
        PromotePiece, DemotePiece, EmptySquare, ClearBoard },
     { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
        BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
-       BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0, 
+       BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
        PromotePiece, DemotePiece, EmptySquare, ClearBoard },
 };
 
@@ -750,7 +848,7 @@ ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
 String dropMenuStrings[DROP_MENU_SIZE] = {
     "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
   };
-/* must be in same order as PieceMenuStrings! */
+/* must be in same order as dropMenuStrings! */
 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
     (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
     WhiteRook, WhiteQueen
@@ -829,18 +927,22 @@ XtActionsRec boardActions[] = {
     { "DrawPosition", DrawPositionProc },
     { "HandleUserMove", HandleUserMove },
     { "AnimateUserMove", AnimateUserMove },
+    { "HandlePV", HandlePV },
+    { "SelectPV", SelectPV },
+    { "StopPV", StopPV },
     { "FileNameAction", FileNameAction },
     { "AskQuestionProc", AskQuestionProc },
     { "AskQuestionReplyAction", AskQuestionReplyAction },
     { "PieceMenuPopup", PieceMenuPopup },
     { "WhiteClock", WhiteClock },
     { "BlackClock", BlackClock },
-    { "Iconify", Iconify },
     { "ResetProc", ResetProc },
+    { "NewVariantProc", NewVariantProc },
     { "LoadGameProc", LoadGameProc },
     { "LoadNextGameProc", LoadNextGameProc },
     { "LoadPrevGameProc", LoadPrevGameProc },
     { "LoadSelectedProc", LoadSelectedProc },
+    { "SetFilterProc", SetFilterProc },
     { "ReloadGameProc", ReloadGameProc },
     { "LoadPositionProc", LoadPositionProc },
     { "LoadNextPositionProc", LoadNextPositionProc },
@@ -849,6 +951,7 @@ XtActionsRec boardActions[] = {
     { "CopyPositionProc", CopyPositionProc },
     { "PastePositionProc", PastePositionProc },
     { "CopyGameProc", CopyGameProc },
+    { "CopyGameListProc", CopyGameListProc },
     { "PasteGameProc", PasteGameProc },
     { "SaveGameProc", SaveGameProc },
     { "SavePositionProc", SavePositionProc },
@@ -865,11 +968,12 @@ XtActionsRec boardActions[] = {
     { "EditPositionProc", EditPositionProc },
     { "TrainingProc", EditPositionProc },
     { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
+    { "EvalGraphProc", EvalGraphProc},       // [HGM] Winboard_x avaluation graph window
     { "ShowGameListProc", ShowGameListProc },
     { "ShowMoveListProc", HistoryShowProc},
-    { "EditTagsProc", EditCommentProc },
+    { "EditTagsProc", EditTagsProc },
+    { "EditBookProc", EditBookProc },
     { "EditCommentProc", EditCommentProc },
-    { "IcsAlarmProc", IcsAlarmProc },
     { "IcsInputBoxProc", IcsInputBoxProc },
     { "PauseProc", PauseProc },
     { "AcceptProc", AcceptProc },
@@ -883,46 +987,52 @@ XtActionsRec boardActions[] = {
     { "AdjuWhiteProc", AdjuWhiteProc },
     { "AdjuBlackProc", AdjuBlackProc },
     { "AdjuDrawProc", AdjuDrawProc },
+    { "TypeInProc", TypeInProc },
     { "EnterKeyProc", EnterKeyProc },
+    { "UpKeyProc", UpKeyProc },
+    { "DownKeyProc", DownKeyProc },
     { "StopObservingProc", StopObservingProc },
     { "StopExaminingProc", StopExaminingProc },
+    { "UploadProc", UploadProc },
     { "BackwardProc", BackwardProc },
     { "ForwardProc", ForwardProc },
+    { "TempBackwardProc", TempBackwardProc },
+    { "TempForwardProc", TempForwardProc },
     { "ToStartProc", ToStartProc },
     { "ToEndProc", ToEndProc },
     { "RevertProc", RevertProc },
+    { "AnnotateProc", AnnotateProc },
     { "TruncateGameProc", TruncateGameProc },
     { "MoveNowProc", MoveNowProc },
     { "RetractMoveProc", RetractMoveProc },
+    { "EngineMenuProc", (XtActionProc) EngineMenuProc },
+    { "UciMenuProc", (XtActionProc) UciMenuProc },
+    { "TimeControlProc", (XtActionProc) TimeControlProc },
+    { "FlipViewProc", FlipViewProc },
+    { "PonderNextMoveProc", PonderNextMoveProc },
+#ifndef OPTIONSDIALOG
     { "AlwaysQueenProc", AlwaysQueenProc },
     { "AnimateDraggingProc", AnimateDraggingProc },
     { "AnimateMovingProc", AnimateMovingProc },
     { "AutoflagProc", AutoflagProc },
     { "AutoflipProc", AutoflipProc },
-    { "AutobsProc", AutobsProc },
-    { "AutoraiseProc", AutoraiseProc },
-    { "AutosaveProc", AutosaveProc },
     { "BlindfoldProc", BlindfoldProc },
     { "FlashMovesProc", FlashMovesProc },
-    { "FlipViewProc", FlipViewProc },
-    { "GetMoveListProc", GetMoveListProc },
 #if HIGHDRAG
     { "HighlightDraggingProc", HighlightDraggingProc },
 #endif
     { "HighlightLastMoveProc", HighlightLastMoveProc },
-    { "IcsAlarmProc", IcsAlarmProc },
+//    { "IcsAlarmProc", IcsAlarmProc },
     { "MoveSoundProc", MoveSoundProc },
-    { "OldSaveStyleProc", OldSaveStyleProc },
     { "PeriodicUpdatesProc", PeriodicUpdatesProc },
-    { "PonderNextMoveProc", PonderNextMoveProc },
     { "PopupExitMessageProc", PopupExitMessageProc },
     { "PopupMoveErrorsProc", PopupMoveErrorsProc },
-    { "PremoveProc", PremoveProc },
-    { "QuietPlayProc", QuietPlayProc },
+//    { "PremoveProc", PremoveProc },
     { "ShowCoordsProc", ShowCoordsProc },
     { "ShowThinkingProc", ShowThinkingProc },
     { "HideThinkingProc", HideThinkingProc },
     { "TestLegalityProc", TestLegalityProc },
+#endif
     { "SaveSettingsProc", SaveSettingsProc },
     { "SaveOnExitProc", SaveOnExitProc },
     { "InfoProc", InfoProc },
@@ -933,55 +1043,101 @@ XtActionsRec boardActions[] = {
     { "AboutProc", AboutProc },
     { "DebugProc", DebugProc },
     { "NothingProc", NothingProc },
+    { "CommentClick", (XtActionProc) CommentClick },
     { "CommentPopDown", (XtActionProc) CommentPopDown },
-    { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
     { "TagsPopDown", (XtActionProc) TagsPopDown },
     { "ErrorPopDown", (XtActionProc) ErrorPopDown },
     { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
     { "FileNamePopDown", (XtActionProc) FileNamePopDown },
     { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
     { "GameListPopDown", (XtActionProc) GameListPopDown },
+    { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
     { "PromotionPopDown", (XtActionProc) PromotionPopDown },
-    { "HistoryPopDown", (XtActionProc) HistoryPopDown },
     { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
-    { "ShufflePopDown", (XtActionProc) ShufflePopDown },
-    { "EnginePopDown", (XtActionProc) EnginePopDown },
-    { "UciPopDown", (XtActionProc) UciPopDown },
-    { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
-    { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
-    { "SettingsPopDown", (XtActionProc) SettingsPopDown },
+    { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
+    { "GenericPopDown", (XtActionProc) GenericPopDown },
+    { "CopyMemoProc", (XtActionProc) CopyMemoProc },
+    { "SelectMove", (XtActionProc) SelectMove },
 };
 
 char globalTranslations[] =
-  ":<Key>R: ResignProc() \n \
-   :<Key>r: ResetProc() \n \
-   :<Key>g: LoadGameProc() \n \
-   :<Key>N: LoadNextGameProc() \n \
-   :<Key>P: LoadPrevGameProc() \n \
-   :<Key>Q: QuitProc() \n \
-   :<Key>F: ToEndProc() \n \
-   :<Key>f: ForwardProc() \n \
-   :<Key>B: ToStartProc() \n \
-   :<Key>b: BackwardProc() \n \
-   :<Key>p: PauseProc() \n \
-   :<Key>d: DrawProc() \n \
-   :<Key>t: CallFlagProc() \n \
-   :<Key>i: Iconify() \n \
-   :<Key>c: Iconify() \n \
-   :<Key>v: FlipViewProc() \n \
-   <KeyDown>Control_L: BackwardProc() \n \
-   <KeyUp>Control_L: ForwardProc() \n \
-   <KeyDown>Control_R: BackwardProc() \n \
-   <KeyUp>Control_R: ForwardProc() \n \
-   Shift<Key>1: AskQuestionProc(\"Direct command\",\
-                                \"Send to chess program:\",,1) \n \
-   Shift<Key>2: AskQuestionProc(\"Direct command\",\
-                                \"Send to second chess program:\",,2) \n";
+  ":<Key>F9: ResignProc() \n \
+   :Ctrl<Key>n: ResetProc() \n \
+   :Meta<Key>V: NewVariantProc() \n \
+   :Ctrl<Key>o: LoadGameProc() \n \
+   :Meta<Key>Next: LoadNextGameProc() \n \
+   :Meta<Key>Prior: LoadPrevGameProc() \n \
+   :Ctrl<Key>Down: LoadSelectedProc(3) \n \
+   :Ctrl<Key>Up: LoadSelectedProc(-3) \n \
+   :Ctrl<Key>s: SaveGameProc() \n \
+   :Ctrl<Key>c: CopyGameProc() \n \
+   :Ctrl<Key>v: PasteGameProc() \n \
+   :Ctrl<Key>O: LoadPositionProc() \n \
+   :Shift<Key>Next: LoadNextPositionProc() \n \
+   :Shift<Key>Prior: LoadPrevPositionProc() \n \
+   :Ctrl<Key>S: SavePositionProc() \n \
+   :Ctrl<Key>C: CopyPositionProc() \n \
+   :Ctrl<Key>V: PastePositionProc() \n \
+   :Ctrl<Key>q: QuitProc() \n \
+   :Ctrl<Key>w: MachineWhiteProc() \n \
+   :Ctrl<Key>b: MachineBlackProc() \n \
+   :Ctrl<Key>t: TwoMachinesProc() \n \
+   :Ctrl<Key>a: AnalysisModeProc() \n \
+   :Ctrl<Key>g: AnalyzeFileProc() \n \
+   :Ctrl<Key>e: EditGameProc() \n \
+   :Ctrl<Key>E: EditPositionProc() \n \
+   :Meta<Key>O: EngineOutputProc() \n \
+   :Meta<Key>E: EvalGraphProc() \n \
+   :Meta<Key>G: ShowGameListProc() \n \
+   :Meta<Key>H: ShowMoveListProc() \n \
+   :<Key>Pause: PauseProc() \n \
+   :<Key>F3: AcceptProc() \n \
+   :<Key>F4: DeclineProc() \n \
+   :<Key>F12: RematchProc() \n \
+   :<Key>F5: CallFlagProc() \n \
+   :<Key>F6: DrawProc() \n \
+   :<Key>F7: AdjournProc() \n \
+   :<Key>F8: AbortProc() \n \
+   :<Key>F10: StopObservingProc() \n \
+   :<Key>F11: StopExaminingProc() \n \
+   :Meta Ctrl<Key>F12: DebugProc() \n \
+   :Meta<Key>End: ToEndProc() \n \
+   :Meta<Key>Right: ForwardProc() \n \
+   :Meta<Key>Home: ToStartProc() \n \
+   :Meta<Key>Left: BackwardProc() \n \
+   :<Key>Left: BackwardProc() \n \
+   :<Key>Right: ForwardProc() \n \
+   :<Key>Home: RevertProc() \n \
+   :<Key>End: TruncateGameProc() \n \
+   :Ctrl<Key>m: MoveNowProc() \n \
+   :Ctrl<Key>x: RetractMoveProc() \n \
+   :Meta<Key>J: EngineMenuProc() \n \
+   :Meta<Key>U: UciMenuProc() \n \
+   :Meta<Key>T: TimeControlProc() \n \
+   :Ctrl<Key>P: PonderNextMoveProc() \n "
+#ifndef OPTIONSDIALOG
+    "\
+   :Ctrl<Key>Q: AlwaysQueenProc() \n \
+   :Ctrl<Key>F: AutoflagProc() \n \
+   :Ctrl<Key>A: AnimateMovingProc() \n \
+   :Ctrl<Key>L: TestLegalityProc() \n \
+   :Ctrl<Key>H: HideThinkingProc() \n "
+#endif
+   "\
+   :<Key>F1: ManProc() \n \
+   :<Key>F2: FlipViewProc() \n \
+   :<KeyDown>Return: TempBackwardProc() \n \
+   :<KeyUp>Return: TempForwardProc() \n";
 
 char boardTranslations[] =
-   "<Btn1Down>: HandleUserMove() \n \
-   <Btn1Up>: HandleUserMove() \n \
+   "<Btn1Down>: HandleUserMove(0) \n \
+   Shift<Btn1Up>: HandleUserMove(1) \n \
+   <Btn1Up>: HandleUserMove(0) \n \
    <Btn1Motion>: AnimateUserMove() \n \
+   <Btn3Motion>: HandlePV() \n \
+   <Btn2Motion>: HandlePV() \n \
+   <Btn3Up>: PieceMenuPopup(menuB) \n \
+   <Btn2Up>: PieceMenuPopup(menuB) \n \
    Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
                  PieceMenuPopup(menuB) \n \
    Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
@@ -991,12 +1147,22 @@ char boardTranslations[] =
    Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
                  PieceMenuPopup(menuB) \n";
 
-char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
-char blackTranslations[] = "<BtnDown>: BlackClock()\n";
+char whiteTranslations[] =
+   "Shift<BtnDown>: WhiteClock(1)\n \
+   <BtnDown>: WhiteClock(0)\n";
+char blackTranslations[] =
+   "Shift<BtnDown>: BlackClock(1)\n \
+   <BtnDown>: BlackClock(0)\n";
 
 char ICSInputTranslations[] =
+    "<Key>Up: UpKeyProc() \n "
+    "<Key>Down: DownKeyProc() \n "
     "<Key>Return: EnterKeyProc() \n";
 
+// [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
+//             as the widget is destroyed before the up-click can call extend-end
+char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
+
 String xboardResources[] = {
     "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
     "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
@@ -1014,10 +1180,7 @@ static int xpm_avail[MAXSQSIZE];
 
 /* Extract piece size from filename */
 static int
-xpm_getsize(name, len, ext)
-     char *name;
-     int len;
-     char *ext;
+xpm_getsize (char *name, int len, char *ext)
 {
     char *p, *d;
     char buf[10];
@@ -1041,9 +1204,7 @@ xpm_getsize(name, len, ext)
 
 /* Setup xpm_avail */
 static int
-xpm_getavail(dirname, ext)
-     char *dirname;
-     char *ext;
+xpm_getavail (char *dirname, char *ext)
 {
     DIR *dir;
     struct dirent *ent;
@@ -1075,9 +1236,7 @@ xpm_getavail(dirname, ext)
 }
 
 void
-xpm_print_avail(fp, ext)
-     FILE *fp;
-     char *ext;
+xpm_print_avail (FILE *fp, char *ext)
 {
     int i;
 
@@ -1090,10 +1249,7 @@ xpm_print_avail(fp, ext)
 
 /* Return XPM piecesize closest to size */
 int
-xpm_closest_to(dirname, size, ext)
-     char *dirname;
-     int size;
-     char *ext;
+xpm_closest_to (char *dirname, int size, char *ext)
 {
     int i;
     int sm_diff = MAXSQSIZE;
@@ -1128,16 +1284,13 @@ xpm_closest_to(dirname, size, ext)
    read the directory, so we can't collect a list of
    filenames, etc., so we can't do any size-fitting. */
 int
-xpm_closest_to(dirname, size, ext)
-     char *dirname;
-     int size;
-     char *ext;
+xpm_closest_to (char *dirname, int size, char *ext)
 {
     fprintf(stderr, _("\
 Warning: No DIR structure found on this system --\n\
          Unable to autosize for XPM/XIM pieces.\n\
-   Please report this error to frankm@hiwaay.net.\n\
-   Include system type & operating system in message.\n"));
+   Please report this error to %s.\n\
+   Include system type & operating system in message.\n"), PACKAGE_BUGREPORT););
     return size;
 }
 #endif /* HAVE_DIR_STRUCT */
@@ -1151,9 +1304,7 @@ TextColors textColors[(int)NColorClasses];
 
 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
 static int
-parse_color(str, which)
-     char *str;
-     int which;
+parse_color (char *str, int which)
 {
     char *p, buf[100], *d;
     int i;
@@ -1199,9 +1350,7 @@ parse_color(str, which)
 }
 
 static int
-parse_cpair(cc, str)
-     ColorClass cc;
-     char *str;
+parse_cpair (ColorClass cc, char *str)
 {
     if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
        fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
@@ -1221,7 +1370,7 @@ parse_cpair(cc, str)
 /* Arrange to catch delete-window events */
 Atom wm_delete_window;
 void
-CatchDeleteWindow(Widget w, String procname)
+CatchDeleteWindow (Widget w, String procname)
 {
   char buf[MSG_SIZ];
   XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
@@ -1230,7 +1379,7 @@ CatchDeleteWindow(Widget w, String procname)
 }
 
 void
-BoardToTop()
+BoardToTop ()
 {
   Arg args[16];
   XtSetArg(args[0], XtNiconic, False);
@@ -1245,14 +1394,13 @@ BoardToTop()
 #define JAWS_ARGS
 #define CW_USEDEFAULT (1<<31)
 #define ICS_TEXT_MENU_SIZE 90
+#define DEBUG_FILE "xboard.debug"
 #define SetCurrentDirectory chdir
 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
 #define OPTCHAR "-"
 #define SEPCHAR " "
 
 // these two must some day move to frontend.h, when they are implemented
-Boolean EvalGraphIsUp();
-Boolean MoveHistoryIsUp();
 Boolean GameListIsUp();
 
 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
@@ -1261,28 +1409,46 @@ Boolean GameListIsUp();
 // front-end part of option handling
 
 // [HGM] This platform-dependent table provides the location for storing the color info
+extern char *crWhite, * crBlack;
+
 void *
 colorVariable[] = {
-  &appData.whitePieceColor, 
-  &appData.blackPieceColor, 
+  &appData.whitePieceColor,
+  &appData.blackPieceColor,
   &appData.lightSquareColor,
-  &appData.darkSquareColor, 
+  &appData.darkSquareColor,
   &appData.highlightSquareColor,
   &appData.premoveHighlightColor,
+  &appData.lowTimeWarningColor,
   NULL,
   NULL,
   NULL,
   NULL,
   NULL,
-  NULL,
-  NULL,
-  NULL,
+  &crWhite,
+  &crBlack,
   NULL
 };
 
+// [HGM] font: keep a font for each square size, even non-stndard ones
+#define NUM_SIZES 18
+#define MAX_SIZE 130
+Boolean fontIsSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
+char *fontTable[NUM_FONTS][MAX_SIZE];
+
 void
-ParseFont(char *name, int number)
+ParseFont (char *name, int number)
 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
+  int size;
+  if(sscanf(name, "size%d:", &size)) {
+    // [HGM] font: font is meant for specific boardSize (likely from settings file);
+    //       defer processing it until we know if it matches our board size
+    if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
+       fontTable[number][size] = strdup(strchr(name, ':')+1);
+       fontValid[number][size] = True;
+    }
+    return;
+  }
   switch(number) {
     case 0: // CLOCK_FONT
        appData.clockFont = strdup(name);
@@ -1296,10 +1462,11 @@ ParseFont(char *name, int number)
     default:
       return;
   }
+  fontIsSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
 }
 
 void
-SetFontDefaults()
+SetFontDefaults ()
 { // only 2 fonts currently
   appData.clockFont = CLOCK_FONT_NAME;
   appData.coordFont = COORD_FONT_NAME;
@@ -1307,44 +1474,45 @@ SetFontDefaults()
 }
 
 void
-CreateFonts()
+CreateFonts ()
 { // no-op, until we identify the code for this already in XBoard and move it here
 }
 
 void
-ParseColor(int n, char *name)
+ParseColor (int n, char *name)
 { // in XBoard, just copy the color-name string
   if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
 }
 
 void
-ParseTextAttribs(ColorClass cc, char *s)
-{   
+ParseTextAttribs (ColorClass cc, char *s)
+{
     (&appData.colorShout)[cc] = strdup(s);
 }
 
 void
-ParseBoardSize(void *addr, char *name)
+ParseBoardSize (void *addr, char *name)
 {
     appData.boardSize = strdup(name);
 }
 
 void
-LoadAllSounds()
+LoadAllSounds ()
 { // In XBoard the sound-playing program takes care of obtaining the actual sound
 }
 
 void
-SetCommPortDefaults()
+SetCommPortDefaults ()
 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
 }
 
 // [HGM] args: these three cases taken out to stay in front-end
 void
-SaveFontArg(FILE *f, ArgDescriptor *ad)
+SaveFontArg (FILE *f, ArgDescriptor *ad)
 {
   char *name;
-  switch((int)ad->argLoc) {
+  int i, n = (int)(intptr_t)ad->argLoc;
+  switch(n) {
     case 0: // CLOCK_FONT
        name = appData.clockFont;
       break;
@@ -1357,158 +1525,172 @@ SaveFontArg(FILE *f, ArgDescriptor *ad)
     default:
       return;
   }
-  fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, name);
+  for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
+    if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
+       fontTable[n][squareSize] = strdup(name);
+       fontValid[n][squareSize] = True;
+       break;
+  }
+  for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
+    fprintf(f, OPTCHAR "%s" SEPCHAR "\"size%d:%s\"\n", ad->argName, i, fontTable[n][i]);
 }
 
 void
-ExportSounds()
+ExportSounds ()
 { // nothing to do, as the sounds are at all times represented by their text-string names already
 }
 
 void
-SaveAttribsArg(FILE *f, ArgDescriptor *ad)
+SaveAttribsArg (FILE *f, ArgDescriptor *ad)
 {      // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
-       fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)ad->argLoc]);
+       fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)(intptr_t)ad->argLoc]);
 }
 
 void
-SaveColor(FILE *f, ArgDescriptor *ad)
+SaveColor (FILE *f, ArgDescriptor *ad)
 {      // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
-       if(colorVariable[(int)ad->argLoc])
-       fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)ad->argLoc]);
+       if(colorVariable[(int)(intptr_t)ad->argLoc])
+       fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)ad->argLoc]);
 }
 
 void
-SaveBoardSize(FILE *f, char *name, void *addr)
+SaveBoardSize (FILE *f, char *name, void *addr)
 { // wrapper to shield back-end from BoardSize & sizeInfo
   fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
 }
 
 void
-ParseCommPortSettings(char *s)
+ParseCommPortSettings (char *s)
 { // no such option in XBoard (yet)
 }
 
 extern Widget engineOutputShell;
-extern Widget tagsShell, editTagsShell;
+int frameX, frameY;
+
 void
-GetActualPlacement(Widget wg, WindowPlacement *wp)
+GetActualPlacement (Widget wg, WindowPlacement *wp)
 {
   Arg args[16];
   Dimension w, h;
   Position x, y;
-  int i;
+  XWindowAttributes winAt;
+  Window win, dummy;
+  int i, rx, ry;
 
   if(!wg) return;
-  
-    i = 0;
-    XtSetArg(args[i], XtNx, &x); i++;
-    XtSetArg(args[i], XtNy, &y); i++;
-    XtSetArg(args[i], XtNwidth, &w); i++;
-    XtSetArg(args[i], XtNheight, &h); i++;
-    XtGetValues(wg, args, i);
-    wp->x = x - 4;
-    wp->y = y - 23;
-    wp->height = h;
-    wp->width = w;
+
+    win = XtWindow(wg);
+    XGetWindowAttributes(xDisplay, win, &winAt); // this works, where XtGetValues on XtNx, XtNy does not!
+    XTranslateCoordinates (xDisplay, win, winAt.root, -winAt.border_width, -winAt.border_width, &rx, &ry, &dummy);
+    wp->x = rx - winAt.x;
+    wp->y = ry - winAt.y;
+    wp->height = winAt.height;
+    wp->width = winAt.width;
+    frameX = winAt.x; frameY = winAt.y; // remember to decide if windows touch
 }
 
 void
-GetWindowCoords()
+GetWindowCoords ()
 { // wrapper to shield use of window handles from back-end (make addressible by number?)
   // In XBoard this will have to wait until awareness of window parameters is implemented
   GetActualPlacement(shellWidget, &wpMain);
-  if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
-  if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
+  if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput);
+  if(MoveHistoryIsUp()) GetActualPlacement(shells[7], &wpMoveHistory);
+  if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
   if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
-  if(commentShell) GetActualPlacement(commentShell, &wpComment);
-  else             GetActualPlacement(editShell,    &wpComment);
-  if(tagsShell) GetActualPlacement(tagsShell, &wpTags);
-  else      GetActualPlacement(editTagsShell, &wpTags);
-#if 0
-  GetActualPlacement(hwndConsole, &wpConsole);
-  GetActualPlacement(evalGraphDialog, &wpEvalGraph);
-#endif
+  if(shellUp[1]) GetActualPlacement(shells[1], &wpComment);
+  if(shellUp[2]) GetActualPlacement(shells[2], &wpTags);
 }
 
 void
-PrintCommPortSettings(FILE *f, char *name)
+PrintCommPortSettings (FILE *f, char *name)
 { // This option does not exist in XBoard
 }
 
 int
-MySearchPath(char *installDir, char *name, char *fullname)
+MySearchPath (char *installDir, char *name, char *fullname)
 { // just append installDir and name. Perhaps ExpandPath should be used here?
   name = ExpandPathName(name);
-  if(name && name[0] == '/') strcpy(fullname, name); else {
+  if(name && name[0] == '/')
+    safeStrCpy(fullname, name, MSG_SIZ );
+  else {
     sprintf(fullname, "%s%c%s", installDir, '/', name);
   }
   return 1;
 }
 
 int
-MyGetFullPathName(char *name, char *fullname)
+MyGetFullPathName (char *name, char *fullname)
 { // should use ExpandPath?
   name = ExpandPathName(name);
-  strcpy(fullname, name);
+  safeStrCpy(fullname, name, MSG_SIZ );
   return 1;
 }
 
 void
-EnsureOnScreen(int *x, int *y, int minX, int minY)
+EnsureOnScreen (int *x, int *y, int minX, int minY)
 {
   return;
 }
 
-Boolean
-EvalGraphIsUp()
-{
-  return False;
-}
-
 int
-MainWindowUp()
+MainWindowUp ()
 { // [HGM] args: allows testing if main window is realized from back-end
   return xBoardWindow != 0;
 }
 
 void
-PopUpStartupDialog()
+PopUpStartupDialog ()
 {  // start menu not implemented in XBoard
 }
+
 char *
-ConvertToLine(int argc, char **argv)
+ConvertToLine (int argc, char **argv)
 {
   static char line[128*1024], buf[1024];
   int i;
 
   line[0] = NULLCHAR;
-  for(i=1; i<argc; i++) {
-    if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
-       && argv[i][0] != '{' )
-         sprintf(buf, "{%s} ", argv[i]);
-    else sprintf(buf, "%s ", argv[i]);
-    strcat(line, buf);
-  }
-    line[strlen(line)-1] = NULLCHAR;
+  for(i=1; i<argc; i++)
+    {
+      if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') || argv[i][0] == NULLCHAR)
+         && argv[i][0] != '{' )
+       snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
+      else
+       snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
+      strncat(line, buf, 128*1024 - strlen(line) - 1 );
+    }
+
+  line[strlen(line)-1] = NULLCHAR;
   return line;
 }
 
 //--------------------------------------------------------------------------------------------
 
+extern Boolean twoBoards, partnerUp;
+
 #ifdef IDSIZES
   // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
 #else
 #define BoardSize int
-void InitDrawingSizes(BoardSize boardSize, int flags)
+void
+InitDrawingSizes (BoardSize boardSize, int flags)
 {   // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
     Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
     Arg args[16];
     XtGeometryResult gres;
     int i;
+    static Dimension oldWidth, oldHeight;
+    static VariantClass oldVariant;
+    static int oldDual = -1, oldMono = -1;
 
     if(!formWidget) return;
 
+    if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
+    boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
+    boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
+
+  if(boardWidth != oldWidth || boardHeight != oldHeight || oldDual != twoBoards) { // do resizing stuff only if size actually changed
     /*
      * Enable shell resizing.
      */
@@ -1516,16 +1698,21 @@ void InitDrawingSizes(BoardSize boardSize, int flags)
     shellArgs[1].value = (XtArgVal) &h;
     XtGetValues(shellWidget, shellArgs, 2);
 
-    shellArgs[4].value = 2*w; shellArgs[2].value = 10;
+    shellArgs[4].value = 3*w; shellArgs[2].value = 10;
     shellArgs[5].value = 2*h; shellArgs[3].value = 10;
     XtSetValues(shellWidget, &shellArgs[2], 4);
 
     XtSetArg(args[0], XtNdefaultDistance, &sep);
     XtGetValues(formWidget, args, 1);
 
-    boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
-    boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
+    oldWidth = boardWidth; oldHeight = boardHeight; oldDual = twoBoards;
     CreateGrid();
+    hOffset = boardWidth + 10;
+    for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
+       secondSegments[i] = gridSegments[i];
+       secondSegments[i].x1 += hOffset;
+       secondSegments[i].x2 += hOffset;
+    }
 
     XtSetArg(args[0], XtNwidth, boardWidth);
     XtSetArg(args[1], XtNheight, boardHeight);
@@ -1564,14 +1751,21 @@ void InitDrawingSizes(BoardSize boardSize, int flags)
     /*
      * Inhibit shell resizing.
      */
-    shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
+    shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
     shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
     shellArgs[4].value = shellArgs[2].value = w;
     shellArgs[5].value = shellArgs[3].value = h;
     XtSetValues(shellWidget, &shellArgs[0], 6);
 
+    XSync(xDisplay, False);
+    DelayedDrag();
+  }
+
     // [HGM] pieces: tailor piece bitmaps to needs of specific variant
     // (only for xpm)
+
+  if(gameInfo.variant != oldVariant) { // and only if variant changed
+
     if(useImages) {
       for(i=0; i<4; i++) {
        int p;
@@ -1589,6 +1783,10 @@ void InitDrawingSizes(BoardSize boardSize, int flags)
           xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
        }
 #endif
+       if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
+          xpmPieceBitmap[i][(int)WhiteAngel]    = xpmPieceBitmap2[i][(int)WhiteFalcon];
+          xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
+       }
 #if !HAVE_LIBXPM
        // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
        for(p=0; p<=(int)WhiteKing; p++)
@@ -1605,6 +1803,10 @@ void InitDrawingSizes(BoardSize boardSize, int flags)
            ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
        }
 #endif
+       if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
+           ximMaskPm[(int)WhiteAngel]    = ximMaskPm2[(int)WhiteFalcon];
+           ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
+       }
 #endif
       }
     } else {
@@ -1624,31 +1826,147 @@ void InitDrawingSizes(BoardSize boardSize, int flags)
           pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
        }
 #endif
+       if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
+          pieceBitmap[i][(int)WhiteAngel]    = pieceBitmap2[i][(int)WhiteFalcon];
+          pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
+       }
       }
     }
+    oldMono = -10; // kludge to force recreation of animation masks
+    oldVariant = gameInfo.variant;
+  }
 #if HAVE_LIBXPM
+  if(appData.monoMode != oldMono)
     CreateAnimVars();
 #endif
+  oldMono = appData.monoMode;
 }
 #endif
 
-void EscapeExpand(char *p, char *q)
-{      // [HGM] initstring: routine to shape up string arguments
-       while(*p++ = *q++) if(p[-1] == '\\')
-           switch(*q++) {
-               case 'n': p[-1] = '\n'; break;
-               case 'r': p[-1] = '\r'; break;
-               case 't': p[-1] = '\t'; break;
-               case '\\': p[-1] = '\\'; break;
-               case 0: *p = 0; return;
-               default: p[-1] = q[-1]; break;
-           }
+void
+ParseIcsTextColors ()
+{   // [HGM] tken out of main(), so it can be called from ICS-Options dialog
+    if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
+       parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
+       parse_cpair(ColorChannel1, appData.colorChannel1) < 0  ||
+       parse_cpair(ColorChannel, appData.colorChannel) < 0  ||
+       parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
+       parse_cpair(ColorTell, appData.colorTell) < 0 ||
+       parse_cpair(ColorChallenge, appData.colorChallenge) < 0  ||
+       parse_cpair(ColorRequest, appData.colorRequest) < 0  ||
+       parse_cpair(ColorSeek, appData.colorSeek) < 0  ||
+       parse_cpair(ColorNormal, appData.colorNormal) < 0)
+      {
+         if (appData.colorize) {
+             fprintf(stderr,
+                     _("%s: can't parse color names; disabling colorization\n"),
+                     programName);
+         }
+         appData.colorize = FALSE;
+      }
+}
+
+int
+MakeColors ()
+{   // [HGM] taken out of main(), so it can be called from BoardOptions dialog
+    XrmValue vFrom, vTo;
+    int forceMono = False;
+
+    if (!appData.monoMode) {
+       vFrom.addr = (caddr_t) appData.lightSquareColor;
+       vFrom.size = strlen(appData.lightSquareColor);
+       XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
+       if (vTo.addr == NULL) {
+         appData.monoMode = True;
+         forceMono = True;
+       } else {
+         lightSquareColor = *(Pixel *) vTo.addr;
+       }
+    }
+    if (!appData.monoMode) {
+       vFrom.addr = (caddr_t) appData.darkSquareColor;
+       vFrom.size = strlen(appData.darkSquareColor);
+       XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
+       if (vTo.addr == NULL) {
+         appData.monoMode = True;
+         forceMono = True;
+       } else {
+         darkSquareColor = *(Pixel *) vTo.addr;
+       }
+    }
+    if (!appData.monoMode) {
+       vFrom.addr = (caddr_t) appData.whitePieceColor;
+       vFrom.size = strlen(appData.whitePieceColor);
+       XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
+       if (vTo.addr == NULL) {
+         appData.monoMode = True;
+         forceMono = True;
+       } else {
+         whitePieceColor = *(Pixel *) vTo.addr;
+       }
+    }
+    if (!appData.monoMode) {
+       vFrom.addr = (caddr_t) appData.blackPieceColor;
+       vFrom.size = strlen(appData.blackPieceColor);
+       XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
+       if (vTo.addr == NULL) {
+         appData.monoMode = True;
+         forceMono = True;
+       } else {
+         blackPieceColor = *(Pixel *) vTo.addr;
+       }
+    }
+
+    if (!appData.monoMode) {
+       vFrom.addr = (caddr_t) appData.highlightSquareColor;
+       vFrom.size = strlen(appData.highlightSquareColor);
+       XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
+       if (vTo.addr == NULL) {
+         appData.monoMode = True;
+         forceMono = True;
+       } else {
+         highlightSquareColor = *(Pixel *) vTo.addr;
+       }
+    }
+
+    if (!appData.monoMode) {
+       vFrom.addr = (caddr_t) appData.premoveHighlightColor;
+       vFrom.size = strlen(appData.premoveHighlightColor);
+       XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
+       if (vTo.addr == NULL) {
+         appData.monoMode = True;
+         forceMono = True;
+       } else {
+         premoveHighlightColor = *(Pixel *) vTo.addr;
+       }
+    }
+    return forceMono;
+}
+
+void
+CreateAnyPieces ()
+{   // [HGM] taken out of main
+#if HAVE_LIBXPM
+    if (appData.monoMode && // [HGM] no sense to go on to certain doom
+       (appData.bitmapDirectory == NULL || appData.bitmapDirectory[0] == NULLCHAR))
+           appData.bitmapDirectory = strdup(DEF_BITMAP_DIR);
+
+    if (appData.bitmapDirectory[0] != NULLCHAR) {
+      CreatePieces();
+    } else {
+      CreateXPMPieces();
+      CreateXPMBoard(appData.liteBackTextureFile, 1);
+      CreateXPMBoard(appData.darkBackTextureFile, 0);
+    }
+#else
+    CreateXIMPieces();
+    /* Create regular pieces */
+    if (!useImages) CreatePieces();
+#endif
 }
 
 int
-main(argc, argv)
-     int argc;
-     char **argv;
+main (int argc, char **argv)
 {
     int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
     XSetWindowAttributes window_attributes;
@@ -1659,49 +1977,18 @@ main(argc, argv)
     char *p;
     XrmDatabase xdb;
     int forceMono = False;
-//define INDIRECTION
-#ifdef INDIRECTION
-    // [HGM] before anything else, expand any indirection files amongst options
-    char *argvCopy[1000]; // 1000 seems enough
-    char newArgs[10000];  // holds actual characters
-    int k = 0;
 
     srandom(time(0)); // [HGM] book: make random truly random
 
-    j = 0;
-    for(i=0; i<argc; i++) {
-       if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
-//fprintf(stderr, "arg %s\n", argv[i]);
-       if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
-           char c;
-           FILE *f = fopen(argv[i]+1, "rb");
-           if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
-           argvCopy[j++] = newArgs + k; // get ready for first argument from file
-           while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
-               if(c == '\n') {
-                   if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
-                   newArgs[k++] = 0;  // terminate current arg
-                   if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
-                   argvCopy[j++] = newArgs + k; // get ready for next
-               } else {
-                   if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
-                   newArgs[k++] = c;
-               }
-           }
-           newArgs[k] = 0;
-           j--;
-           fclose(f);
-       }
-    }
-    argvCopy[j] = NULL;
-    argv = argvCopy;
-    argc = j;
-#endif
-
     setbuf(stdout, NULL);
     setbuf(stderr, NULL);
     debugFP = stderr;
 
+    if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
+       printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+       exit(0);
+    }
+
     programName = strrchr(argv[0], '/');
     if (programName == NULL)
       programName = argv[0];
@@ -1734,8 +2021,8 @@ main(argc, argv)
 
     { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
        static char buf[MSG_SIZ];
-       EscapeExpand(buf, appData.initString);
-       appData.initString = strdup(buf);
+       EscapeExpand(buf, appData.firstInitString);
+       appData.firstInitString = strdup(buf);
        EscapeExpand(buf, appData.secondInitString);
        appData.secondInitString = strdup(buf);
        EscapeExpand(buf, appData.firstComputerString);
@@ -1763,6 +2050,12 @@ main(argc, argv)
         setbuf(debugFP, NULL);
     }
 
+#if ENABLE_NLS
+    if (appData.debugMode) {
+      fprintf(debugFP, "locale = %s\n", setlocale(LC_ALL, NULL));
+    }
+#endif
+
     /* [HGM,HR] make sure board size is acceptable */
     if(appData.NrFiles > BOARD_FILES ||
        appData.NrRanks > BOARD_RANKS   )
@@ -1838,7 +2131,14 @@ main(argc, argv)
        fontPxlSize = szd->fontPxlSize;
        smallLayout = szd->smallLayout;
        tinyLayout = szd->tinyLayout;
+       // [HGM] font: use defaults from settings file if available and not overruled
     }
+    if(!fontIsSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
+       appData.clockFont = fontTable[CLOCK_FONT][squareSize];
+    if(!fontIsSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
+       appData.font = fontTable[MESSAGE_FONT][squareSize];
+    if(!fontIsSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
+       appData.coordFont = fontTable[COORD_FONT][squareSize];
 
     /* Now, using squareSize as a hint, find a good XPM/XIM set size */
     if (strlen(appData.pixmapDirectory) > 0) {
@@ -1858,6 +2158,8 @@ XBoard square size (hint): %d\n\
            fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
        }
     }
+    defaultLineGap = lineGap;
+    if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
 
     /* [HR] height treated separately (hacked) */
     boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
@@ -1881,19 +2183,45 @@ XBoard square size (hint): %d\n\
     /*
      * Determine what fonts to use.
      */
+#if ENABLE_NLS
+    appData.font = InsertPxlSize(appData.font, fontPxlSize);
+    appData.clockFont = InsertPxlSize(appData.clockFont, clockFontPxlSize);
+    appData.coordFont = InsertPxlSize(appData.coordFont, coordFontPxlSize);
+    fontSet = CreateFontSet(appData.font);
+    clockFontSet = CreateFontSet(appData.clockFont);
+    {
+      /* For the coordFont, use the 0th font of the fontset. */
+      XFontSet coordFontSet = CreateFontSet(appData.coordFont);
+      XFontStruct **font_struct_list;
+      XFontSetExtents *fontSize;
+      char **font_name_list;
+      XFontsOfFontSet(coordFontSet, &font_struct_list, &font_name_list);
+      coordFontID = XLoadFont(xDisplay, font_name_list[0]);
+      coordFontStruct = XQueryFont(xDisplay, coordFontID);
+      fontSize = XExtentsOfFontSet(fontSet); // [HGM] figure out how much vertical space font takes
+      textHeight = fontSize->max_logical_extent.height + 5; // add borderWidth
+    }
+#else
+    appData.font = FindFont(appData.font, fontPxlSize);
     appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
+    appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
     clockFontID = XLoadFont(xDisplay, appData.clockFont);
     clockFontStruct = XQueryFont(xDisplay, clockFontID);
-    appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
     coordFontID = XLoadFont(xDisplay, appData.coordFont);
     coordFontStruct = XQueryFont(xDisplay, coordFontID);
-    appData.font = FindFont(appData.font, fontPxlSize);
-    countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
-    countFontStruct = XQueryFont(xDisplay, countFontID);
-//    appData.font = FindFont(appData.font, fontPxlSize);
+#endif
+    countFontID = coordFontID;  // [HGM] holdings
+    countFontStruct = coordFontStruct;
 
     xdb = XtDatabase(xDisplay);
+#if ENABLE_NLS
+    XrmPutLineResource(&xdb, "*international: True");
+    vTo.size = sizeof(XFontSet);
+    vTo.addr = (XtPointer) &fontSet;
+    XrmPutResource(&xdb, "*fontSet", XtRFontSet, &vTo);
+#else
     XrmPutStringResource(&xdb, "*font", appData.font);
+#endif
 
     /*
      * Detect if there are not enough colors available and adapt.
@@ -1902,89 +2230,19 @@ XBoard square size (hint): %d\n\
       appData.monoMode = True;
     }
 
-    if (!appData.monoMode) {
-       vFrom.addr = (caddr_t) appData.lightSquareColor;
-       vFrom.size = strlen(appData.lightSquareColor);
-       XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
-       if (vTo.addr == NULL) {
-         appData.monoMode = True;
-         forceMono = True;
-       } else {
-         lightSquareColor = *(Pixel *) vTo.addr;
-       }
-    }
-    if (!appData.monoMode) {
-       vFrom.addr = (caddr_t) appData.darkSquareColor;
-       vFrom.size = strlen(appData.darkSquareColor);
-       XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
-       if (vTo.addr == NULL) {
-         appData.monoMode = True;
-         forceMono = True;
-       } else {
-         darkSquareColor = *(Pixel *) vTo.addr;
-       }
-    }
-    if (!appData.monoMode) {
-       vFrom.addr = (caddr_t) appData.whitePieceColor;
-       vFrom.size = strlen(appData.whitePieceColor);
-       XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
-       if (vTo.addr == NULL) {
-         appData.monoMode = True;
-         forceMono = True;
-       } else {
-         whitePieceColor = *(Pixel *) vTo.addr;
-       }
-    }
-    if (!appData.monoMode) {
-       vFrom.addr = (caddr_t) appData.blackPieceColor;
-       vFrom.size = strlen(appData.blackPieceColor);
-       XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
-       if (vTo.addr == NULL) {
-         appData.monoMode = True;
-         forceMono = True;
-       } else {
-         blackPieceColor = *(Pixel *) vTo.addr;
-       }
-    }
-
-    if (!appData.monoMode) {
-       vFrom.addr = (caddr_t) appData.highlightSquareColor;
-       vFrom.size = strlen(appData.highlightSquareColor);
-       XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
-       if (vTo.addr == NULL) {
-         appData.monoMode = True;
-         forceMono = True;
-       } else {
-         highlightSquareColor = *(Pixel *) vTo.addr;
-       }
-    }
-
-    if (!appData.monoMode) {
-       vFrom.addr = (caddr_t) appData.premoveHighlightColor;
-       vFrom.size = strlen(appData.premoveHighlightColor);
-       XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
-       if (vTo.addr == NULL) {
-         appData.monoMode = True;
-         forceMono = True;
-       } else {
-         premoveHighlightColor = *(Pixel *) vTo.addr;
-       }
-    }
+    forceMono = MakeColors();
 
     if (forceMono) {
       fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
              programName);
-      
-      if (appData.bitmapDirectory == NULL ||
-             appData.bitmapDirectory[0] == NULLCHAR)
-           appData.bitmapDirectory = DEF_BITMAP_DIR;
+       appData.monoMode = True;
     }
 
     if (appData.lowTimeWarning && !appData.monoMode) {
       vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
       vFrom.size = strlen(appData.lowTimeWarningColor);
       XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
-      if (vTo.addr == NULL) 
+      if (vTo.addr == NULL)
                appData.monoMode = True;
       else
                lowTimeWarningColor = *(Pixel *) vTo.addr;
@@ -1996,24 +2254,7 @@ XBoard square size (hint): %d\n\
                (unsigned long) XBlackPixel(xDisplay, xScreen));
     }
 
-    if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
-       parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
-       parse_cpair(ColorChannel1, appData.colorChannel1) < 0  ||
-       parse_cpair(ColorChannel, appData.colorChannel) < 0  ||
-       parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
-       parse_cpair(ColorTell, appData.colorTell) < 0 ||
-       parse_cpair(ColorChallenge, appData.colorChallenge) < 0  ||
-       parse_cpair(ColorRequest, appData.colorRequest) < 0  ||
-       parse_cpair(ColorSeek, appData.colorSeek) < 0  ||
-       parse_cpair(ColorNormal, appData.colorNormal) < 0)
-      {
-         if (appData.colorize) {
-             fprintf(stderr,
-                     _("%s: can't parse color names; disabling colorization\n"),
-                     programName);
-         }
-         appData.colorize = FALSE;
-      }
+    ParseIcsTextColors();
     textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
     textColors[ColorNone].attr = 0;
 
@@ -2041,7 +2282,7 @@ XBoard square size (hint): %d\n\
     XtGetValues(formWidget, args, 1);
 
     j = 0;
-    widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
+    widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar, boardWidth);
     XtSetArg(args[0], XtNtop,    XtChainTop);
     XtSetArg(args[1], XtNbottom, XtChainTop);
     XtSetArg(args[2], XtNright,  XtChainLeft);
@@ -2050,7 +2291,11 @@ XBoard square size (hint): %d\n\
     widgetList[j++] = whiteTimerWidget =
       XtCreateWidget("whiteTime", labelWidgetClass,
                     formWidget, timerArgs, XtNumber(timerArgs));
+#if ENABLE_NLS
+    XtSetArg(args[0], XtNfontSet, clockFontSet);
+#else
     XtSetArg(args[0], XtNfont, clockFontStruct);
+#endif
     XtSetArg(args[1], XtNtop,    XtChainTop);
     XtSetArg(args[2], XtNbottom, XtChainTop);
     XtSetValues(whiteTimerWidget, args, 3);
@@ -2058,7 +2303,11 @@ XBoard square size (hint): %d\n\
     widgetList[j++] = blackTimerWidget =
       XtCreateWidget("blackTime", labelWidgetClass,
                     formWidget, timerArgs, XtNumber(timerArgs));
+#if ENABLE_NLS
+    XtSetArg(args[0], XtNfontSet, clockFontSet);
+#else
     XtSetArg(args[0], XtNfont, clockFontStruct);
+#endif
     XtSetArg(args[1], XtNtop,    XtChainTop);
     XtSetArg(args[2], XtNbottom, XtChainTop);
     XtSetValues(blackTimerWidget, args, 3);
@@ -2233,6 +2482,7 @@ XBoard square size (hint): %d\n\
              programName, gres, w, h, wr, hr);
     }
     /* !! end hack */
+    if(!textHeight) textHeight = hr; // [HGM] if !NLS textHeight is still undefined, and we grab it from here
     XtSetArg(args[0], XtNleft,  XtChainLeft);  // [HGM] glue ends for good run-time sizing
     XtSetArg(args[1], XtNright, XtChainRight);
     XtSetValues(messageWidget, args, 2);
@@ -2271,6 +2521,7 @@ XBoard square size (hint): %d\n\
     ReadBitmap(&xMarkPixmap, "checkmark.bm",
               checkmark_bits, checkmark_width, checkmark_height);
     XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+#ifndef OPTIONSDIALOG
     if (appData.alwaysPromoteToQueen) {
        XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
                    args, 1);
@@ -2284,10 +2535,6 @@ XBoard square size (hint): %d\n\
        XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
                    args, 1);
     }
-    if (appData.autoComment) {
-       XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
-                   args, 1);
-    }
     if (appData.autoCallFlag) {
        XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
                    args, 1);
@@ -2296,26 +2543,6 @@ XBoard square size (hint): %d\n\
        XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
                    args, 1);
     }
-    if (appData.autoObserve) {
-       XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
-                   args, 1);
-    }
-    if (appData.autoRaiseBoard) {
-       XtSetValues(XtNameToWidget(menuBarWidget,
-                                  "menuOptions.Auto Raise Board"), args, 1);
-    }
-    if (appData.autoSaveGames) {
-       XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
-                   args, 1);
-    }
-    if (appData.saveGameFile[0] != NULLCHAR) {
-       /* Can't turn this off from menu */
-       XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
-                   args, 1);
-       XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
-                      False);
-
-    }
     if (appData.blindfold) {
        XtSetValues(XtNameToWidget(menuBarWidget,
                                   "menuOptions.Blindfold"), args, 1);
@@ -2325,10 +2552,6 @@ XBoard square size (hint): %d\n\
                                   "menuOptions.Flash Moves"),
                    args, 1);
     }
-    if (appData.getMoveList) {
-       XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
-                   args, 1);
-    }
 #if HIGHDRAG
     if (appData.highlightDragging) {
        XtSetValues(XtNameToWidget(menuBarWidget,
@@ -2341,17 +2564,22 @@ XBoard square size (hint): %d\n\
                                   "menuOptions.Highlight Last Move"),
                    args, 1);
     }
-    if (appData.icsAlarm) {
-       XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
+    if (appData.highlightMoveWithArrow) {
+       XtSetValues(XtNameToWidget(menuBarWidget,
+                                  "menuOptions.Arrow"),
                    args, 1);
     }
+//    if (appData.icsAlarm) {
+//     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
+//                 args, 1);
+//    }
     if (appData.ringBellAfterMoves) {
        XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
                    args, 1);
     }
-    if (appData.oldSaveStyle) {
+    if (appData.oneClick) {
        XtSetValues(XtNameToWidget(menuBarWidget,
-                                  "menuOptions.Old Save Style"), args, 1);
+                                  "menuOptions.OneClick"), args, 1);
     }
     if (appData.periodicUpdates) {
        XtSetValues(XtNameToWidget(menuBarWidget,
@@ -2369,14 +2597,10 @@ XBoard square size (hint): %d\n\
        XtSetValues(XtNameToWidget(menuBarWidget,
                                   "menuOptions.Popup Move Errors"), args, 1);
     }
-    if (appData.premove) {
-       XtSetValues(XtNameToWidget(menuBarWidget,
-                                  "menuOptions.Premove"), args, 1);
-    }
-    if (appData.quietPlay) {
-       XtSetValues(XtNameToWidget(menuBarWidget,
-                                  "menuOptions.Quiet Play"), args, 1);
-    }
+//    if (appData.premove) {
+//     XtSetValues(XtNameToWidget(menuBarWidget,
+//                                "menuOptions.Premove"), args, 1);
+//    }
     if (appData.showCoords) {
        XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
                    args, 1);
@@ -2389,6 +2613,7 @@ XBoard square size (hint): %d\n\
        XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
                    args, 1);
     }
+#endif
     if (saveSettingsOnExit) {
        XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
                    args, 1);
@@ -2427,19 +2652,9 @@ XBoard square size (hint): %d\n\
 
     CatchDeleteWindow(shellWidget, "QuitProc");
 
-    CreateGCs();
+    CreateGCs(False);
     CreateGrid();
-#if HAVE_LIBXPM
-    if (appData.bitmapDirectory[0] != NULLCHAR) {
-      CreatePieces();
-    } else {
-      CreateXPMPieces();
-    }
-#else
-    CreateXIMPieces();
-    /* Create regular pieces */
-    if (!useImages) CreatePieces();
-#endif
+    CreateAnyPieces();
 
     CreatePieceMenus();
 
@@ -2457,9 +2672,27 @@ XBoard square size (hint): %d\n\
 
     /* Why is the following needed on some versions of X instead
      * of a translation? */
-    XtAddEventHandler(boardWidget, ExposureMask, False,
+    XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
                      (XtEventHandler) EventProc, NULL);
     /* end why */
+    XtAddEventHandler(formWidget, KeyPressMask, False,
+                     (XtEventHandler) MoveTypeInProc, NULL);
+    XtAddEventHandler(shellWidget, StructureNotifyMask, False,
+                     (XtEventHandler) EventProc, NULL);
+
+    /* [AS] Restore layout */
+    if( wpMoveHistory.visible ) {
+      HistoryPopUp();
+    }
+
+    if( wpEvalGraph.visible )
+      {
+       EvalGraphPopUp();
+      };
+
+    if( wpEngineOutput.visible ) {
+      EngineOutputPopUp();
+    }
 
     InitBackEnd2();
 
@@ -2482,14 +2715,18 @@ XBoard square size (hint): %d\n\
     }
     gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
     InitPosition(TRUE);
+//    XtSetKeyboardFocus(shellWidget, formWidget);
+    XSetInputFocus(xDisplay, XtWindow(formWidget), RevertToPointerRoot, CurrentTime);
 
     XtAppMainLoop(appContext);
     if (appData.debugMode) fclose(debugFP); // [DM] debug
     return 0;
 }
 
+static Boolean noEcho;
+
 void
-ShutDownFrontEnd()
+ShutDownFrontEnd ()
 {
     if (appData.icsActive && oldICSInteractionTitle != NULL) {
         DisplayIcsInteractionTitle(oldICSInteractionTitle);
@@ -2497,23 +2734,23 @@ ShutDownFrontEnd()
     if (saveSettingsOnExit) SaveSettings(settingsFileName);
     unlink(gameCopyFilename);
     unlink(gamePasteFilename);
+    if(noEcho) EchoOn();
 }
 
-RETSIGTYPE TermSizeSigHandler(int sig)
+RETSIGTYPE
+TermSizeSigHandler (int sig)
 {
     update_ics_width();
 }
 
 RETSIGTYPE
-IntSigHandler(sig)
-     int sig;
+IntSigHandler (int sig)
 {
     ExitEvent(sig);
 }
 
 RETSIGTYPE
-CmailSigHandler(sig)
-     int sig;
+CmailSigHandler (int sig)
 {
     int dummy = 0;
     int error;
@@ -2527,12 +2764,7 @@ CmailSigHandler(sig)
 }
 
 void
-CmailSigHandlerCallBack(isr, closure, message, count, error)
-     InputSourceRef isr;
-     VOIDSTAR closure;
-     char *message;
-     int count;
-     int error;
+CmailSigHandlerCallBack (InputSourceRef isr, VOIDSTAR closure, char *message, int count, int error)
 {
     BoardToTop();
     ReloadCmailMsgEvent(TRUE); /* Reload cmail msg  */
@@ -2541,31 +2773,41 @@ CmailSigHandlerCallBack(isr, closure, message, count, error)
 
 
 void
-ICSInitScript()
+ICSInitScript ()
 {
-    FILE *f;
-    char buf[MSG_SIZ];
-    char *p;
+  /* try to open the icsLogon script, either in the location given
+   * or in the users HOME directory
+   */
+
+  FILE *f;
+  char buf[MSG_SIZ];
+  char *homedir;
 
-    f = fopen(appData.icsLogon, "r");
-    if (f == NULL) {
-       p = getenv("HOME");
-       if (p != NULL) {
-           strcpy(buf, p);
-           strcat(buf, "/");
-           strcat(buf, appData.icsLogon);
-           f = fopen(buf, "r");
+  f = fopen(appData.icsLogon, "r");
+  if (f == NULL)
+    {
+      homedir = getenv("HOME");
+      if (homedir != NULL)
+       {
+         safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
+         strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
+         strncat(buf, appData.icsLogon,  MSG_SIZ - strlen(buf) - 1);
+         f = fopen(buf, "r");
        }
     }
-    if (f != NULL)
-      ProcessICSInitScript(f);
+
+  if (f != NULL)
+    ProcessICSInitScript(f);
+  else
+    printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
+
+  return;
 }
 
 void
-ResetFrontEnd()
+ResetFrontEnd ()
 {
     CommentPopDown();
-    EditCommentPopDown();
     TagsPopDown();
     return;
 }
@@ -2576,22 +2818,26 @@ typedef struct {
 } Enables;
 
 void
-GreyRevert(grey)
-     Boolean grey;
+GreyRevert (Boolean grey)
 {
     Widget w;
     if (!menuBarWidget) return;
-    w = XtNameToWidget(menuBarWidget, "menuStep.Revert");
+    w = XtNameToWidget(menuBarWidget, "menuEdit.Revert");
+    if (w == NULL) {
+      DisplayError("menuEdit.Revert", 0);
+    } else {
+      XtSetSensitive(w, !grey);
+    }
+    w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate");
     if (w == NULL) {
-      DisplayError("menuStep.Revert", 0);
+      DisplayError("menuEdit.Annotate", 0);
     } else {
       XtSetSensitive(w, !grey);
     }
 }
 
 void
-SetMenuEnables(enab)
-     Enables *enab;
+SetMenuEnables (Enables *enab)
 {
   Widget w;
   if (!menuBarWidget) return;
@@ -2614,14 +2860,22 @@ Enables icsEnables[] = {
     { "menuMode.Analysis Mode", False },
     { "menuMode.Analyze File", False },
     { "menuMode.Two Machines", False },
+    { "menuMode.Machine Match", False },
 #ifndef ZIPPY
-    { "menuHelp.Hint", False },
-    { "menuHelp.Book", False },
-    { "menuStep.Move Now", False },
+    { "menuEngine.Hint", False },
+    { "menuEngine.Book", False },
+    { "menuEngine.Move Now", False },
+#ifndef OPTIONSDIALOG
     { "menuOptions.Periodic Updates", False },
     { "menuOptions.Hide Thinking", False },
     { "menuOptions.Ponder Next Move", False },
 #endif
+#endif
+    { "menuEngine.Engine #1 Settings", False },
+    { "menuEngine.Engine #2 Settings", False },
+    { "menuEngine.Load Engine", False },
+    { "menuEdit.Annotate", False },
+    { "menuOptions.Match", False },
     { NULL, False }
 };
 
@@ -2633,45 +2887,46 @@ Enables ncpEnables[] = {
     { "menuMode.Analysis Mode", False },
     { "menuMode.Analyze File", False },
     { "menuMode.Two Machines", False },
+    { "menuMode.Machine Match", False },
     { "menuMode.ICS Client", False },
-    { "menuMode.ICS Input Box", False },
+    { "menuView.ICStex", False },
+    { "menuView.ICS Input Box", False },
     { "Action", False },
-    { "menuStep.Revert", False },
-    { "menuStep.Move Now", False },
-    { "menuStep.Retract Move", False },
-    { "menuOptions.Auto Comment", False },
+    { "menuEdit.Revert", False },
+    { "menuEdit.Annotate", False },
+    { "menuEngine.Engine #1 Settings", False },
+    { "menuEngine.Engine #2 Settings", False },
+    { "menuEngine.Move Now", False },
+    { "menuEngine.Retract Move", False },
+    { "menuOptions.ICS", False },
+#ifndef OPTIONSDIALOG
     { "menuOptions.Auto Flag", False },
     { "menuOptions.Auto Flip View", False },
-    { "menuOptions.Auto Observe", False },
-    { "menuOptions.Auto Raise Board", False },
-    { "menuOptions.Get Move List", False },
-    { "menuOptions.ICS Alarm", False },
+//    { "menuOptions.ICS Alarm", False },
     { "menuOptions.Move Sound", False },
-    { "menuOptions.Quiet Play", False },
     { "menuOptions.Hide Thinking", False },
     { "menuOptions.Periodic Updates", False },
     { "menuOptions.Ponder Next Move", False },
-    { "menuHelp.Hint", False },
-    { "menuHelp.Book", False },
+#endif
+    { "menuEngine.Hint", False },
+    { "menuEngine.Book", False },
     { NULL, False }
 };
 
 Enables gnuEnables[] = {
     { "menuMode.ICS Client", False },
-    { "menuMode.ICS Input Box", False },
+    { "menuView.ICStex", False },
+    { "menuView.ICS Input Box", False },
     { "menuAction.Accept", False },
     { "menuAction.Decline", False },
     { "menuAction.Rematch", False },
     { "menuAction.Adjourn", False },
     { "menuAction.Stop Examining", False },
     { "menuAction.Stop Observing", False },
-    { "menuStep.Revert", False },
-    { "menuOptions.Auto Comment", False },
-    { "menuOptions.Auto Observe", False },
-    { "menuOptions.Auto Raise Board", False },
-    { "menuOptions.Get Move List", False },
-    { "menuOptions.Premove", False },
-    { "menuOptions.Quiet Play", False },
+    { "menuAction.Upload to Examine", False },
+    { "menuEdit.Revert", False },
+    { "menuEdit.Annotate", False },
+    { "menuOptions.ICS", False },
 
     /* The next two options rely on SetCmailMode being called *after*    */
     /* SetGNUMode so that when GNU is being used to give hints these     */
@@ -2679,6 +2934,20 @@ Enables gnuEnables[] = {
 
     { "menuFile.Mail Move", False },
     { "menuFile.Reload CMail Message", False },
+    // [HGM] The following have been added to make a switch from ncp to GNU mode possible
+    { "menuMode.Machine White", True },
+    { "menuMode.Machine Black", True },
+    { "menuMode.Analysis Mode", True },
+    { "menuMode.Analyze File", True },
+    { "menuMode.Two Machines", True },
+    { "menuMode.Machine Match", True },
+    { "menuEngine.Engine #1 Settings", True },
+    { "menuEngine.Engine #2 Settings", True },
+    { "menuEngine.Hint", True },
+    { "menuEngine.Book", True },
+    { "menuEngine.Move Now", True },
+    { "menuEngine.Retract Move", True },
+    { "Action", True },
     { NULL, False }
 };
 
@@ -2698,93 +2967,98 @@ Enables cmailEnables[] = {
 Enables trainingOnEnables[] = {
   { "menuMode.Edit Comment", False },
   { "menuMode.Pause", False },
-  { "menuStep.Forward", False },
-  { "menuStep.Backward", False },
-  { "menuStep.Forward to End", False },
-  { "menuStep.Back to Start", False },
-  { "menuStep.Move Now", False },
-  { "menuStep.Truncate Game", False },
+  { "menuEdit.Forward", False },
+  { "menuEdit.Backward", False },
+  { "menuEdit.Forward to End", False },
+  { "menuEdit.Back to Start", False },
+  { "menuEngine.Move Now", False },
+  { "menuEdit.Truncate Game", False },
   { NULL, False }
 };
 
 Enables trainingOffEnables[] = {
   { "menuMode.Edit Comment", True },
   { "menuMode.Pause", True },
-  { "menuStep.Forward", True },
-  { "menuStep.Backward", True },
-  { "menuStep.Forward to End", True },
-  { "menuStep.Back to Start", True },
-  { "menuStep.Move Now", True },
-  { "menuStep.Truncate Game", True },
+  { "menuEdit.Forward", True },
+  { "menuEdit.Backward", True },
+  { "menuEdit.Forward to End", True },
+  { "menuEdit.Back to Start", True },
+  { "menuEngine.Move Now", True },
+  { "menuEdit.Truncate Game", True },
   { NULL, False }
 };
 
 Enables machineThinkingEnables[] = {
   { "menuFile.Load Game", False },
-  { "menuFile.Load Next Game", False },
-  { "menuFile.Load Previous Game", False },
-  { "menuFile.Reload Same Game", False },
-  { "menuFile.Paste Game", False },
+//  { "menuFile.Load Next Game", False },
+//  { "menuFile.Load Previous Game", False },
+//  { "menuFile.Reload Same Game", False },
+  { "menuEdit.Paste Game", False },
   { "menuFile.Load Position", False },
-  { "menuFile.Load Next Position", False },
-  { "menuFile.Load Previous Position", False },
-  { "menuFile.Reload Same Position", False },
-  { "menuFile.Paste Position", False },
+//  { "menuFile.Load Next Position", False },
+//  { "menuFile.Load Previous Position", False },
+//  { "menuFile.Reload Same Position", False },
+  { "menuEdit.Paste Position", False },
   { "menuMode.Machine White", False },
   { "menuMode.Machine Black", False },
   { "menuMode.Two Machines", False },
-  { "menuStep.Retract Move", False },
+//  { "menuMode.Machine Match", False },
+  { "menuEngine.Retract Move", False },
   { NULL, False }
 };
 
 Enables userThinkingEnables[] = {
   { "menuFile.Load Game", True },
-  { "menuFile.Load Next Game", True },
-  { "menuFile.Load Previous Game", True },
-  { "menuFile.Reload Same Game", True },
-  { "menuFile.Paste Game", True },
+//  { "menuFile.Load Next Game", True },
+//  { "menuFile.Load Previous Game", True },
+//  { "menuFile.Reload Same Game", True },
+  { "menuEdit.Paste Game", True },
   { "menuFile.Load Position", True },
-  { "menuFile.Load Next Position", True },
-  { "menuFile.Load Previous Position", True },
-  { "menuFile.Reload Same Position", True },
-  { "menuFile.Paste Position", True },
+//  { "menuFile.Load Next Position", True },
+//  { "menuFile.Load Previous Position", True },
+//  { "menuFile.Reload Same Position", True },
+  { "menuEdit.Paste Position", True },
   { "menuMode.Machine White", True },
   { "menuMode.Machine Black", True },
   { "menuMode.Two Machines", True },
-  { "menuStep.Retract Move", True },
+//  { "menuMode.Machine Match", True },
+  { "menuEngine.Retract Move", True },
   { NULL, False }
 };
 
-void SetICSMode()
+void
+SetICSMode ()
 {
   SetMenuEnables(icsEnables);
 
-#ifdef ZIPPY
-  if (appData.zippyPlay && !appData.noChessProgram)   /* [DM] icsEngineAnalyze */
+#if ZIPPY
+  if (appData.zippyPlay && !appData.noChessProgram) { /* [DM] icsEngineAnalyze */
      XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
+     XtSetSensitive(XtNameToWidget(menuBarWidget, "menuEngine.Engine #1 Settings"), True);
+  }
 #endif
 }
 
 void
-SetNCPMode()
+SetNCPMode ()
 {
   SetMenuEnables(ncpEnables);
 }
 
 void
-SetGNUMode()
+SetGNUMode ()
 {
   SetMenuEnables(gnuEnables);
 }
 
 void
-SetCmailMode()
+SetCmailMode ()
 {
   SetMenuEnables(cmailEnables);
 }
 
 void
-SetTrainingModeOn()
+SetTrainingModeOn ()
 {
   SetMenuEnables(trainingOnEnables);
   if (appData.showButtonBar) {
@@ -2794,7 +3068,7 @@ SetTrainingModeOn()
 }
 
 void
-SetTrainingModeOff()
+SetTrainingModeOff ()
 {
   SetMenuEnables(trainingOffEnables);
   if (appData.showButtonBar) {
@@ -2803,14 +3077,14 @@ SetTrainingModeOff()
 }
 
 void
-SetUserThinkingEnables()
+SetUserThinkingEnables ()
 {
   if (appData.noChessProgram) return;
   SetMenuEnables(userThinkingEnables);
 }
 
 void
-SetMachineThinkingEnables()
+SetMachineThinkingEnables ()
 {
   if (appData.noChessProgram) return;
   SetMenuEnables(machineThinkingEnables);
@@ -2826,8 +3100,140 @@ SetMachineThinkingEnables()
   }
 }
 
+// [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
+#define HISTORY_SIZE 64
+static char *history[HISTORY_SIZE];
+int histIn = 0, histP = 0;
+
+void
+SaveInHistory (char *cmd)
+{
+  if (history[histIn] != NULL) {
+    free(history[histIn]);
+    history[histIn] = NULL;
+  }
+  if (*cmd == NULLCHAR) return;
+  history[histIn] = StrSave(cmd);
+  histIn = (histIn + 1) % HISTORY_SIZE;
+  if (history[histIn] != NULL) {
+    free(history[histIn]);
+    history[histIn] = NULL;
+  }
+  histP = histIn;
+}
+
+char *
+PrevInHistory (char *cmd)
+{
+  int newhp;
+  if (histP == histIn) {
+    if (history[histIn] != NULL) free(history[histIn]);
+    history[histIn] = StrSave(cmd);
+  }
+  newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
+  if (newhp == histIn || history[newhp] == NULL) return NULL;
+  histP = newhp;
+  return history[histP];
+}
+
+char *
+NextInHistory ()
+{
+  if (histP == histIn) return NULL;
+  histP = (histP + 1) % HISTORY_SIZE;
+  return history[histP];   
+}
+// end of borrowed code
+
 #define Abs(n) ((n)<0 ? -(n) : (n))
 
+#ifdef ENABLE_NLS
+char *
+InsertPxlSize (char *pattern, int targetPxlSize)
+{
+    char *base_fnt_lst, strInt[12], *p, *q;
+    int alternatives, i, len, strIntLen;
+
+    /*
+     * Replace the "*" (if present) in the pixel-size slot of each
+     * alternative with the targetPxlSize.
+     */
+    p = pattern;
+    alternatives = 1;
+    while ((p = strchr(p, ',')) != NULL) {
+      alternatives++;
+      p++;
+    }
+    snprintf(strInt, sizeof(strInt), "%d", targetPxlSize);
+    strIntLen = strlen(strInt);
+    base_fnt_lst = calloc(1, strlen(pattern) + strIntLen * alternatives + 1);
+
+    p = pattern;
+    q = base_fnt_lst;
+    while (alternatives--) {
+      char *comma = strchr(p, ',');
+      for (i=0; i<14; i++) {
+       char *hyphen = strchr(p, '-');
+       if (!hyphen) break;
+       if (comma && hyphen > comma) break;
+       len = hyphen + 1 - p;
+       if (i == 7 && *p == '*' && len == 2) {
+         p += len;
+         memcpy(q, strInt, strIntLen);
+         q += strIntLen;
+         *q++ = '-';
+       } else {
+         memcpy(q, p, len);
+         p += len;
+         q += len;
+       }
+      }
+      if (!comma) break;
+      len = comma + 1 - p;
+      memcpy(q, p, len);
+      p += len;
+      q += len;
+    }
+    strcpy(q, p);
+
+    return base_fnt_lst;
+}
+
+XFontSet
+CreateFontSet (char *base_fnt_lst)
+{
+    XFontSet fntSet;
+    char **missing_list;
+    int missing_count;
+    char *def_string;
+
+    fntSet = XCreateFontSet(xDisplay, base_fnt_lst,
+                           &missing_list, &missing_count, &def_string);
+    if (appData.debugMode) {
+      int i, count;
+      XFontStruct **font_struct_list;
+      char **font_name_list;
+      fprintf(debugFP, "Requested font set for list %s\n", base_fnt_lst);
+      if (fntSet) {
+       fprintf(debugFP, " got list %s, locale %s\n",
+               XBaseFontNameListOfFontSet(fntSet),
+               XLocaleOfFontSet(fntSet));
+       count = XFontsOfFontSet(fntSet, &font_struct_list, &font_name_list);
+       for (i = 0; i < count; i++) {
+         fprintf(debugFP, " got charset %s\n", font_name_list[i]);
+       }
+      }
+      for (i = 0; i < missing_count; i++) {
+       fprintf(debugFP, " missing charset %s\n", missing_list[i]);
+      }
+    }
+    if (fntSet == NULL) {
+      fprintf(stderr, _("Unable to create font set for %s.\n"), base_fnt_lst);
+      exit(2);
+    }
+    return fntSet;
+}
+#else // not ENABLE_NLS
 /*
  * Find a font that matches "pattern" that is as close as
  * possible to the targetPxlSize.  Prefer fonts that are k
@@ -2837,46 +3243,18 @@ SetMachineThinkingEnables()
  * The return value should be freed with XtFree when no
  * longer needed.
  */
-char *FindFont(pattern, targetPxlSize)
-     char *pattern;
-     int targetPxlSize;
+char *
+FindFont (char *pattern, int targetPxlSize)
 {
     char **fonts, *p, *best, *scalable, *scalableTail;
     int i, j, nfonts, minerr, err, pxlSize;
 
-#ifdef ENABLE_NLS
-    char **missing_list;
-    int missing_count;
-    char *def_string, *base_fnt_lst, strInt[3];
-    XFontSet fntSet;
-    XFontStruct **fnt_list;
-
-    base_fnt_lst = calloc(1, strlen(pattern) + 3);
-    sprintf(strInt, "%d", targetPxlSize);
-    p = strstr(pattern, "--");
-    strncpy(base_fnt_lst, pattern, p - pattern + 2);
-    strcat(base_fnt_lst, strInt);
-    strcat(base_fnt_lst, strchr(p + 2, '-'));
-
-    if ((fntSet = XCreateFontSet(xDisplay,
-                                 base_fnt_lst,
-                                 &missing_list,
-                                 &missing_count,
-                                 &def_string)) == NULL) {
-
-       fprintf(stderr, _("Unable to create font set.\n"));
-       exit (2);
-    }
-
-    nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
-#else
     fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
     if (nfonts < 1) {
        fprintf(stderr, _("%s: no fonts match pattern %s\n"),
                programName, pattern);
        exit(2);
     }
-#endif
 
     best = fonts[0];
     scalable = NULL;
@@ -2911,24 +3289,46 @@ char *FindFont(pattern, targetPxlSize)
        while (isdigit(*scalableTail)) scalableTail++;
        sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
     } else {
-        p = (char *) XtMalloc(strlen(best) + 1);
-        strcpy(p, best);
+        p = (char *) XtMalloc(strlen(best) + 2);
+        safeStrCpy(p, best, strlen(best)+1 );
     }
     if (appData.debugMode) {
         fprintf(debugFP, _("resolved %s at pixel size %d\n  to %s\n"),
                pattern, targetPxlSize, p);
     }
-#ifdef ENABLE_NLS
-    if (missing_count > 0)
-       XFreeStringList(missing_list);
-    XFreeFontSet(xDisplay, fntSet);
-#else
-     XFreeFontNames(fonts);
-#endif
+    XFreeFontNames(fonts);
     return p;
 }
+#endif
 
-void CreateGCs()
+void
+DeleteGCs ()
+{   // [HGM] deletes GCs that are to be remade, to prevent resource leak;
+    // must be called before all non-first callse to CreateGCs()
+    XtReleaseGC(shellWidget, highlineGC);
+    XtReleaseGC(shellWidget, lightSquareGC);
+    XtReleaseGC(shellWidget, darkSquareGC);
+    XtReleaseGC(shellWidget, lineGC);
+    if (appData.monoMode) {
+       if (DefaultDepth(xDisplay, xScreen) == 1) {
+           XtReleaseGC(shellWidget, wbPieceGC);
+       } else {
+           XtReleaseGC(shellWidget, bwPieceGC);
+       }
+    } else {
+       XtReleaseGC(shellWidget, prelineGC);
+       XtReleaseGC(shellWidget, jailSquareGC);
+       XtReleaseGC(shellWidget, wdPieceGC);
+       XtReleaseGC(shellWidget, wlPieceGC);
+       XtReleaseGC(shellWidget, wjPieceGC);
+       XtReleaseGC(shellWidget, bdPieceGC);
+       XtReleaseGC(shellWidget, blPieceGC);
+       XtReleaseGC(shellWidget, bjPieceGC);
+    }
+}
+
+void
+CreateGCs (int redo)
 {
     XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
       | GCBackground | GCFunction | GCPlaneMask;
@@ -2940,20 +3340,23 @@ void CreateGCs()
     gc_values.line_style = LineSolid;
     gc_values.function = GXcopy;
 
-    gc_values.foreground = XBlackPixel(xDisplay, xScreen);
-    gc_values.background = XBlackPixel(xDisplay, xScreen);
-    lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
-
+  if(redo) {
+    DeleteGCs(); // called a second time; clean up old GCs first
+  } else { // [HGM] grid and font GCs created on first call only
     gc_values.foreground = XBlackPixel(xDisplay, xScreen);
     gc_values.background = XWhitePixel(xDisplay, xScreen);
     coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
     XSetFont(xDisplay, coordGC, coordFontID);
 
-    // [HGM] make font for holdings counts (white on black0
+    // [HGM] make font for holdings counts (white on black)
     gc_values.foreground = XWhitePixel(xDisplay, xScreen);
     gc_values.background = XBlackPixel(xDisplay, xScreen);
     countGC = XtGetGC(shellWidget, value_mask, &gc_values);
     XSetFont(xDisplay, countGC, countFontID);
+  }
+    gc_values.foreground = XBlackPixel(xDisplay, xScreen);
+    gc_values.background = XBlackPixel(xDisplay, xScreen);
+    lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
 
     if (appData.monoMode) {
        gc_values.foreground = XWhitePixel(xDisplay, xScreen);
@@ -3030,12 +3433,8 @@ void CreateGCs()
     }
 }
 
-void loadXIM(xim, xmask, filename, dest, mask)
-     XImage *xim;
-     XImage *xmask;
-     char *filename;
-     Pixmap *dest;
-     Pixmap *mask;
+void
+loadXIM (XImage *xim, XImage *xmask, char *filename, Pixmap *dest, Pixmap *mask)
 {
     int x, y, w, h, p;
     FILE *fp;
@@ -3081,6 +3480,8 @@ void loadXIM(xim, xmask, filename, dest, mask)
        }
     }
 
+    fclose(fp);
+
     /* create Pixmap of piece */
     *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
                          w, h, xim->depth);
@@ -3116,7 +3517,8 @@ void loadXIM(xim, xmask, filename, dest, mask)
 
 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
 
-void CreateXIMPieces()
+void
+CreateXIMPieces ()
 {
     int piece, kind;
     char buf[MSG_SIZ];
@@ -3201,8 +3603,35 @@ void CreateXIMPieces()
     XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
 }
 
+static VariantClass oldVariant = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
+
 #if HAVE_LIBXPM
-void CreateXPMPieces()
+void
+CreateXPMBoard (char *s, int kind)
+{
+    XpmAttributes attr;
+    attr.valuemask = 0;
+    if(!appData.useBitmaps || s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
+    if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
+       useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
+    }
+}
+
+void
+FreeXPMPieces ()
+{   // [HGM] to prevent resoucre leak on calling CreaeXPMPieces() a second time,
+    // thisroutine has to be called t free the old piece pixmaps
+    int piece, kind;
+    for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++)
+       for (kind=0; kind<4; kind++) XFreePixmap(xDisplay, xpmPieceBitmap2[kind][piece]);
+    if(useImageSqs) {
+       XFreePixmap(xDisplay, xpmLightSquare);
+       XFreePixmap(xDisplay, xpmDarkSquare);
+    }
+}
+
+void
+CreateXPMPieces ()
 {
     int piece, kind, r;
     char buf[MSG_SIZ];
@@ -3210,6 +3639,9 @@ void CreateXPMPieces()
     XpmAttributes attr;
     static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
     XpmColorSymbol symbols[4];
+    static int redo = False;
+
+    if(redo) FreeXPMPieces(); else redo = 1;
 
     /* The XSynchronize calls were copied from CreatePieces.
        Not sure if needed, but can't hurt */
@@ -3298,7 +3730,7 @@ void CreateXPMPieces()
                        exit(1);
                    }
                }
-               if(piece <= (int) WhiteKing) 
+               if(piece <= (int) WhiteKing)
                    xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
            }
        }
@@ -3334,6 +3766,7 @@ void CreateXPMPieces()
        xpmJailSquare = xpmLightSquare;
        fprintf(stderr, _("Done.\n"));
     }
+    oldVariant = -1; // kludge to force re-makig of animation masks
     XSynchronize(xDisplay, False); /* Work-around for xlib/xt
                                      buffering bug */
 }
@@ -3352,12 +3785,12 @@ void CreatePieces()
 
     for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
        for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
-           sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
-                   pieceBitmapNames[piece],
-                   ss, kind == SOLID ? 's' : 'o');
-           ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
-           if(piece <= (int)WhiteKing)
-               pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
+         snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
+                  pieceBitmapNames[piece],
+                  ss, kind == SOLID ? 's' : 'o');
+         ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
+         if(piece <= (int)WhiteKing)
+           pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
        }
     }
 
@@ -3366,7 +3799,8 @@ void CreatePieces()
 }
 #else
 /* With built-in bitmaps */
-void CreatePieces()
+void
+CreatePieces ()
 {
     BuiltInBits* bib = builtInBits;
     int piece, kind;
@@ -3380,13 +3814,13 @@ void CreatePieces()
 
     for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
        for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
-           sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
-                   pieceBitmapNames[piece],
-                   ss, kind == SOLID ? 's' : 'o');
-           ReadBitmap(&pieceBitmap2[kind][piece], buf,
-                      bib->bits[kind][piece], ss, ss);
-           if(piece <= (int)WhiteKing)
-               pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
+         snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
+                  pieceBitmapNames[piece],
+                  ss, kind == SOLID ? 's' : 'o');
+         ReadBitmap(&pieceBitmap2[kind][piece], buf,
+                    bib->bits[kind][piece], ss, ss);
+         if(piece <= (int)WhiteKing)
+           pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
        }
     }
 
@@ -3395,11 +3829,8 @@ void CreatePieces()
 }
 #endif
 
-void ReadBitmap(pm, name, bits, wreq, hreq)
-     Pixmap *pm;
-     String name;
-     unsigned char bits[];
-     u_int wreq, hreq;
+void
+ReadBitmap (Pixmap *pm, String name, unsigned char bits[], u_int wreq, u_int hreq)
 {
     int x_hot, y_hot;
     u_int w, h;
@@ -3407,12 +3838,12 @@ void ReadBitmap(pm, name, bits, wreq, hreq)
     char msg[MSG_SIZ], fullname[MSG_SIZ];
 
     if (*appData.bitmapDirectory != NULLCHAR) {
-        strcpy(fullname, appData.bitmapDirectory);
-       strcat(fullname, "/");
-       strcat(fullname, name);
-       errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
-                                 &w, &h, pm, &x_hot, &y_hot);
-    fprintf(stderr, "load %s\n", name);
+      safeStrCpy(fullname, appData.bitmapDirectory, sizeof(fullname)/sizeof(fullname[0]) );
+      strncat(fullname, "/", MSG_SIZ - strlen(fullname) - 1);
+      strncat(fullname, name, MSG_SIZ - strlen(fullname) - 1);
+      errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
+                               &w, &h, pm, &x_hot, &y_hot);
+      fprintf(stderr, "load %s\n", name);
        if (errcode != BitmapSuccess) {
            switch (errcode) {
              case BitmapOpenFailed:
@@ -3446,7 +3877,8 @@ void ReadBitmap(pm, name, bits, wreq, hreq)
     }
 }
 
-void CreateGrid()
+void
+CreateGrid ()
 {
     int i, j;
 
@@ -3471,20 +3903,49 @@ void CreateGrid()
     }
 }
 
-static void MenuBarSelect(w, addr, index)
-     Widget w;
-     caddr_t addr;
-     caddr_t index;
+static void
+MenuBarSelect (Widget w, caddr_t addr, caddr_t index)
 {
     XtActionProc proc = (XtActionProc) addr;
 
     (proc)(NULL, NULL, NULL, NULL);
 }
 
-void CreateMenuBarPopup(parent, name, mb)
-     Widget parent;
-     String name;
-     Menu *mb;
+static void
+MenuEngineSelect (Widget w, caddr_t addr, caddr_t index)
+{
+    RecentEngineEvent((int) (intptr_t) addr);
+}
+
+void
+AppendEnginesToMenu (Widget menu, char *list)
+{
+    int i=0, j;
+    Widget entry;
+    MenuItem *mi;
+    Arg args[16];
+    char *p;
+
+    if(appData.icsActive || appData.recentEngines <= 0) return;
+    recentEngines = strdup(list);
+    j = 0;
+    XtSetArg(args[j], XtNleftMargin, 20);   j++;
+    XtSetArg(args[j], XtNrightMargin, 20);  j++;
+    while (*list) {
+       p = strchr(list, '\n'); if(p == NULL) break;
+       if(i == 0) XtCreateManagedWidget(_("----"), smeLineObjectClass, menu, args, j); // at least one valid item to add
+       *p = 0;
+       XtSetArg(args[j], XtNlabel, XtNewString(list));
+       entry = XtCreateManagedWidget("engine", smeBSBObjectClass, menu, args, j+1);
+       XtAddCallback(entry, XtNcallback,
+                         (XtCallbackProc) MenuEngineSelect,
+                         (caddr_t) (intptr_t) i);
+       i++; *p = '\n'; list = p + 1;
+    }
+}
+
+void
+CreateMenuBarPopup (Widget parent, String name, Menu *mb)
 {
     int j;
     Widget menu, entry;
@@ -3499,11 +3960,11 @@ void CreateMenuBarPopup(parent, name, mb)
     mi = mb->mi;
     while (mi->string != NULL) {
        if (strcmp(mi->string, "----") == 0) {
-           entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
+         entry = XtCreateManagedWidget(_(mi->string), smeLineObjectClass,
                                          menu, args, j);
        } else {
           XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
-           entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
+           entry = XtCreateManagedWidget(mi->ref, smeBSBObjectClass,
                                          menu, args, j+1);
            XtAddCallback(entry, XtNcallback,
                          (XtCallbackProc) MenuBarSelect,
@@ -3511,15 +3972,18 @@ void CreateMenuBarPopup(parent, name, mb)
        }
        mi++;
     }
+    if(!strcmp(mb->name, "Engine")) AppendEnginesToMenu(menu, appData.recentEngineList);
 }
 
-Widget CreateMenuBar(mb)
-     Menu *mb;
+Widget
+CreateMenuBar (Menu *mb, int boardWidth)
 {
-    int j;
-    Widget anchor, menuBar;
+    int i, j, nr = 0, wtot = 0, widths[10];
+    Widget menuBar;
     Arg args[16];
     char menuName[MSG_SIZ];
+    Dimension w;
+    Menu *ma = mb;
 
     j = 0;
     XtSetArg(args[j], XtNorientation, XtorientHorizontal);  j++;
@@ -3529,31 +3993,37 @@ Widget CreateMenuBar(mb)
                             formWidget, args, j);
 
     while (mb->name != NULL) {
-       strcpy(menuName, "menu");
-       strcat(menuName, mb->name);
+        safeStrCpy(menuName, "menu", sizeof(menuName)/sizeof(menuName[0]) );
+       strncat(menuName, mb->ref, MSG_SIZ - strlen(menuName) - 1);
        j = 0;
        XtSetArg(args[j], XtNmenuName, XtNewString(menuName));  j++;
-       if (tinyLayout) {
-           char shortName[2];
-            shortName[0] = _(mb->name)[0];
-           shortName[1] = NULLCHAR;
-           XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
-       }
-      else {
-          XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
-      }
-
+       XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name)));  j++;
        XtSetArg(args[j], XtNborderWidth, 0);                   j++;
-       anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
+       mb->subMenu = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
                                       menuBar, args, j);
        CreateMenuBarPopup(menuBar, menuName, mb);
+       j = 0;
+       XtSetArg(args[j], XtNwidth, &w);                   j++;
+       XtGetValues(mb->subMenu, args, j);
+       wtot += mb->textWidth = widths[nr++] = w;
        mb++;
     }
+    while(wtot > boardWidth - 40) {
+       int wmax=0, imax=0;
+       for(i=0; i<nr; i++) if(widths[i] > wmax) wmax = widths[imax=i];
+       widths[imax]--;
+       wtot--;
+    }
+    for(i=0; i<nr; i++) if(widths[i] != ma[i].textWidth) {
+       j = 0;
+       XtSetArg(args[j], XtNwidth, widths[i]);                   j++;
+       XtSetValues(ma[i].subMenu, args, j);
+    }
     return menuBar;
 }
 
-Widget CreateButtonBar(mi)
-     MenuItem *mi;
+Widget
+CreateButtonBar (MenuItem *mi)
 {
     int j;
     Widget button, buttonBar;
@@ -3587,9 +4057,7 @@ Widget CreateButtonBar(mi)
 }
 
 Widget
-CreatePieceMenu(name, color)
-     char *name;
-     int color;
+CreatePieceMenu (char *name, int color)
 {
     int i;
     Widget entry, menu;
@@ -3623,7 +4091,7 @@ CreatePieceMenu(name, color)
 }
 
 void
-CreatePieceMenus()
+CreatePieceMenus ()
 {
     int i;
     Widget entry;
@@ -3633,6 +4101,7 @@ CreatePieceMenus()
     whitePieceMenu = CreatePieceMenu("menuW", 0);
     blackPieceMenu = CreatePieceMenu("menuB", 1);
 
+    if(appData.pieceMenu) // [HGM] sweep: no idea what this was good for, but it stopped reporting button events outside the window
     XtRegisterGrabAction(PieceMenuPopup, True,
                         (unsigned)(ButtonPressMask|ButtonReleaseMask),
                         GrabModeAsync, GrabModeAsync);
@@ -3658,7 +4127,8 @@ CreatePieceMenus()
     }
 }
 
-void SetupDropMenu()
+void
+SetupDropMenu ()
 {
     int i, j, count;
     char label[32];
@@ -3682,90 +4152,51 @@ void SetupDropMenu()
     }
 }
 
-void PieceMenuPopup(w, event, params, num_params)
-     Widget w;
-     XEvent *event;
-     String *params;
-     Cardinal *num_params;
-{
-    String whichMenu;
-    if (event->type != ButtonPress) return;
-    if (errorUp) ErrorPopDown();
-    switch (gameMode) {
-      case EditPosition:
-      case IcsExamining:
-       whichMenu = params[0];
-       break;
-      case IcsPlayingWhite:
-      case IcsPlayingBlack:
-      case EditGame:
-      case MachinePlaysWhite:
-      case MachinePlaysBlack:
-       if (appData.testLegality &&
-           gameInfo.variant != VariantBughouse &&
-           gameInfo.variant != VariantCrazyhouse) return;
-       SetupDropMenu();
-       whichMenu = "menuD";
-       break;
-      default:
-       return;
-    }
-
-    if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
-       ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
-       pmFromX = pmFromY = -1;
-       return;
+void
+PieceMenuPopup (Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+    String whichMenu; int menuNr = -2;
+    shiftKey = strcmp(params[0], "menuW"); // used to indicate black
+    if (event->type == ButtonRelease)
+        menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
+    else if (event->type == ButtonPress)
+        menuNr = RightClick(Press,   event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
+    switch(menuNr) {
+      case 0: whichMenu = params[0]; break;
+      case 1: SetupDropMenu(); whichMenu = "menuD"; break;
+      case 2:
+      case -1: if (errorUp) ErrorPopDown();
+      default: return;
     }
-    if (flipView)
-      pmFromX = BOARD_WIDTH - 1 - pmFromX;
-    else
-      pmFromY = BOARD_HEIGHT - 1 - pmFromY;
-
     XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
 }
 
-static void PieceMenuSelect(w, piece, junk)
-     Widget w;
-     ChessSquare piece;
-     caddr_t junk;
+static void
+PieceMenuSelect (Widget w, ChessSquare piece, caddr_t junk)
 {
     if (pmFromX < 0 || pmFromY < 0) return;
     EditPositionMenuEvent(piece, pmFromX, pmFromY);
 }
 
-static void DropMenuSelect(w, piece, junk)
-     Widget w;
-     ChessSquare piece;
-     caddr_t junk;
+static void
+DropMenuSelect (Widget w, ChessSquare piece, caddr_t junk)
 {
     if (pmFromX < 0 || pmFromY < 0) return;
     DropMenuEvent(piece, pmFromX, pmFromY);
 }
 
-void WhiteClock(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+WhiteClock (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
-    if (gameMode == EditPosition || gameMode == IcsExamining) {
-       SetWhiteToPlayEvent();
-    } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
-       CallFlagEvent();
-    }
+    shiftKey = prms[0][0] & 1;
+    ClockClick(0);
 }
 
-void BlackClock(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+BlackClock (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
-    if (gameMode == EditPosition || gameMode == IcsExamining) {
-       SetBlackToPlayEvent();
-    } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
-       CallFlagEvent();
-    }
+    shiftKey = prms[0][0] & 1;
+    ClockClick(1);
 }
 
 
@@ -3773,8 +4204,8 @@ void BlackClock(w, event, prms, nprms)
  * If the user selects on a border boundary, return -1; if off the board,
  *   return -2.  Otherwise map the event coordinate to the square.
  */
-int EventToSquare(x, limit)
-     int x;
+int
+EventToSquare (int x, int limit)
 {
     if (x <= 0)
       return -2;
@@ -3789,19 +4220,18 @@ int EventToSquare(x, limit)
     return x;
 }
 
-static void do_flash_delay(msec)
-     unsigned long msec;
+static void
+do_flash_delay (unsigned long msec)
 {
     TimeDelay(msec);
 }
 
-static void drawHighlight(file, rank, gc)
-     int file, rank;
-     GC gc;
+static void
+drawHighlight (int file, int rank, GC gc)
 {
     int x, y;
 
-    if (lineGap == 0 || appData.blindfold) return;
+    if (lineGap == 0) return;
 
     if (flipView) {
        x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
@@ -3821,25 +4251,30 @@ int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
 
 void
-SetHighlights(fromX, fromY, toX, toY)
-     int fromX, fromY, toX, toY;
+SetHighlights (int fromX, int fromY, int toX, int toY)
 {
     if (hi1X != fromX || hi1Y != fromY) {
        if (hi1X >= 0 && hi1Y >= 0) {
            drawHighlight(hi1X, hi1Y, lineGC);
        }
+    } // [HGM] first erase both, then draw new!
+    if (hi2X != toX || hi2Y != toY) {
+       if (hi2X >= 0 && hi2Y >= 0) {
+           drawHighlight(hi2X, hi2Y, lineGC);
+       }
+    }
+    if (hi1X != fromX || hi1Y != fromY) {
        if (fromX >= 0 && fromY >= 0) {
            drawHighlight(fromX, fromY, highlineGC);
        }
     }
     if (hi2X != toX || hi2Y != toY) {
-       if (hi2X >= 0 && hi2Y >= 0) {
-           drawHighlight(hi2X, hi2Y, lineGC);
-       }
        if (toX >= 0 && toY >= 0) {
            drawHighlight(toX, toY, highlineGC);
        }
     }
+    if(toX<0) // clearing the highlights must have damaged arrow
+       DrawArrowHighlight(hi1X, hi1Y, hi2X, hi2Y); // for now, redraw it (should really be cleared!)
     hi1X = fromX;
     hi1Y = fromY;
     hi2X = toX;
@@ -3847,15 +4282,14 @@ SetHighlights(fromX, fromY, toX, toY)
 }
 
 void
-ClearHighlights()
+ClearHighlights ()
 {
     SetHighlights(-1, -1, -1, -1);
 }
 
 
 void
-SetPremoveHighlights(fromX, fromY, toX, toY)
-     int fromX, fromY, toX, toY;
+SetPremoveHighlights (int fromX, int fromY, int toX, int toY)
 {
     if (pm1X != fromX || pm1Y != fromY) {
        if (pm1X >= 0 && pm1Y >= 0) {
@@ -3880,16 +4314,37 @@ SetPremoveHighlights(fromX, fromY, toX, toY)
 }
 
 void
-ClearPremoveHighlights()
+ClearPremoveHighlights ()
 {
   SetPremoveHighlights(-1, -1, -1, -1);
 }
 
-static void BlankSquare(x, y, color, piece, dest)
-     int x, y, color;
-     ChessSquare piece;
-     Drawable dest;
-{
+static int
+CutOutSquare (int x, int y, int *x0, int *y0, int  kind)
+{
+    int W = BOARD_WIDTH, H = BOARD_HEIGHT;
+    int nx = x/(squareSize + lineGap), ny = y/(squareSize + lineGap);
+    *x0 = 0; *y0 = 0;
+    if(textureW[kind] < squareSize || textureH[kind] < squareSize) return 0;
+    if(textureW[kind] < W*squareSize)
+       *x0 = (textureW[kind] - squareSize) * nx/(W-1);
+    else
+       *x0 = textureW[kind]*nx / W + (textureW[kind] - W*squareSize) / (2*W);
+    if(textureH[kind] < H*squareSize)
+       *y0 = (textureH[kind] - squareSize) * ny/(H-1);
+    else
+       *y0 = textureH[kind]*ny / H + (textureH[kind] - H*squareSize) / (2*H);
+    return 1;
+}
+
+static void
+BlankSquare (int x, int y, int color, ChessSquare piece, Drawable dest, int fac)
+{   // [HGM] extra param 'fac' for forcing destination to (0,0) for copying to animation buffer
+    int x0, y0;
+    if (useImages && color != 2 && (useTexture & color+1) && CutOutSquare(x, y, &x0, &y0, color)) {
+       XCopyArea(xDisplay, xpmBoardBitmap[color], dest, wlPieceGC, x0, y0,
+                 squareSize, squareSize, x*fac, y*fac);
+    } else
     if (useImages && useImageSqs) {
        Pixmap pm;
        switch (color) {
@@ -3905,7 +4360,7 @@ static void BlankSquare(x, y, color, piece, dest)
            break;
        }
        XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
-                 squareSize, squareSize, x, y);
+                 squareSize, squareSize, x*fac, y*fac);
     } else {
        GC gc;
        switch (color) {
@@ -3920,7 +4375,7 @@ static void BlankSquare(x, y, color, piece, dest)
            gc = jailSquareGC;
            break;
        }
-       XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
+       XFillRectangle(xDisplay, dest, gc, x*fac, y*fac, squareSize, squareSize);
     }
 }
 
@@ -3928,10 +4383,8 @@ static void BlankSquare(x, y, color, piece, dest)
    I split out the routines to draw a piece so that I could
    make a generic flash routine.
 */
-static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
-     ChessSquare piece;
-     int square_color, x, y;
-     Drawable dest;
+static void
+monoDrawPiece_1bit (ChessSquare piece, int square_color, int x, int y, Drawable dest)
 {
     /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
     switch (square_color) {
@@ -3954,10 +4407,8 @@ static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
     }
 }
 
-static void monoDrawPiece(piece, square_color, x, y, dest)
-     ChessSquare piece;
-     int square_color, x, y;
-     Drawable dest;
+static void
+monoDrawPiece (ChessSquare piece, int square_color, int x, int y, Drawable dest)
 {
     switch (square_color) {
       case 1: /* light */
@@ -3979,10 +4430,8 @@ static void monoDrawPiece(piece, square_color, x, y, dest)
     }
 }
 
-static void colorDrawPiece(piece, square_color, x, y, dest)
-     ChessSquare piece;
-     int square_color, x, y;
-     Drawable dest;
+static void
+colorDrawPiece (ChessSquare piece, int square_color, int x, int y, Drawable dest)
 {
     if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
     switch (square_color) {
@@ -4008,12 +4457,10 @@ static void colorDrawPiece(piece, square_color, x, y, dest)
     }
 }
 
-static void colorDrawPieceImage(piece, square_color, x, y, dest)
-     ChessSquare piece;
-     int square_color, x, y;
-     Drawable dest;
+static void
+colorDrawPieceImage (ChessSquare piece, int square_color, int x, int y, Drawable dest)
 {
-    int kind;
+    int kind, p = piece;
 
     switch (square_color) {
       case 1: /* light */
@@ -4035,6 +4482,15 @@ static void colorDrawPieceImage(piece, square_color, x, y, dest)
        }
        break;
     }
+    if(appData.upsideDown && flipView) { kind ^= 2; p += p < BlackPawn ? BlackPawn : -BlackPawn; }// swap white and black pieces
+    if(useTexture & square_color+1) {
+        BlankSquare(x, y, square_color, piece, dest, 1); // erase previous contents with background
+       XSetClipMask(xDisplay, wlPieceGC, xpmMask[p]);
+       XSetClipOrigin(xDisplay, wlPieceGC, x, y);
+       XCopyArea(xDisplay, xpmPieceBitmap[kind][piece], dest, wlPieceGC, 0, 0, squareSize, squareSize, x, y);
+       XSetClipMask(xDisplay, wlPieceGC, None);
+       XSetClipOrigin(xDisplay, wlPieceGC, 0, 0);
+    } else
     XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
              dest, wlPieceGC, 0, 0,
              squareSize, squareSize, x, y);
@@ -4042,7 +4498,8 @@ static void colorDrawPieceImage(piece, square_color, x, y, dest)
 
 typedef void (*DrawFunc)();
 
-DrawFunc ChooseDrawFunc()
+DrawFunc
+ChooseDrawFunc ()
 {
     if (appData.monoMode) {
        if (DefaultDepth(xDisplay, xScreen) == 1) {
@@ -4059,8 +4516,8 @@ DrawFunc ChooseDrawFunc()
 }
 
 /* [HR] determine square color depending on chess variant. */
-static int SquareColor(row, column)
-     int row, column;
+static int
+SquareColor (int row, int column)
 {
     int square_color;
 
@@ -4084,9 +4541,8 @@ static int SquareColor(row, column)
     return square_color;
 }
 
-void DrawSquare(row, column, piece, do_flash)
-     int row, column, do_flash;
-     ChessSquare piece;
+void
+DrawSquare (int row, int column, ChessSquare piece, int do_flash)
 {
     int square_color, x, y, direction, font_ascent, font_descent;
     int i;
@@ -4108,13 +4564,15 @@ void DrawSquare(row, column, piece, do_flash)
          (squareSize + lineGap);
     }
 
+    if(twoBoards && partnerUp) x += hOffset; // [HGM] dual: draw second board
+
     square_color = SquareColor(row, column);
 
     if ( // [HGM] holdings: blank out area between board and holdings
                  column == BOARD_LEFT-1 ||  column == BOARD_RGHT
               || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
                  || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
-                       BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
+                       BlankSquare(x, y, 2, EmptySquare, xBoardWindow, 1);
 
                        // [HGM] print piece counts next to holdings
                        string[1] = NULLCHAR;
@@ -4146,17 +4604,17 @@ void DrawSquare(row, column, piece, do_flash)
                        }
     } else {
            if (piece == EmptySquare || appData.blindfold) {
-                       BlankSquare(x, y, square_color, piece, xBoardWindow);
+                       BlankSquare(x, y, square_color, piece, xBoardWindow, 1);
            } else {
                        drawfunc = ChooseDrawFunc();
+
                        if (do_flash && appData.flashCount > 0) {
                            for (i=0; i<appData.flashCount; ++i) {
-
                                        drawfunc(piece, square_color, x, y, xBoardWindow);
                                        XSync(xDisplay, False);
                                        do_flash_delay(flash_delay);
 
-                                       BlankSquare(x, y, square_color, piece, xBoardWindow);
+                                       BlankSquare(x, y, square_color, piece, xBoardWindow, 1);
                                        XSync(xDisplay, False);
                                        do_flash_delay(flash_delay);
                            }
@@ -4193,40 +4651,126 @@ void DrawSquare(row, column, piece, do_flash)
                        x + 2, y + font_ascent + 1, string, 1);
        }
     }
+    if(!partnerUp && marker[row][column]) {
+       if(appData.monoMode) {
+           XFillArc(xDisplay, xBoardWindow, marker[row][column] == 2 ? darkSquareGC : lightSquareGC,
+                   x + squareSize/4, y+squareSize/4, squareSize/2, squareSize/2, 0, 64*360);
+           XDrawArc(xDisplay, xBoardWindow, marker[row][column] == 2 ? lightSquareGC : darkSquareGC,
+                   x + squareSize/4, y+squareSize/4, squareSize/2, squareSize/2, 0, 64*360);
+       } else
+       XFillArc(xDisplay, xBoardWindow, marker[row][column] == 2 ? prelineGC : highlineGC,
+               x + squareSize/4, y+squareSize/4, squareSize/2, squareSize/2, 0, 64*360);
+    }
 }
 
+double
+Fraction (int x, int start, int stop)
+{
+   double f = ((double) x - start)/(stop - start);
+   if(f > 1.) f = 1.; else if(f < 0.) f = 0.;
+   return f;
+}
+
+static WindowPlacement wpNew;
+
+void
+CoDrag (Widget sh, WindowPlacement *wp)
+{
+    Arg args[16];
+    int j=0, touch=0, fudge = 2;
+    GetActualPlacement(sh, wp);
+    if(abs(wpMain.x + wpMain.width + 2*frameX - wp->x)         < fudge) touch = 1; else // right touch
+    if(abs(wp->x + wp->width + 2*frameX - wpMain.x)            < fudge) touch = 2; else // left touch
+    if(abs(wpMain.y + wpMain.height + frameX + frameY - wp->y) < fudge) touch = 3; else // bottom touch
+    if(abs(wp->y + wp->height + frameX + frameY - wpMain.y)    < fudge) touch = 4;      // top touch
+    if(!touch ) return; // only windows that touch co-move
+    if(touch < 3 && wpNew.height != wpMain.height) { // left or right and height changed
+       int heightInc = wpNew.height - wpMain.height;
+       double fracTop = Fraction(wp->y, wpMain.y, wpMain.y + wpMain.height + frameX + frameY);
+       double fracBot = Fraction(wp->y + wp->height + frameX + frameY + 1, wpMain.y, wpMain.y + wpMain.height + frameX + frameY);
+       wp->y += fracTop * heightInc;
+       heightInc = (int) (fracBot * heightInc) - (int) (fracTop * heightInc);
+       if(heightInc) XtSetArg(args[j], XtNheight, wp->height + heightInc), j++;
+    } else if(touch > 2 && wpNew.width != wpMain.width) { // top or bottom and width changed
+       int widthInc = wpNew.width - wpMain.width;
+       double fracLeft = Fraction(wp->x, wpMain.x, wpMain.x + wpMain.width + 2*frameX);
+       double fracRght = Fraction(wp->x + wp->width + 2*frameX + 1, wpMain.x, wpMain.x + wpMain.width + 2*frameX);
+       wp->y += fracLeft * widthInc;
+       widthInc = (int) (fracRght * widthInc) - (int) (fracLeft * widthInc);
+       if(widthInc) XtSetArg(args[j], XtNwidth, wp->width + widthInc), j++;
+    }
+    wp->x += wpNew.x - wpMain.x;
+    wp->y += wpNew.y - wpMain.y;
+    if(touch == 1) wp->x += wpNew.width - wpMain.width; else
+    if(touch == 3) wp->y += wpNew.height - wpMain.height;
+    XtSetArg(args[j], XtNx, wp->x); j++;
+    XtSetArg(args[j], XtNy, wp->y); j++;
+    XtSetValues(sh, args, j);
+}
+
+void
+DragProc ()
+{
+       GetActualPlacement(shellWidget, &wpNew);
+       if(wpNew.x == wpMain.x && wpNew.y == wpMain.y && // not moved
+          wpNew.width == wpMain.width && wpNew.height == wpMain.height) // not sized
+           return; // false alarm
+       if(EngineOutputIsUp()) CoDrag(engineOutputShell, &wpEngineOutput);
+       if(MoveHistoryIsUp()) CoDrag(shells[7], &wpMoveHistory);
+       if(EvalGraphIsUp()) CoDrag(evalGraphShell, &wpEvalGraph);
+       if(GameListIsUp()) CoDrag(gameListShell, &wpGameList);
+       wpMain = wpNew;
+       XDrawPosition(boardWidget, True, NULL);
+}
+
+
+void
+DelayedDrag ()
+{
+    static XtIntervalId delayedDragID = 0;
+    if(delayedDragID) XtRemoveTimeOut(delayedDragID); // cancel pending
+    delayedDragID =
+      XtAppAddTimeOut(appContext, 50, (XtTimerCallbackProc) DragProc, (XtPointer) 0); // and schedule new one 50 msec later
+}
 
 /* Why is this needed on some versions of X? */
-void EventProc(widget, unused, event)
-     Widget widget;
-     caddr_t unused;
-     XEvent *event;
+void
+EventProc (Widget widget, caddr_t unused, XEvent *event)
 {
     if (!XtIsRealized(widget))
       return;
-
     switch (event->type) {
+      case ConfigureNotify: // main window is being dragged: drag attached windows with it
+       if(appData.useStickyWindows)
+           DelayedDrag(); // as long as events keep coming in faster than 50 msec, they destroy each other
+       break;
       case Expose:
        if (event->xexpose.count > 0) return;  /* no clipping is done */
        XDrawPosition(widget, True, NULL);
+       if(twoBoards) { // [HGM] dual: draw other board in other orientation
+           flipView = !flipView; partnerUp = !partnerUp;
+           XDrawPosition(widget, True, NULL);
+           flipView = !flipView; partnerUp = !partnerUp;
+       }
        break;
+      case MotionNotify:
+        if(SeekGraphClick(Press, event->xbutton.x, event->xbutton.y, 1)) break;
       default:
        return;
     }
 }
 /* end why */
 
-void DrawPosition(fullRedraw, board)
-     /*Boolean*/int fullRedraw;
-     Board board;
+void
+DrawPosition (int fullRedraw, Board board)
 {
     XDrawPosition(boardWidget, fullRedraw, board);
 }
 
 /* Returns 1 if there are "too many" differences between b1 and b2
    (i.e. more than 1 move was made) */
-static int too_many_diffs(b1, b2)
-     Board b1, b2;
+static int
+too_many_diffs (Board b1, Board b2)
 {
     int i, j;
     int c = 0;
@@ -4239,7 +4783,6 @@ static int too_many_diffs(b1, b2)
            }
        }
     }
-
     return 0;
 }
 
@@ -4260,9 +4803,8 @@ static int castling_matrix[4][5] = {
    Note: Only handles a max of 1 castling move, so be sure
    to call too_many_diffs() first.
    */
-static int check_castle_draw(newb, oldb, rrow, rcol)
-     Board newb, oldb;
-     int *rrow, *rcol;
+static int
+check_castle_draw (Board newb, Board oldb, int *rrow, int *rcol)
 {
     int i, *r, j;
     int match;
@@ -4290,30 +4832,65 @@ static int check_castle_draw(newb, oldb, rrow, rcol)
     return 0;
 }
 
-static int damage[BOARD_RANKS][BOARD_FILES];
+// [HGM] seekgraph: some low-level drawing routines cloned from xevalgraph
+void
+DrawSeekAxis (int x, int y, int xTo, int yTo)
+{
+      XDrawLine(xDisplay, xBoardWindow, lineGC, x, y, xTo, yTo);
+}
+
+void
+DrawSeekBackground (int left, int top, int right, int bottom)
+{
+    XFillRectangle(xDisplay, xBoardWindow, lightSquareGC, left, top, right-left, bottom-top);
+}
+
+void
+DrawSeekText (char *buf, int x, int y)
+{
+    XDrawString(xDisplay, xBoardWindow, coordGC, x, y+4, buf, strlen(buf));
+}
+
+void
+DrawSeekDot (int x, int y, int colorNr)
+{
+    int square = colorNr & 0x80;
+    GC color;
+    colorNr &= 0x7F;
+    color = colorNr == 0 ? prelineGC : colorNr == 1 ? darkSquareGC : highlineGC;
+    if(square)
+       XFillRectangle(xDisplay, xBoardWindow, color,
+               x-squareSize/9, y-squareSize/9, 2*squareSize/9, 2*squareSize/9);
+    else
+       XFillArc(xDisplay, xBoardWindow, color,
+               x-squareSize/8, y-squareSize/8, squareSize/4, squareSize/4, 0, 64*360);
+}
+
+static int damage[2][BOARD_RANKS][BOARD_FILES];
 
 /*
  * event handler for redrawing the board
  */
-void XDrawPosition(w, repaint, board)
-     Widget w;
-     /*Boolean*/int repaint;
-     Board board;
+void
+XDrawPosition (Widget w, int repaint, Board board)
 {
     int i, j, do_flash;
     static int lastFlipView = 0;
-    static int lastBoardValid = 0;
-    static Board lastBoard;
+    static int lastBoardValid[2] = {0, 0};
+    static Board lastBoard[2];
     Arg args[16];
     int rrow, rcol;
+    int nr = twoBoards*partnerUp;
+
+    if(DrawSeekGraph()) return; // [HGM] seekgraph: suppress any drawing if seek graph up
 
     if (board == NULL) {
-       if (!lastBoardValid) return;
-       board = lastBoard;
+       if (!lastBoardValid[nr]) return;
+       board = lastBoard[nr];
     }
-    if (!lastBoardValid || lastFlipView != flipView) {
+    if (!lastBoardValid[nr] || (nr == 0 && lastFlipView != flipView)) {
        XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
-       XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
+       XtSetValues(XtNameToWidget(menuBarWidget, "menuView.Flip View"),
                    args, 1);
     }
 
@@ -4322,19 +4899,23 @@ void XDrawPosition(w, repaint, board)
      * but this causes a very distracting flicker.
      */
 
-    if (!repaint && lastBoardValid && lastFlipView == flipView) {
+    if (!repaint && lastBoardValid[nr] && (nr == 1 || lastFlipView == flipView)) {
+
+       if ( lineGap && IsDrawArrowEnabled())
+           XDrawSegments(xDisplay, xBoardWindow, lineGC,
+                       gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
 
        /* If too much changes (begin observing new game, etc.), don't
           do flashing */
-       do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
+       do_flash = too_many_diffs(board, lastBoard[nr]) ? 0 : 1;
 
        /* Special check for castling so we don't flash both the king
           and the rook (just flash the king). */
        if (do_flash) {
-           if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
+           if (check_castle_draw(board, lastBoard[nr], &rrow, &rcol)) {
                /* Draw rook with NO flashing. King will be drawn flashing later */
                DrawSquare(rrow, rcol, board[rrow][rcol], 0);
-               lastBoard[rrow][rcol] = board[rrow][rcol];
+               lastBoard[nr][rrow][rcol] = board[rrow][rcol];
            }
        }
 
@@ -4343,32 +4924,34 @@ void XDrawPosition(w, repaint, board)
           is flashing on its new square */
        for (i = 0; i < BOARD_HEIGHT; i++)
          for (j = 0; j < BOARD_WIDTH; j++)
-           if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
-               || damage[i][j]) {
+           if ((board[i][j] != lastBoard[nr][i][j] && board[i][j] == EmptySquare)
+               || damage[nr][i][j]) {
                DrawSquare(i, j, board[i][j], 0);
-               damage[i][j] = False;
+               damage[nr][i][j] = False;
            }
 
        /* Second pass -- Draw piece(s) in new position and flash them */
        for (i = 0; i < BOARD_HEIGHT; i++)
          for (j = 0; j < BOARD_WIDTH; j++)
-           if (board[i][j] != lastBoard[i][j]) {
+           if (board[i][j] != lastBoard[nr][i][j]) {
                DrawSquare(i, j, board[i][j], do_flash);
            }
     } else {
        if (lineGap > 0)
          XDrawSegments(xDisplay, xBoardWindow, lineGC,
+                       twoBoards & partnerUp ? secondSegments : // [HGM] dual
                        gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
 
        for (i = 0; i < BOARD_HEIGHT; i++)
          for (j = 0; j < BOARD_WIDTH; j++) {
              DrawSquare(i, j, board[i][j], 0);
-             damage[i][j] = False;
+             damage[nr][i][j] = False;
          }
     }
 
-    CopyBoard(lastBoard, board);
-    lastBoardValid = 1;
+    CopyBoard(lastBoard[nr], board);
+    lastBoardValid[nr] = 1;
+  if(nr == 0) { // [HGM] dual: no highlights on second board yet
     lastFlipView = flipView;
 
     /* Draw highlights */
@@ -4384,7 +4967,8 @@ void XDrawPosition(w, repaint, board)
     if (hi2X >= 0 && hi2Y >= 0) {
       drawHighlight(hi2X, hi2Y, highlineGC);
     }
-
+    DrawArrowHighlight(hi1X, hi1Y, hi2X, hi2Y);
+  }
     /* If piece being dragged around board, must redraw that too */
     DrawDragPiece();
 
@@ -4395,11 +4979,8 @@ void XDrawPosition(w, repaint, board)
 /*
  * event handler for redrawing the board
  */
-void DrawPositionProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+DrawPositionProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     XDrawPosition(w, True, NULL);
 }
@@ -4415,13 +4996,11 @@ void DrawPositionProc(w, event, prms, nprms)
 //       move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
 //       and at the end FinishMove() to perform the move after optional promotion popups.
 //       For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
-void HandleUserMove(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+HandleUserMove (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     if (w != boardWidget || errorExitStatus != -1) return;
+    if(nprms) shiftKey = !strcmp(prms[0], "1");
 
     if (promotionUp) {
        if (event->type == ButtonPress) {
@@ -4440,548 +5019,114 @@ void HandleUserMove(w, event, prms, nprms)
     if(event->type == ButtonRelease) LeftClick(Release, event->xbutton.x, event->xbutton.y);
 }
 
-void AnimateUserMove (Widget w, XEvent * event,
-                     String * params, Cardinal * nParams)
+void
+AnimateUserMove (Widget w, XEvent *event, String *params, Cardinal *nParams)
 {
+    if(!PromoScroll(event->xmotion.x, event->xmotion.y))
     DragPieceMove(event->xmotion.x, event->xmotion.y);
 }
 
-Widget CommentCreate(name, text, mutable, callback, lines)
-     char *name, *text;
-     int /*Boolean*/ mutable;
-     XtCallbackProc callback;
-     int lines;
-{
-    Arg args[16];
-    Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
-    Dimension bw_width;
-    int j;
-
-    j = 0;
-    XtSetArg(args[j], XtNwidth, &bw_width);  j++;
-    XtGetValues(boardWidget, args, j);
-
-    j = 0;
-    XtSetArg(args[j], XtNresizable, True);  j++;
-#if TOPLEVEL
-    shell =
-      XtCreatePopupShell(name, topLevelShellWidgetClass,
-                        shellWidget, args, j);
-#else
-    shell =
-      XtCreatePopupShell(name, transientShellWidgetClass,
-                        shellWidget, args, j);
-#endif
-    layout =
-      XtCreateManagedWidget(layoutName, formWidgetClass, shell,
-                           layoutArgs, XtNumber(layoutArgs));
-    form =
-      XtCreateManagedWidget("form", formWidgetClass, layout,
-                           formArgs, XtNumber(formArgs));
-
-    j = 0;
-    if (mutable) {
-       XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;
-       XtSetArg(args[j], XtNuseStringInPlace, False);  j++;
-    }
-    XtSetArg(args[j], XtNstring, text);  j++;
-    XtSetArg(args[j], XtNtop, XtChainTop);  j++;
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
-    XtSetArg(args[j], XtNright, XtChainRight);  j++;
-    XtSetArg(args[j], XtNresizable, True);  j++;
-    XtSetArg(args[j], XtNwidth, bw_width);  j++; /*force wider than buttons*/
-    /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
-    XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways);  j++;
-    XtSetArg(args[j], XtNautoFill, True);  j++;
-    XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
-    edit =
-      XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
-
-    if (mutable) {
-       j = 0;
-       XtSetArg(args[j], XtNfromVert, edit);  j++;
-       XtSetArg(args[j], XtNtop, XtChainBottom); j++;
-       XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
-       XtSetArg(args[j], XtNleft, XtChainLeft); j++;
-       XtSetArg(args[j], XtNright, XtChainLeft); j++;
-       b_ok =
-         XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
-       XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
-
-       j = 0;
-       XtSetArg(args[j], XtNfromVert, edit);  j++;
-       XtSetArg(args[j], XtNfromHoriz, b_ok);  j++;
-       XtSetArg(args[j], XtNtop, XtChainBottom); j++;
-       XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
-       XtSetArg(args[j], XtNleft, XtChainLeft); j++;
-       XtSetArg(args[j], XtNright, XtChainLeft); j++;
-       b_cancel =
-         XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
-       XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
-
-       j = 0;
-       XtSetArg(args[j], XtNfromVert, edit);  j++;
-       XtSetArg(args[j], XtNfromHoriz, b_cancel);  j++;
-       XtSetArg(args[j], XtNtop, XtChainBottom); j++;
-       XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
-       XtSetArg(args[j], XtNleft, XtChainLeft); j++;
-       XtSetArg(args[j], XtNright, XtChainLeft); j++;
-       b_clear =
-         XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
-       XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
-    } else {
-       j = 0;
-       XtSetArg(args[j], XtNfromVert, edit);  j++;
-       XtSetArg(args[j], XtNtop, XtChainBottom); j++;
-       XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
-       XtSetArg(args[j], XtNleft, XtChainLeft); j++;
-       XtSetArg(args[j], XtNright, XtChainLeft); j++;
-       b_close =
-         XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
-       XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
-
-       j = 0;
-       XtSetArg(args[j], XtNfromVert, edit);  j++;
-       XtSetArg(args[j], XtNfromHoriz, b_close);  j++;
-       XtSetArg(args[j], XtNtop, XtChainBottom); j++;
-       XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
-       XtSetArg(args[j], XtNleft, XtChainLeft); j++;
-       XtSetArg(args[j], XtNright, XtChainLeft); j++;
-       b_edit =
-         XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
-       XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
-    }
-
-    XtRealizeWidget(shell);
-
-    if (commentX == -1) {
-       int xx, yy;
-       Window junk;
-       Dimension pw_height;
-       Dimension ew_height;
-
-       j = 0;
-       XtSetArg(args[j], XtNheight, &ew_height);  j++;
-       XtGetValues(edit, args, j);
-
-       j = 0;
-       XtSetArg(args[j], XtNheight, &pw_height);  j++;
-       XtGetValues(shell, args, j);
-       commentH = pw_height + (lines - 1) * ew_height;
-       commentW = bw_width - 16;
-
-       XSync(xDisplay, False);
-#ifdef NOTDEF
-       /* This code seems to tickle an X bug if it is executed too soon
-          after xboard starts up.  The coordinates get transformed as if
-          the main window was positioned at (0, 0).
-          */
-       XtTranslateCoords(shellWidget,
-                         (bw_width - commentW) / 2, 0 - commentH / 2,
-                         &commentX, &commentY);
-#else  /*!NOTDEF*/
-        XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
-                             RootWindowOfScreen(XtScreen(shellWidget)),
-                             (bw_width - commentW) / 2, 0 - commentH / 2,
-                             &xx, &yy, &junk);
-       commentX = xx;
-       commentY = yy;
-#endif /*!NOTDEF*/
-       if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
-    }
-
-    if(wpComment.width > 0) {
-      commentX = wpComment.x;
-      commentY = wpComment.y;
-      commentW = wpComment.width;
-      commentH = wpComment.height;
-    }
-
-    j = 0;
-    XtSetArg(args[j], XtNheight, commentH);  j++;
-    XtSetArg(args[j], XtNwidth, commentW);  j++;
-    XtSetArg(args[j], XtNx, commentX);  j++;
-    XtSetArg(args[j], XtNy, commentY);  j++;
-    XtSetValues(shell, args, j);
-    XtSetKeyboardFocus(shell, edit);
-
-    return shell;
-}
-
-/* Used for analysis window and ICS input window */
-Widget MiscCreate(name, text, mutable, callback, lines)
-     char *name, *text;
-     int /*Boolean*/ mutable;
-     XtCallbackProc callback;
-     int lines;
-{
-    Arg args[16];
-    Widget shell, layout, form, edit;
-    Position x, y;
-    Dimension bw_width, pw_height, ew_height, w, h;
-    int j;
-    int xx, yy;
-    Window junk;
-
-    j = 0;
-    XtSetArg(args[j], XtNresizable, True);  j++;
-#if TOPLEVEL
-    shell =
-      XtCreatePopupShell(name, topLevelShellWidgetClass,
-                        shellWidget, args, j);
-#else
-    shell =
-      XtCreatePopupShell(name, transientShellWidgetClass,
-                        shellWidget, args, j);
-#endif
-    layout =
-      XtCreateManagedWidget(layoutName, formWidgetClass, shell,
-                           layoutArgs, XtNumber(layoutArgs));
-    form =
-      XtCreateManagedWidget("form", formWidgetClass, layout,
-                           formArgs, XtNumber(formArgs));
-
-    j = 0;
-    if (mutable) {
-       XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;
-       XtSetArg(args[j], XtNuseStringInPlace, False);  j++;
-    }
-    XtSetArg(args[j], XtNstring, text);  j++;
-    XtSetArg(args[j], XtNtop, XtChainTop);  j++;
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
-    XtSetArg(args[j], XtNright, XtChainRight);  j++;
-    XtSetArg(args[j], XtNresizable, True);  j++;
-    /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
-    XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways);  j++;
-    XtSetArg(args[j], XtNautoFill, True);  j++;
-    XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
-    edit =
-      XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
-
-    XtRealizeWidget(shell);
-
-    j = 0;
-    XtSetArg(args[j], XtNwidth, &bw_width);  j++;
-    XtGetValues(boardWidget, args, j);
-
-    j = 0;
-    XtSetArg(args[j], XtNheight, &ew_height);  j++;
-    XtGetValues(edit, args, j);
-
-    j = 0;
-    XtSetArg(args[j], XtNheight, &pw_height);  j++;
-    XtGetValues(shell, args, j);
-    h = pw_height + (lines - 1) * ew_height;
-    w = bw_width - 16;
-
-    XSync(xDisplay, False);
-#ifdef NOTDEF
-    /* This code seems to tickle an X bug if it is executed too soon
-       after xboard starts up.  The coordinates get transformed as if
-       the main window was positioned at (0, 0).
-    */
-    XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
-#else  /*!NOTDEF*/
-    XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
-                         RootWindowOfScreen(XtScreen(shellWidget)),
-                         (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
-#endif /*!NOTDEF*/
-    x = xx;
-    y = yy;
-    if (y < 0) y = 0; /*avoid positioning top offscreen*/
-
-    j = 0;
-    XtSetArg(args[j], XtNheight, h);  j++;
-    XtSetArg(args[j], XtNwidth, w);  j++;
-    XtSetArg(args[j], XtNx, x);  j++;
-    XtSetArg(args[j], XtNy, y);  j++;
-    XtSetValues(shell, args, j);
-
-    return shell;
+void
+HandlePV (Widget w, XEvent * event, String * params, Cardinal * nParams)
+{   // [HGM] pv: walk PV
+    MovePV(event->xmotion.x, event->xmotion.y, lineGap + BOARD_HEIGHT * (squareSize + lineGap));
 }
 
-
 static int savedIndex;  /* gross that this is global */
 
-void EditCommentPopUp(index, title, text)
-     int index;
-     char *title, *text;
-{
-    Widget edit;
-    Arg args[16];
-    int j;
-
-    savedIndex = index;
-    if (text == NULL) text = "";
-
-    if (editShell == NULL) {
-       editShell =
-         CommentCreate(title, text, True, EditCommentCallback, 4);
-       XtRealizeWidget(editShell);
-       CatchDeleteWindow(editShell, "EditCommentPopDown");
-    } else {
-       edit = XtNameToWidget(editShell, "*form.text");
-       j = 0;
-       XtSetArg(args[j], XtNstring, text); j++;
-       XtSetValues(edit, args, j);
-       j = 0;
-       XtSetArg(args[j], XtNiconName, (XtArgVal) title);   j++;
-       XtSetArg(args[j], XtNtitle, (XtArgVal) title);      j++;
-       XtSetValues(editShell, args, j);
-    }
-
-    XtPopup(editShell, XtGrabNone);
-
-    editUp = True;
-    j = 0;
-    XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
-               args, j);
-}
-
-void EditCommentCallback(w, client_data, call_data)
-     Widget w;
-     XtPointer client_data, call_data;
+void
+CommentClick (Widget w, XEvent * event, String * params, Cardinal * nParams)
 {
-    String name, val;
-    Arg args[16];
-    int j;
-    Widget edit;
+       String val;
+       XawTextPosition index, dummy;
+       Arg arg;
 
-    j = 0;
-    XtSetArg(args[j], XtNlabel, &name);  j++;
-    XtGetValues(w, args, j);
-
-    if (strcmp(name, _("ok")) == 0) {
-       edit = XtNameToWidget(editShell, "*form.text");
-       j = 0;
-       XtSetArg(args[j], XtNstring, &val); j++;
-       XtGetValues(edit, args, j);
+       XawTextGetSelectionPos(w, &index, &dummy);
+       XtSetArg(arg, XtNstring, &val);
+       XtGetValues(w, &arg, 1);
        ReplaceComment(savedIndex, val);
-       EditCommentPopDown();
-    } else if (strcmp(name, _("cancel")) == 0) {
-       EditCommentPopDown();
-    } else if (strcmp(name, _("clear")) == 0) {
-       edit = XtNameToWidget(editShell, "*form.text");
-       XtCallActionProc(edit, "select-all", NULL, NULL, 0);
-       XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
-    }
+       if(savedIndex != currentMove) ToNrEvent(savedIndex);
+       LoadVariation( index, val ); // [HGM] also does the actual moving to it, now
 }
 
-void EditCommentPopDown()
+void
+EditCommentPopUp (int index, char *title, char *text)
 {
-    Arg args[16];
-    int j;
-
-    if (!editUp) return;
-    j = 0;
-    XtSetArg(args[j], XtNx, &commentX); j++;
-    XtSetArg(args[j], XtNy, &commentY); j++;
-    XtSetArg(args[j], XtNheight, &commentH); j++;
-    XtSetArg(args[j], XtNwidth, &commentW); j++;
-    XtGetValues(editShell, args, j);
-    XtPopdown(editShell);
-    editUp = False;
-    j = 0;
-    XtSetArg(args[j], XtNleftBitmap, None); j++;
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
-               args, j);
+    savedIndex = index;
+    if (text == NULL) text = "";
+    NewCommentPopup(title, text, index);
 }
 
-void ICSInputBoxPopUp()
+void
+ICSInputBoxPopUp ()
 {
-    Widget edit;
-    Arg args[16];
-    int j;
-    char *title = _("ICS Input");
-    XtTranslations tr;
-
-    if (ICSInputShell == NULL) {
-       ICSInputShell = MiscCreate(title, "", True, NULL, 1);
-       tr = XtParseTranslationTable(ICSInputTranslations);
-       edit = XtNameToWidget(ICSInputShell, "*form.text");
-       XtOverrideTranslations(edit, tr);
-       XtRealizeWidget(ICSInputShell);
-       CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
-
-    } else {
-       edit = XtNameToWidget(ICSInputShell, "*form.text");
-       j = 0;
-       XtSetArg(args[j], XtNstring, ""); j++;
-       XtSetValues(edit, args, j);
-       j = 0;
-       XtSetArg(args[j], XtNiconName, (XtArgVal) title);   j++;
-       XtSetArg(args[j], XtNtitle, (XtArgVal) title);      j++;
-       XtSetValues(ICSInputShell, args, j);
-    }
-
-    XtPopup(ICSInputShell, XtGrabNone);
-    XtSetKeyboardFocus(ICSInputShell, edit);
-
-    ICSInputBoxUp = True;
-    j = 0;
-    XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
-               args, j);
+    InputBoxPopup();
 }
 
-void ICSInputSendText()
+extern Option boxOptions[];
+
+void
+ICSInputSendText ()
 {
     Widget edit;
     int j;
     Arg args[16];
     String val;
 
-    edit = XtNameToWidget(ICSInputShell, "*form.text");
+    edit = boxOptions[0].handle;
     j = 0;
     XtSetArg(args[j], XtNstring, &val); j++;
     XtGetValues(edit, args, j);
+    SaveInHistory(val);
     SendMultiLineToICS(val);
     XtCallActionProc(edit, "select-all", NULL, NULL, 0);
     XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
 }
 
-void ICSInputBoxPopDown()
+void
+ICSInputBoxPopDown ()
 {
-    Arg args[16];
-    int j;
-
-    if (!ICSInputBoxUp) return;
-    j = 0;
-    XtPopdown(ICSInputShell);
-    ICSInputBoxUp = False;
-    j = 0;
-    XtSetArg(args[j], XtNleftBitmap, None); j++;
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
-               args, j);
+    PopDown(4);
 }
 
-void CommentPopUp(title, text)
-     char *title, *text;
+void
+CommentPopUp (char *title, char *text)
 {
-    Arg args[16];
-    int j;
-    Widget edit;
-
-    if (commentShell == NULL) {
-       commentShell =
-         CommentCreate(title, text, False, CommentCallback, 4);
-       XtRealizeWidget(commentShell);
-       CatchDeleteWindow(commentShell, "CommentPopDown");
-    } else {
-       edit = XtNameToWidget(commentShell, "*form.text");
-       j = 0;
-       XtSetArg(args[j], XtNstring, text); j++;
-       XtSetValues(edit, args, j);
-       j = 0;
-       XtSetArg(args[j], XtNiconName, (XtArgVal) title);   j++;
-       XtSetArg(args[j], XtNtitle, (XtArgVal) title);      j++;
-       XtSetValues(commentShell, args, j);
-    }
-
-    XtPopup(commentShell, XtGrabNone);
-    XSync(xDisplay, False);
-
-    commentUp = True;
+    savedIndex = currentMove; // [HGM] vari
+    NewCommentPopup(title, text, currentMove);
 }
 
-void CommentCallback(w, client_data, call_data)
-     Widget w;
-     XtPointer client_data, call_data;
+void
+CommentPopDown ()
 {
-    String name;
-    Arg args[16];
-    int j;
-
-    j = 0;
-    XtSetArg(args[j], XtNlabel, &name);  j++;
-    XtGetValues(w, args, j);
-
-    if (strcmp(name, _("close")) == 0) {
-       CommentPopDown();
-    } else if (strcmp(name, _("edit")) == 0) {
-       CommentPopDown();
-       EditCommentEvent();
-    }
+    PopDown(1);
 }
 
+static char *openName;
+FILE *openFP;
 
-void CommentPopDown()
+void
+DelayedLoad ()
 {
-    Arg args[16];
-    int j;
-
-    if (!commentUp) return;
-    j = 0;
-    XtSetArg(args[j], XtNx, &commentX); j++;
-    XtSetArg(args[j], XtNy, &commentY); j++;
-    XtSetArg(args[j], XtNwidth, &commentW); j++;
-    XtSetArg(args[j], XtNheight, &commentH); j++;
-    XtGetValues(commentShell, args, j);
-    XtPopdown(commentShell);
-    XSync(xDisplay, False);
-    commentUp = False;
+  (void) (*fileProc)(openFP, 0, openName);
 }
 
-void FileNamePopUp(label, def, proc, openMode)
-     char *label;
-     char *def;
-     FileProc proc;
-     char *openMode;
+void
+FileNamePopUp (char *label, char *def, char *filter, FileProc proc, char *openMode)
 {
-    Arg args[16];
-    Widget popup, layout, dialog, edit;
-    Window root, child;
-    int x, y, i;
-    int win_x, win_y;
-    unsigned int mask;
-
     fileProc = proc;           /* I can't see a way not */
     fileOpenMode = openMode;   /*   to use globals here */
-
-    i = 0;
-    XtSetArg(args[i], XtNresizable, True); i++;
-    XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
-    XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
-    fileNameShell = popup =
-      XtCreatePopupShell("File name prompt", transientShellWidgetClass,
-                        shellWidget, args, i);
-
-    layout =
-      XtCreateManagedWidget(layoutName, formWidgetClass, popup,
-                           layoutArgs, XtNumber(layoutArgs));
-
-    i = 0;
-    XtSetArg(args[i], XtNlabel, label); i++;
-    XtSetArg(args[i], XtNvalue, def); i++;
-    XtSetArg(args[i], XtNborderWidth, 0); i++;
-    dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
-                                  layout, args, i);
-
-    XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
-    XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
-                      (XtPointer) dialog);
-
-    XtRealizeWidget(popup);
-    CatchDeleteWindow(popup, "FileNamePopDown");
-
-    XQueryPointer(xDisplay, xBoardWindow, &root, &child,
-                 &x, &y, &win_x, &win_y, &mask);
-
-    XtSetArg(args[0], XtNx, x - 10);
-    XtSetArg(args[1], XtNy, y - 30);
-    XtSetValues(popup, args, 2);
-
-    XtPopup(popup, XtGrabExclusive);
-    filenameUp = True;
-
-    edit = XtNameToWidget(dialog, "*value");
-    XtSetKeyboardFocus(popup, edit);
+    {   // [HGM] use file-selector dialog stolen from Ghostview
+       int index; // this is not supported yet
+       if(openFP = XsraSelFile(shellWidget, label, NULL, NULL, _("could not open: "),
+                          (def[0] ? def : NULL), filter, openMode, NULL, &openName))
+         // [HGM] delay to give expose event opportunity to redraw board after browser-dialog popdown before lengthy load starts
+         ScheduleDelayedEvent(&DelayedLoad, 50);
+    }
 }
 
-void FileNamePopDown()
+void
+FileNamePopDown ()
 {
     if (!filenameUp) return;
     XtPopdown(fileNameShell);
@@ -4990,9 +5135,8 @@ void FileNamePopDown()
     ModeHighlight();
 }
 
-void FileNameCallback(w, client_data, call_data)
-     Widget w;
-     XtPointer client_data, call_data;
+void
+FileNameCallback (Widget w, XtPointer client_data, XtPointer call_data)
 {
     String name;
     Arg args[16];
@@ -5008,11 +5152,8 @@ void FileNameCallback(w, client_data, call_data)
     FileNameAction(w, NULL, NULL, NULL);
 }
 
-void FileNameAction(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+FileNameAction (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     char buf[MSG_SIZ];
     String name;
@@ -5023,7 +5164,7 @@ void FileNameAction(w, event, prms, nprms)
     name = XawDialogGetValueString(w = XtParent(w));
 
     if ((name != NULL) && (*name != NULLCHAR)) {
-       strcpy(buf, name);
+        safeStrCpy(buf, name, sizeof(buf)/sizeof(buf[0]) );
        XtPopdown(w = XtParent(XtParent(w)));
        XtDestroyWidget(w);
        filenameUp = False;
@@ -5057,13 +5198,15 @@ void FileNameAction(w, event, prms, nprms)
     ModeHighlight();
 }
 
-void PromotionPopUp()
+void
+PromotionPopUp ()
 {
     Arg args[16];
     Widget dialog, layout;
     Position x, y;
     Dimension bw_width, pw_width;
     int j;
+    char *PromoChars = "wglcqrbnkac+=\0";
 
     j = 0;
     XtSetArg(args[j], XtNwidth, &bw_width); j++;
@@ -5086,36 +5229,34 @@ void PromotionPopUp()
                                   layout, args, j);
 
   if(gameInfo.variant != VariantShogi) {
-    XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
-                      (XtPointer) dialog);
-    XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
-                      (XtPointer) dialog);
-    XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
-                      (XtPointer) dialog);
-    XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
-                      (XtPointer) dialog);
+   if(gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove)) {
+      XawDialogAddButton(dialog, _("Warlord"), PromotionCallback, PromoChars + 0);
+      XawDialogAddButton(dialog, _("General"), PromotionCallback, PromoChars + 1);
+      XawDialogAddButton(dialog, _("Lieutenant"), PromotionCallback, PromoChars + 2);
+      XawDialogAddButton(dialog, _("Captain"), PromotionCallback, PromoChars + 3);
+    } else {
+    XawDialogAddButton(dialog, _("Queen"), PromotionCallback, PromoChars + 4);
+    XawDialogAddButton(dialog, _("Rook"), PromotionCallback, PromoChars + 5);
+    XawDialogAddButton(dialog, _("Bishop"), PromotionCallback, PromoChars + 6);
+    XawDialogAddButton(dialog, _("Knight"), PromotionCallback, PromoChars + 7);
+    }
     if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
+        gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove) ||
         gameInfo.variant == VariantGiveaway) {
-      XawDialogAddButton(dialog, _("King"), PromotionCallback,
-                        (XtPointer) dialog);
+      XawDialogAddButton(dialog, _("King"), PromotionCallback, PromoChars + 8);
     }
-    if(gameInfo.variant == VariantCapablanca || 
-       gameInfo.variant == VariantGothic || 
+    if(gameInfo.variant == VariantCapablanca ||
+       gameInfo.variant == VariantGothic ||
        gameInfo.variant == VariantCapaRandom) {
-      XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
-                        (XtPointer) dialog);
-      XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
-                        (XtPointer) dialog);
+      XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback, PromoChars + 9);
+      XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback, PromoChars + 10);
     }
   } else // [HGM] shogi
   {
-      XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
-                        (XtPointer) dialog);
-      XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
-                        (XtPointer) dialog);
+      XawDialogAddButton(dialog, _("Promote"), PromotionCallback, PromoChars + 11);
+      XawDialogAddButton(dialog, _("Defer"), PromotionCallback, PromoChars + 12);
   }
-    XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
-                      (XtPointer) dialog);
+    XawDialogAddButton(dialog, _("cancel"), PromotionCallback, PromoChars + 13);
 
     XtRealizeWidget(promotionShell);
     CatchDeleteWindow(promotionShell, "PromotionPopDown");
@@ -5139,7 +5280,8 @@ void PromotionPopUp()
     promotionUp = True;
 }
 
-void PromotionPopDown()
+void
+PromotionPopDown ()
 {
     if (!promotionUp) return;
     XtPopdown(promotionShell);
@@ -5147,35 +5289,20 @@ void PromotionPopDown()
     promotionUp = False;
 }
 
-void PromotionCallback(w, client_data, call_data)
-     Widget w;
-     XtPointer client_data, call_data;
+void
+PromotionCallback (Widget w, XtPointer client_data, XtPointer call_data)
 {
-    String name;
-    Arg args[16];
-    int promoChar;
-
-    XtSetArg(args[0], XtNlabel, &name);
-    XtGetValues(w, args, 1);
+    int promoChar = * (const char *) client_data;
 
     PromotionPopDown();
 
     if (fromX == -1) return;
 
-    if (strcmp(name, _("cancel")) == 0) {
+    if (! promoChar) {
        fromX = fromY = -1;
        ClearHighlights();
        return;
-    } else if (strcmp(name, _("Knight")) == 0) {
-       promoChar = 'n';
-    } else if (strcmp(name, _("Promote")) == 0) {
-       promoChar = '+';
-    } else if (strcmp(name, _("Defer")) == 0) {
-       promoChar = '=';
-    } else {
-       promoChar = ToLower(name[0]);
     }
-
     UserMoveEvent(fromX, fromY, toX, toY, promoChar);
 
     if (!appData.highlightLastMove || gotPremove) ClearHighlights();
@@ -5184,29 +5311,28 @@ void PromotionCallback(w, client_data, call_data)
 }
 
 
-void ErrorCallback(w, client_data, call_data)
-     Widget w;
-     XtPointer client_data, call_data;
+void
+ErrorCallback (Widget w, XtPointer client_data, XtPointer call_data)
 {
-    errorUp = False;
+    dialogError = errorUp = False;
     XtPopdown(w = XtParent(XtParent(XtParent(w))));
     XtDestroyWidget(w);
     if (errorExitStatus != -1) ExitEvent(errorExitStatus);
 }
 
 
-void ErrorPopDown()
+void
+ErrorPopDown ()
 {
     if (!errorUp) return;
-    errorUp = False;
+    dialogError = errorUp = False;
     XtPopdown(errorShell);
     XtDestroyWidget(errorShell);
     if (errorExitStatus != -1) ExitEvent(errorExitStatus);
 }
 
-void ErrorPopUp(title, label, modal)
-     char *title, *label;
-     int modal;
+void
+ErrorPopUp (char *title, char *label, int modal)
 {
     Arg args[16];
     Widget dialog, layout;
@@ -5222,7 +5348,7 @@ void ErrorPopUp(title, label, modal)
     XtSetArg(args[i], XtNtitle, title); i++;
     errorShell =
       XtCreatePopupShell("errorpopup", transientShellWidgetClass,
-                        shellWidget, args, i);
+                        shellUp[0] ? (dialogError = modal = TRUE, shells[0]) : shellWidget, args, i);
     layout =
       XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
                            layoutArgs, XtNumber(layoutArgs));
@@ -5274,7 +5400,9 @@ void ErrorPopUp(title, label, modal)
 
 /* Disable all user input other than deleting the window */
 static int frozen = 0;
-void FreezeUI()
+
+void
+FreezeUI ()
 {
   if (frozen) return;
   /* Grab by a widget that doesn't accept input */
@@ -5283,15 +5411,16 @@ void FreezeUI()
 }
 
 /* Undo a FreezeUI */
-void ThawUI()
+void
+ThawUI ()
 {
   if (!frozen) return;
   XtRemoveGrab(messageWidget);
   frozen = 0;
 }
 
-char *ModeToWidgetName(mode)
-     GameMode mode;
+char *
+ModeToWidgetName (GameMode mode)
 {
     switch (mode) {
       case BeginningOfGame:
@@ -5332,7 +5461,8 @@ char *ModeToWidgetName(mode)
     }
 }
 
-void ModeHighlight()
+void
+ModeHighlight ()
 {
     Arg args[16];
     static int oldPausing = FALSE;
@@ -5379,6 +5509,8 @@ void ModeHighlight()
        XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
     }
     oldmode = gameMode;
+    XtSetArg(args[0], XtNleftBitmap, matchMode && matchGame < appData.matchGames ? xMarkPixmap : None);
+    XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Machine Match"), args, 1);
 
     /* Maybe all the enables should be handled here, not just this one */
     XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
@@ -5389,19 +5521,14 @@ void ModeHighlight()
 /*
  * Button/menu procedures
  */
-void ResetProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+ResetProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     ResetGameEvent();
 }
 
-int LoadGamePopUp(f, gameNumber, title)
-     FILE *f;
-     int gameNumber;
-     char *title;
+int
+LoadGamePopUp (FILE *f, int gameNumber, char *title)
 {
     cmailMsgLoaded = FALSE;
     if (gameNumber == 0) {
@@ -5419,131 +5546,97 @@ int LoadGamePopUp(f, gameNumber, title)
     return LoadGame(f, gameNumber, title, FALSE);
 }
 
-void LoadGameProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+LoadGameProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
        Reset(FALSE, TRUE);
     }
-    FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
+    FileNamePopUp(_("Load game file name?"), "", ".pgn .game", LoadGamePopUp, "rb");
 }
 
-void LoadNextGameProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+LoadNextGameProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     ReloadGame(1);
 }
 
-void LoadPrevGameProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+LoadPrevGameProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     ReloadGame(-1);
 }
 
-void ReloadGameProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+ReloadGameProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     ReloadGame(0);
 }
 
-void LoadNextPositionProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+LoadNextPositionProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     ReloadPosition(1);
 }
 
-void LoadPrevPositionProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+LoadPrevPositionProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     ReloadPosition(-1);
 }
 
-void ReloadPositionProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+ReloadPositionProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     ReloadPosition(0);
 }
 
-void LoadPositionProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+LoadPositionProc(Widget w, XEvent *event, String *prms, Cardinal *nprms) 
 {
     if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
        Reset(FALSE, TRUE);
     }
-    FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
+    FileNamePopUp(_("Load position file name?"), "", ".fen .epd .pos", LoadPosition, "rb");
 }
 
-void SaveGameProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+SaveGameProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     FileNamePopUp(_("Save game file name?"),
                  DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
+                 appData.oldSaveStyle ? ".game" : ".pgn",
                  SaveGame, "a");
 }
 
-void SavePositionProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+SavePositionProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     FileNamePopUp(_("Save position file name?"),
                  DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
+                 appData.oldSaveStyle ? ".pos" : ".fen",
                  SavePosition, "a");
 }
 
-void ReloadCmailMsgProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+ReloadCmailMsgProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     ReloadCmailMsgEvent(FALSE);
 }
 
-void MailMoveProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+MailMoveProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     MailMoveEvent();
 }
 
 /* this variable is shared between CopyPositionProc and SendPositionSelection */
-static char *selected_fen_position=NULL;
+char *selected_fen_position=NULL;
 
-static Boolean
-SendPositionSelection(Widget w, Atom *selection, Atom *target,
-                Atom *type_return, XtPointer *value_return,
-                unsigned long *length_return, int *format_return)
+Boolean
+SendPositionSelection (Widget w, Atom *selection, Atom *target,
+                      Atom *type_return, XtPointer *value_return,
+                      unsigned long *length_return, int *format_return)
 {
   char *selection_tmp;
 
@@ -5553,7 +5646,7 @@ SendPositionSelection(Widget w, Atom *selection, Atom *target,
      * automatically call XtFree on the value returned.  So have to
      * make a copy of it allocated with XtMalloc */
     selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
-    strcpy(selection_tmp, selected_fen_position);
+    safeStrCpy(selection_tmp, selected_fen_position, strlen(selected_fen_position)+16 );
 
     *value_return=selection_tmp;
     *length_return=strlen(selection_tmp);
@@ -5567,11 +5660,19 @@ SendPositionSelection(Widget w, Atom *selection, Atom *target,
     *value_return = targets_tmp;
     *type_return = XA_ATOM;
     *length_return = 2;
+#if 0
+    // This code leads to a read of value_return out of bounds on 64-bit systems.
+    // Other code which I have seen always sets *format_return to 32 independent of
+    // sizeof(Atom) without adjusting *length_return. For instance see TextConvertSelection()
+    // at http://cgit.freedesktop.org/xorg/lib/libXaw/tree/src/Text.c -- BJ
     *format_return = 8 * sizeof(Atom);
     if (*format_return > 32) {
       *length_return *= *format_return / 32;
       *format_return = 32;
     }
+#else
+    *format_return = 32;
+#endif
     return True;
   } else {
     return False;
@@ -5581,17 +5682,15 @@ SendPositionSelection(Widget w, Atom *selection, Atom *target,
 /* note: when called from menu all parameters are NULL, so no clue what the
  * Widget which was clicked on was, or what the click event was
  */
-void CopyPositionProc(w, event, prms, nprms)
-  Widget w;
-  XEvent *event;
-  String *prms;
-  Cardinal *nprms;
-  {
+void
+CopyPositionProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
+{
     /*
      * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
      * have a notion of a position that is selected but not copied.
      * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki
      */
+    if(gameMode == EditPosition) EditPositionDone(TRUE);
     if (selected_fen_position) free(selected_fen_position);
     selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
     if (!selected_fen_position) return;
@@ -5605,12 +5704,18 @@ void CopyPositionProc(w, event, prms, nprms)
                   SendPositionSelection,
                   NULL/* lose_ownership_proc */ ,
                   NULL/* transfer_done_proc */);
-  }
+}
+
+void
+CopyFENToClipboard ()
+{ // wrapper to make call from back-end possible
+  CopyPositionProc(NULL, NULL, NULL, NULL);
+}
 
 /* function called when the data to Paste is ready */
 static void
-PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
-          Atom *type, XtPointer value, unsigned long *len, int *format)
+PastePositionCB (Widget w, XtPointer client_data, Atom *selection,
+                Atom *type, XtPointer value, unsigned long *len, int *format)
 {
   char *fenstr=value;
   if (value==NULL || *len==0) return; /* nothing had been selected to copy */
@@ -5627,7 +5732,7 @@ void PastePositionProc(w, event, prms, nprms)
   String *prms;
   Cardinal *nprms;
 {
-    XtGetSelectionValue(menuBarWidget, 
+    XtGetSelectionValue(menuBarWidget,
       appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
       /* (XtSelectionCallbackProc) */ PastePositionCB,
       NULL, /* client_data passed to PastePositionCB */
@@ -5641,9 +5746,9 @@ void PastePositionProc(w, event, prms, nprms)
 }
 
 static Boolean
-SendGameSelection(Widget w, Atom *selection, Atom *target,
-                 Atom *type_return, XtPointer *value_return,
-                 unsigned long *length_return, int *format_return)
+SendGameSelection (Widget w, Atom *selection, Atom *target,
+                  Atom *type_return, XtPointer *value_return,
+                  unsigned long *length_return, int *format_return)
 {
   char *selection_tmp;
 
@@ -5657,6 +5762,7 @@ SendGameSelection(Widget w, Atom *selection, Atom *target,
     rewind(f);
     selection_tmp = XtMalloc(len + 1);
     count = fread(selection_tmp, 1, len, f);
+    fclose(f);
     if (len != count) {
       XtFree(selection_tmp);
       return False;
@@ -5674,31 +5780,28 @@ SendGameSelection(Widget w, Atom *selection, Atom *target,
     *value_return = targets_tmp;
     *type_return = XA_ATOM;
     *length_return = 2;
+#if 0
+    // This code leads to a read of value_return out of bounds on 64-bit systems.
+    // Other code which I have seen always sets *format_return to 32 independent of
+    // sizeof(Atom) without adjusting *length_return. For instance see TextConvertSelection()
+    // at http://cgit.freedesktop.org/xorg/lib/libXaw/tree/src/Text.c -- BJ
     *format_return = 8 * sizeof(Atom);
     if (*format_return > 32) {
       *length_return *= *format_return / 32;
       *format_return = 32;
     }
+#else
+    *format_return = 32;
+#endif
     return True;
   } else {
     return False;
   }
 }
 
-/* note: when called from menu all parameters are NULL, so no clue what the
- * Widget which was clicked on was, or what the click event was
- */
-void CopyGameProc(w, event, prms, nprms)
-  Widget w;
-  XEvent *event;
-  String *prms;
-  Cardinal *nprms;
+void
+CopySomething ()
 {
-  int ret;
-
-  ret = SaveGameToFile(gameCopyFilename, FALSE);
-  if (!ret) return;
-
   /*
    * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
    * have a notion of a game that is selected but not copied.
@@ -5716,10 +5819,31 @@ void CopyGameProc(w, event, prms, nprms)
                 NULL/* transfer_done_proc */);
 }
 
+/* note: when called from menu all parameters are NULL, so no clue what the
+ * Widget which was clicked on was, or what the click event was
+ */
+void
+CopyGameProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
+{
+  int ret;
+
+  ret = SaveGameToFile(gameCopyFilename, FALSE);
+  if (!ret) return;
+
+  CopySomething();
+}
+
+void
+CopyGameListProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
+{
+  if(!SaveGameListAsText(fopen(gameCopyFilename, "w"))) return;
+  CopySomething();
+}
+
 /* function called when the data to Paste is ready */
 static void
-PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
-           Atom *type, XtPointer value, unsigned long *len, int *format)
+PasteGameCB (Widget w, XtPointer client_data, Atom *selection,
+            Atom *type, XtPointer value, unsigned long *len, int *format)
 {
   FILE* f;
   if (value == NULL || *len == 0) {
@@ -5738,11 +5862,8 @@ PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
 
 /* called when Paste Game button is pressed,
  * all parameters will be NULL */
-void PasteGameProc(w, event, prms, nprms)
-  Widget w;
-  XEvent *event;
-  String *prms;
-  Cardinal *nprms;
+void
+PasteGameProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     XtGetSelectionValue(menuBarWidget,
       appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
@@ -5758,54 +5879,39 @@ void PasteGameProc(w, event, prms, nprms)
 }
 
 
-void AutoSaveGame()
+void
+AutoSaveGame ()
 {
     SaveGameProc(NULL, NULL, NULL, NULL);
 }
 
 
-void QuitProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+QuitProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     ExitEvent(0);
 }
 
-void PauseProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+PauseProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     PauseEvent();
 }
 
-
-void MachineBlackProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+MachineBlackProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     MachineBlackEvent();
 }
 
-void MachineWhiteProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+MachineWhiteProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     MachineWhiteEvent();
 }
 
-void AnalyzeModeProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+AnalyzeModeProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     char buf[MSG_SIZ];
 
@@ -5817,7 +5923,7 @@ void AnalyzeModeProc(w, event, prms, nprms)
     /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
     if (appData.icsActive) {
         if (gameMode != IcsObserving) {
-            sprintf(buf,_("You are not observing a game"));
+         snprintf(buf, MSG_SIZ, _("You are not observing a game"));
             DisplayError(buf, 0);
             /* secure check */
             if (appData.icsEngineAnalyze) {
@@ -5838,17 +5944,16 @@ void AnalyzeModeProc(w, event, prms, nprms)
         if (appData.debugMode)
             fprintf(debugFP, _("ICS engine analyze starting... \n"));
     }
+#ifndef OPTIONSDIALOG
     if (!appData.showThinking)
       ShowThinkingProc(w,event,prms,nprms);
+#endif
 
     AnalyzeModeEvent();
 }
 
-void AnalyzeFileProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+AnalyzeFileProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     if (!first.analysisSupport) {
       char buf[MSG_SIZ];
@@ -5856,372 +5961,364 @@ void AnalyzeFileProc(w, event, prms, nprms)
       DisplayError(buf, 0);
       return;
     }
-    Reset(FALSE, TRUE);
-
+//    Reset(FALSE, TRUE);
+#ifndef OPTIONSDIALOG
     if (!appData.showThinking)
       ShowThinkingProc(w,event,prms,nprms);
-
+#endif
     AnalyzeFileEvent();
-    FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
+//    FileNamePopUp(_("File to analyze"), "", ".pgn .game", LoadGamePopUp, "rb");
     AnalysisPeriodicEvent(1);
 }
 
-void TwoMachinesProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+TwoMachinesProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     TwoMachinesEvent();
 }
 
-void IcsClientProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+MatchProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
+{
+    MatchEvent(2);
+}
+
+void
+IcsClientProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     IcsClientEvent();
 }
 
-void EditGameProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+EditGameProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     EditGameEvent();
 }
 
-void EditPositionProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+EditPositionProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     EditPositionEvent();
 }
 
-void TrainingProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+TrainingProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     TrainingEvent();
 }
 
-void EditCommentProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+EditCommentProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
-    if (editUp) {
-       EditCommentPopDown();
-    } else {
+    Arg args[5];
+    int j;
+    if (PopDown(1)) { // popdown succesful
+       j = 0;
+       XtSetArg(args[j], XtNleftBitmap, None); j++;
+       XtSetValues(XtNameToWidget(menuBarWidget, "menuEdit.Edit Comment"), args, j);
+       XtSetValues(XtNameToWidget(menuBarWidget, "menuView.Show Comments"), args, j);
+    } else // was not up
        EditCommentEvent();
-    }
 }
 
-void IcsInputBoxProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+IcsInputBoxProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
-    if (ICSInputBoxUp) {
-       ICSInputBoxPopDown();
-    } else {
-       ICSInputBoxPopUp();
-    }
+    if (!PopDown(4)) ICSInputBoxPopUp();
 }
 
-void AcceptProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+AcceptProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     AcceptEvent();
 }
 
-void DeclineProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+DeclineProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     DeclineEvent();
 }
 
-void RematchProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+RematchProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     RematchEvent();
 }
 
-void CallFlagProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+CallFlagProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     CallFlagEvent();
 }
 
-void DrawProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+DrawProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     DrawEvent();
 }
 
-void AbortProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+AbortProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     AbortEvent();
 }
 
-void AdjournProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+AdjournProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     AdjournEvent();
 }
 
-void ResignProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+ResignProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     ResignEvent();
 }
 
-void AdjuWhiteProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+AdjuWhiteProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     UserAdjudicationEvent(+1);
 }
 
-void AdjuBlackProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+AdjuBlackProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     UserAdjudicationEvent(-1);
 }
 
-void AdjuDrawProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+AdjuDrawProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     UserAdjudicationEvent(0);
 }
 
-void EnterKeyProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+EnterKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
-    if (ICSInputBoxUp == True)
+    if (shellUp[4] == True)
       ICSInputSendText();
 }
 
-void StopObservingProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+UpKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
+{   // [HGM] input: let up-arrow recall previous line from history
+    Widget edit;
+    int j;
+    Arg args[16];
+    String val;
+    XawTextBlock t;
+
+    if (!shellUp[4]) return;
+    edit = boxOptions[0].handle;
+    j = 0;
+    XtSetArg(args[j], XtNstring, &val); j++;
+    XtGetValues(edit, args, j);
+    val = PrevInHistory(val);
+    XtCallActionProc(edit, "select-all", NULL, NULL, 0);
+    XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
+    if(val) {
+       t.ptr = val; t.firstPos = 0; t.length = strlen(val); t.format = XawFmt8Bit;
+       XawTextReplace(edit, 0, 0, &t);
+       XawTextSetInsertionPoint(edit, 9999);
+    }
+}
+
+void
+DownKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
+{   // [HGM] input: let down-arrow recall next line from history
+    Widget edit;
+    String val;
+    XawTextBlock t;
+
+    if (!shellUp[4]) return;
+    edit = boxOptions[0].handle;
+    val = NextInHistory();
+    XtCallActionProc(edit, "select-all", NULL, NULL, 0);
+    XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
+    if(val) {
+       t.ptr = val; t.firstPos = 0; t.length = strlen(val); t.format = XawFmt8Bit;
+       XawTextReplace(edit, 0, 0, &t);
+       XawTextSetInsertionPoint(edit, 9999);
+    }
+}
+
+void
+StopObservingProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     StopObservingEvent();
 }
 
-void StopExaminingProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+StopExaminingProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     StopExaminingEvent();
 }
 
+void
+UploadProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
+{
+    UploadGameEvent();
+}
+
 
-void ForwardProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+ForwardProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     ForwardEvent();
 }
 
 
-void BackwardProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+BackwardProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     BackwardEvent();
 }
 
-void ToStartProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+TempBackwardProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
+{
+       if (!TempBackwardActive) {
+               TempBackwardActive = True;
+               BackwardEvent();
+       }
+}
+
+void
+TempForwardProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
+{
+       /* Check to see if triggered by a key release event for a repeating key.
+        * If so the next queued event will be a key press of the same key at the same time */
+       if (XEventsQueued(xDisplay, QueuedAfterReading)) {
+               XEvent next;
+               XPeekEvent(xDisplay, &next);
+               if (next.type == KeyPress && next.xkey.time == event->xkey.time &&
+                       next.xkey.keycode == event->xkey.keycode)
+                               return;
+       }
+    ForwardEvent();
+       TempBackwardActive = False;
+}
+
+void
+ToStartProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     ToStartEvent();
 }
 
-void ToEndProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+ToEndProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     ToEndEvent();
 }
 
-void RevertProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+RevertProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
-    RevertEvent();
+    RevertEvent(False);
 }
 
-void TruncateGameProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+AnnotateProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
+{
+    RevertEvent(True);
+}
+
+void
+TruncateGameProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     TruncateGameEvent();
 }
-void RetractMoveProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+
+void
+RetractMoveProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     RetractMoveEvent();
 }
 
-void MoveNowProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+MoveNowProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     MoveNowEvent();
 }
 
+void
+FlipViewProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
+{
+    flipView = !flipView;
+    DrawPosition(True, NULL);
+}
 
-void AlwaysQueenProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+PonderNextMoveProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
-    appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
-
-    if (appData.alwaysPromoteToQueen) {
+    PonderNextMoveEvent(!appData.ponderNextMove);
+#ifndef OPTIONSDIALOG
+    if (appData.ponderNextMove) {
        XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
     } else {
        XtSetArg(args[0], XtNleftBitmap, None);
     }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
+    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
                args, 1);
+#endif
 }
 
-void AnimateDraggingProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+#ifndef OPTIONSDIALOG
+void
+AlwaysQueenProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
-    appData.animateDragging = !appData.animateDragging;
+    appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
 
-    if (appData.animateDragging) {
+    if (appData.alwaysPromoteToQueen) {
        XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
-        CreateAnimVars();
     } else {
        XtSetArg(args[0], XtNleftBitmap, None);
     }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
+    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
                args, 1);
 }
 
-void AnimateMovingProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+AnimateDraggingProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
-    appData.animate = !appData.animate;
+    appData.animateDragging = !appData.animateDragging;
 
-    if (appData.animate) {
+    if (appData.animateDragging) {
        XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
         CreateAnimVars();
     } else {
        XtSetArg(args[0], XtNleftBitmap, None);
     }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
+    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
                args, 1);
 }
 
-void AutocommProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+AnimateMovingProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
-    appData.autoComment = !appData.autoComment;
+    appData.animate = !appData.animate;
 
-    if (appData.autoComment) {
+    if (appData.animate) {
        XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+        CreateAnimVars();
     } else {
        XtSetArg(args[0], XtNleftBitmap, None);
     }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
+    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
                args, 1);
 }
 
-
-void AutoflagProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+AutoflagProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
@@ -6236,11 +6333,8 @@ void AutoflagProc(w, event, prms, nprms)
                args, 1);
 }
 
-void AutoflipProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+AutoflipProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
@@ -6255,68 +6349,8 @@ void AutoflipProc(w, event, prms, nprms)
                args, 1);
 }
 
-void AutobsProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
-{
-    Arg args[16];
-
-    appData.autoObserve = !appData.autoObserve;
-
-    if (appData.autoObserve) {
-       XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
-    } else {
-       XtSetArg(args[0], XtNleftBitmap, None);
-    }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
-               args, 1);
-}
-
-void AutoraiseProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
-{
-    Arg args[16];
-
-    appData.autoRaiseBoard = !appData.autoRaiseBoard;
-
-    if (appData.autoRaiseBoard) {
-       XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
-    } else {
-       XtSetArg(args[0], XtNleftBitmap, None);
-    }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
-               args, 1);
-}
-
-void AutosaveProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
-{
-    Arg args[16];
-
-    appData.autoSaveGames = !appData.autoSaveGames;
-
-    if (appData.autoSaveGames) {
-       XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
-    } else {
-       XtSetArg(args[0], XtNleftBitmap, None);
-    }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
-               args, 1);
-}
-
-void BlindfoldProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+BlindfoldProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
@@ -6333,11 +6367,8 @@ void BlindfoldProc(w, event, prms, nprms)
     DrawPosition(True, NULL);
 }
 
-void TestLegalityProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+TestLegalityProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
@@ -6353,11 +6384,8 @@ void TestLegalityProc(w, event, prms, nprms)
 }
 
 
-void FlashMovesProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+FlashMovesProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
@@ -6376,81 +6404,59 @@ void FlashMovesProc(w, event, prms, nprms)
                args, 1);
 }
 
-void FlipViewProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
-{
-    flipView = !flipView;
-    DrawPosition(True, NULL);
-}
-
-void GetMoveListProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+#if HIGHDRAG
+void
+HighlightDraggingProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
-    appData.getMoveList = !appData.getMoveList;
+    appData.highlightDragging = !appData.highlightDragging;
 
-    if (appData.getMoveList) {
+    if (appData.highlightDragging) {
        XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
-       GetMoveListEvent();
     } else {
        XtSetArg(args[0], XtNleftBitmap, None);
     }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
-               args, 1);
+    XtSetValues(XtNameToWidget(menuBarWidget,
+                              "menuOptions.Highlight Dragging"), args, 1);
 }
+#endif
 
-#if HIGHDRAG
-void HighlightDraggingProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+HighlightLastMoveProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
-    appData.highlightDragging = !appData.highlightDragging;
+    appData.highlightLastMove = !appData.highlightLastMove;
 
-    if (appData.highlightDragging) {
+    if (appData.highlightLastMove) {
        XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
     } else {
        XtSetArg(args[0], XtNleftBitmap, None);
     }
     XtSetValues(XtNameToWidget(menuBarWidget,
-                              "menuOptions.Highlight Dragging"), args, 1);
+                              "menuOptions.Highlight Last Move"), args, 1);
 }
-#endif
 
-void HighlightLastMoveProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+HighlightArrowProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
-    appData.highlightLastMove = !appData.highlightLastMove;
+    appData.highlightMoveWithArrow = !appData.highlightMoveWithArrow;
 
-    if (appData.highlightLastMove) {
+    if (appData.highlightMoveWithArrow) {
        XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
     } else {
        XtSetArg(args[0], XtNleftBitmap, None);
     }
     XtSetValues(XtNameToWidget(menuBarWidget,
-                              "menuOptions.Highlight Last Move"), args, 1);
+                              "menuOptions.Arrow"), args, 1);
 }
 
-void IcsAlarmProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+#if 0
+void
+IcsAlarmProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
@@ -6464,12 +6470,10 @@ void IcsAlarmProc(w, event, prms, nprms)
     XtSetValues(XtNameToWidget(menuBarWidget,
                               "menuOptions.ICS Alarm"), args, 1);
 }
+#endif
 
-void MoveSoundProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+MoveSoundProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
@@ -6484,31 +6488,24 @@ void MoveSoundProc(w, event, prms, nprms)
                args, 1);
 }
 
-
-void OldSaveStyleProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+OneClickProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
-    appData.oldSaveStyle = !appData.oldSaveStyle;
+    appData.oneClick = !appData.oneClick;
 
-    if (appData.oldSaveStyle) {
+    if (appData.oneClick) {
        XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
     } else {
        XtSetArg(args[0], XtNleftBitmap, None);
     }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
+    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.OneClick"),
                args, 1);
 }
 
-void PeriodicUpdatesProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+PeriodicUpdatesProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
@@ -6523,30 +6520,8 @@ void PeriodicUpdatesProc(w, event, prms, nprms)
                args, 1);
 }
 
-void PonderNextMoveProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
-{
-    Arg args[16];
-
-    PonderNextMoveEvent(!appData.ponderNextMove);
-
-    if (appData.ponderNextMove) {
-       XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
-    } else {
-       XtSetArg(args[0], XtNleftBitmap, None);
-    }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
-               args, 1);
-}
-
-void PopupExitMessageProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+PopupExitMessageProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
@@ -6561,11 +6536,8 @@ void PopupExitMessageProc(w, event, prms, nprms)
                               "menuOptions.Popup Exit Message"), args, 1);
 }
 
-void PopupMoveErrorsProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+PopupMoveErrorsProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
@@ -6580,11 +6552,9 @@ void PopupMoveErrorsProc(w, event, prms, nprms)
                args, 1);
 }
 
-void PremoveProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+#if 0
+void
+PremoveProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
@@ -6598,31 +6568,10 @@ void PremoveProc(w, event, prms, nprms)
     XtSetValues(XtNameToWidget(menuBarWidget,
                               "menuOptions.Premove"), args, 1);
 }
+#endif
 
-void QuietPlayProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
-{
-    Arg args[16];
-
-    appData.quietPlay = !appData.quietPlay;
-
-    if (appData.quietPlay) {
-       XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
-    } else {
-       XtSetArg(args[0], XtNleftBitmap, None);
-    }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
-               args, 1);
-}
-
-void ShowCoordsProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+ShowCoordsProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
@@ -6639,21 +6588,15 @@ void ShowCoordsProc(w, event, prms, nprms)
     DrawPosition(True, NULL);
 }
 
-void ShowThinkingProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+ShowThinkingProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
     ShowThinkingEvent();
 }
 
-void HideThinkingProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+HideThinkingProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
@@ -6668,12 +6611,10 @@ void HideThinkingProc(w, event, prms, nprms)
     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
                args, 1);
 }
+#endif
 
-void SaveOnExitProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+SaveOnExitProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     Arg args[16];
 
@@ -6688,20 +6629,14 @@ void SaveOnExitProc(w, event, prms, nprms)
                args, 1);
 }
 
-void SaveSettingsProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+SaveSettingsProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
      SaveSettings(settingsFileName);
 }
 
-void InfoProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+InfoProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     char buf[MSG_SIZ];
     snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
@@ -6709,11 +6644,8 @@ void InfoProc(w, event, prms, nprms)
     system(buf);
 }
 
-void ManProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+ManProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     char buf[MSG_SIZ];
     String name;
@@ -6725,107 +6657,115 @@ void ManProc(w, event, prms, nprms)
     system(buf);
 }
 
-void HintProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+HintProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     HintEvent();
 }
 
-void BookProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+BookProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     BookEvent();
 }
 
-void AboutProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+BugReportProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
+{
+    char buf[MSG_SIZ];
+    snprintf(buf, MSG_SIZ, "%s mailto:bug-xboard@gnu.org", appData.sysOpen);
+    system(buf);
+}
+
+void
+GuideProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     char buf[MSG_SIZ];
+    snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/user_guide/UserGuide.html", appData.sysOpen);
+    system(buf);
+}
+
+void
+HomePageProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
+{
+    char buf[MSG_SIZ];
+    snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/", appData.sysOpen);
+    system(buf);
+}
+
+void
+NewsPageProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
+{
+    char buf[MSG_SIZ];
+    snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/whats_new/portal.html", appData.sysOpen);
+    system(buf);
+}
+
+void
+AboutProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
+{
+    char buf[2 * MSG_SIZ];
 #if ZIPPY
-    char *zippy = " (with Zippy code)";
+    char *zippy = _(" (with Zippy code)");
 #else
     char *zippy = "";
 #endif
-    snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
-           programVersion, zippy,
-           "Copyright 1991 Digital Equipment Corporation",
-           "Enhancements Copyright 1992-2009 Free Software Foundation",
-           "Enhancements Copyright 2005 Alessandro Scotti",
-           PACKAGE, " is free software and carries NO WARRANTY;",
-           "see the file COPYING for more information.");
+    snprintf(buf, sizeof(buf), 
+_("%s%s\n\n"
+"Copyright 1991 Digital Equipment Corporation\n"
+"Enhancements Copyright 1992-2012 Free Software Foundation\n"
+"Enhancements Copyright 2005 Alessandro Scotti\n\n"
+"%s is free software and carries NO WARRANTY;"
+"see the file COPYING for more information.\n\n"
+"Visit XBoard on the web at: http://www.gnu.org/software/xboard/\n"
+"Check out the newest features at: http://www.gnu.org/software/xboard/whats_new.html\n\n"
+"Report bugs via email at: <bug-xboard@gnu.org>\n\n"
+  ),
+           programVersion, zippy, PACKAGE);
     ErrorPopUp(_("About XBoard"), buf, FALSE);
 }
 
-void DebugProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+DebugProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     appData.debugMode = !appData.debugMode;
 }
 
-void AboutGameProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+AboutGameProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     AboutGameEvent();
 }
 
-void NothingProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+NothingProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     return;
 }
 
-void Iconify(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
-{
-    Arg args[16];
-
-    fromX = fromY = -1;
-    XtSetArg(args[0], XtNiconic, True);
-    XtSetValues(shellWidget, args, 1);
-}
-
-void DisplayMessage(message, extMessage)
-     char *message, *extMessage;
+void
+DisplayMessage (char *message, char *extMessage)
 {
   /* display a message in the message widget */
-  
+
   char buf[MSG_SIZ];
   Arg arg;
-  
-  if (extMessage) 
+
+  if (extMessage)
     {
-      if (*message) 
+      if (*message)
        {
          snprintf(buf, sizeof(buf), "%s  %s", message, extMessage);
          message = buf;
-       } 
-      else 
+       }
+      else
        {
          message = extMessage;
        };
     };
-  
+
+    safeStrCpy(lastMsg, message, MSG_SIZ); // [HGM] make available
+
   /* need to test if messageWidget already exists, since this function
      can also be called during the startup, if for example a Xresource
      is not set up correctly */
@@ -6834,12 +6774,12 @@ void DisplayMessage(message, extMessage)
       XtSetArg(arg, XtNlabel, message);
       XtSetValues(messageWidget, &arg, 1);
     };
-  
+
   return;
 }
 
-void DisplayTitle(text)
-     char *text;
+void
+DisplayTitle (char *text)
 {
     Arg args[16];
     int i;
@@ -6855,8 +6795,8 @@ void DisplayTitle(text)
     }
 
     if (*text != NULLCHAR) {
-       strcpy(icon, text);
-       strcpy(title, text);
+      safeStrCpy(icon, text, sizeof(icon)/sizeof(icon[0]) );
+      safeStrCpy(title, text, sizeof(title)/sizeof(title[0]) );
     } else if (appData.icsActive) {
         snprintf(icon, sizeof(icon), "%s", appData.icsHost);
        snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
@@ -6866,31 +6806,31 @@ void DisplayTitle(text)
 #ifdef GOTHIC
     // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
     } else if (gameInfo.variant == VariantGothic) {
-       strcpy(icon, programName);
-       strcpy(title, GOTHIC);
+      safeStrCpy(icon,  programName, sizeof(icon)/sizeof(icon[0]) );
+      safeStrCpy(title, GOTHIC,     sizeof(title)/sizeof(title[0]) );
 #endif
 #ifdef FALCON
     } else if (gameInfo.variant == VariantFalcon) {
-       strcpy(icon, programName);
-       strcpy(title, FALCON);
+      safeStrCpy(icon, programName, sizeof(icon)/sizeof(icon[0]) );
+      safeStrCpy(title, FALCON, sizeof(title)/sizeof(title[0]) );
 #endif
     } else if (appData.noChessProgram) {
-       strcpy(icon, programName);
-       strcpy(title, programName);
+      safeStrCpy(icon, programName, sizeof(icon)/sizeof(icon[0]) );
+      safeStrCpy(title, programName, sizeof(title)/sizeof(title[0]) );
     } else {
-       strcpy(icon, first.tidy);
+      safeStrCpy(icon, first.tidy, sizeof(icon)/sizeof(icon[0]) );
        snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
     }
     i = 0;
     XtSetArg(args[i], XtNiconName, (XtArgVal) icon);    i++;
     XtSetArg(args[i], XtNtitle, (XtArgVal) title);      i++;
     XtSetValues(shellWidget, args, i);
+    XSync(xDisplay, False);
 }
 
 
-void DisplayError(message, error)
-     String message;
-     int error;
+void
+DisplayError (String message, int error)
 {
     char buf[MSG_SIZ];
 
@@ -6910,8 +6850,8 @@ void DisplayError(message, error)
 }
 
 
-void DisplayMoveError(message)
-     String message;
+void
+DisplayMoveError (String message)
 {
     fromX = fromY = -1;
     ClearHighlights();
@@ -6927,9 +6867,8 @@ void DisplayMoveError(message)
 }
 
 
-void DisplayFatalError(message, error, status)
-     String message;
-     int error, status;
+void
+DisplayFatalError (String message, int error, int status)
 {
     char buf[MSG_SIZ];
 
@@ -6949,30 +6888,28 @@ void DisplayFatalError(message, error, status)
     }
 }
 
-void DisplayInformation(message)
-     String message;
+void
+DisplayInformation (String message)
 {
     ErrorPopDown();
     ErrorPopUp(_("Information"), message, TRUE);
 }
 
-void DisplayNote(message)
-     String message;
+void
+DisplayNote (String message)
 {
     ErrorPopDown();
     ErrorPopUp(_("Note"), message, FALSE);
 }
 
 static int
-NullXErrorCheck(dpy, error_event)
-     Display *dpy;
-     XErrorEvent *error_event;
+NullXErrorCheck (Display *dpy, XErrorEvent *error_event)
 {
     return 0;
 }
 
-void DisplayIcsInteractionTitle(message)
-     String message;
+void
+DisplayIcsInteractionTitle (String message)
 {
   if (oldICSInteractionTitle == NULL) {
     /* Magic to find the old window title, adapted from vim */
@@ -7003,11 +6940,8 @@ void DisplayIcsInteractionTitle(message)
 char pendingReplyPrefix[MSG_SIZ];
 ProcRef pendingReplyPR;
 
-void AskQuestionProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+AskQuestionProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     if (*nprms != 4) {
        fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
@@ -7017,7 +6951,8 @@ void AskQuestionProc(w, event, prms, nprms)
     AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
 }
 
-void AskQuestionPopDown()
+void
+AskQuestionPopDown ()
 {
     if (!askQuestionUp) return;
     XtPopdown(askQuestionShell);
@@ -7025,30 +6960,26 @@ void AskQuestionPopDown()
     askQuestionUp = False;
 }
 
-void AskQuestionReplyAction(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
+void
+AskQuestionReplyAction (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     char buf[MSG_SIZ];
     int err;
     String reply;
 
     reply = XawDialogGetValueString(w = XtParent(w));
-    strcpy(buf, pendingReplyPrefix);
-    if (*buf) strcat(buf, " ");
-    strcat(buf, reply);
-    strcat(buf, "\n");
+    safeStrCpy(buf, pendingReplyPrefix, sizeof(buf)/sizeof(buf[0]) );
+    if (*buf) strncat(buf, " ", MSG_SIZ - strlen(buf) - 1);
+    strncat(buf, reply, MSG_SIZ - strlen(buf) - 1);
+    strncat(buf, "\n",  MSG_SIZ - strlen(buf) - 1);
     OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
     AskQuestionPopDown();
 
     if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
 }
 
-void AskQuestionCallback(w, client_data, call_data)
-     Widget w;
-     XtPointer client_data, call_data;
+void
+AskQuestionCallback (Widget w, XtPointer client_data, XtPointer call_data)
 {
     String name;
     Arg args[16];
@@ -7063,9 +6994,8 @@ void AskQuestionCallback(w, client_data, call_data)
     }
 }
 
-void AskQuestion(title, question, replyPrefix, pr)
-     char *title, *question, *replyPrefix;
-     ProcRef pr;
+void
+AskQuestion (char *title, char *question, char *replyPrefix, ProcRef pr)
 {
     Arg args[16];
     Widget popup, layout, dialog, edit;
@@ -7074,7 +7004,7 @@ void AskQuestion(title, question, replyPrefix, pr)
     int win_x, win_y;
     unsigned int mask;
 
-    strcpy(pendingReplyPrefix, replyPrefix);
+    safeStrCpy(pendingReplyPrefix, replyPrefix, sizeof(pendingReplyPrefix)/sizeof(pendingReplyPrefix[0]) );
     pendingReplyPR = pr;
 
     i = 0;
@@ -7119,8 +7049,7 @@ void AskQuestion(title, question, replyPrefix, pr)
 
 
 void
-PlaySound(name)
-     char *name;
+PlaySound (char *name)
 {
   if (*name == NULLCHAR) {
     return;
@@ -7128,81 +7057,96 @@ PlaySound(name)
     putc(BELLCHAR, stderr);
   } else {
     char buf[2048];
-    snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
+    char *prefix = "", *sep = "";
+    if(appData.soundProgram[0] == NULLCHAR) return;
+    if(!strchr(name, '/')) { prefix = appData.soundDirectory; sep = "/"; }
+    snprintf(buf, sizeof(buf), "%s '%s%s%s' &", appData.soundProgram, prefix, sep, name);
     system(buf);
   }
 }
 
 void
-RingBell()
+RingBell ()
 {
   PlaySound(appData.soundMove);
 }
 
 void
-PlayIcsWinSound()
+PlayIcsWinSound ()
 {
   PlaySound(appData.soundIcsWin);
 }
 
 void
-PlayIcsLossSound()
+PlayIcsLossSound ()
 {
   PlaySound(appData.soundIcsLoss);
 }
 
 void
-PlayIcsDrawSound()
+PlayIcsDrawSound ()
 {
   PlaySound(appData.soundIcsDraw);
 }
 
 void
-PlayIcsUnfinishedSound()
+PlayIcsUnfinishedSound ()
 {
   PlaySound(appData.soundIcsUnfinished);
 }
 
 void
-PlayAlarmSound()
+PlayAlarmSound ()
 {
   PlaySound(appData.soundIcsAlarm);
 }
 
 void
-EchoOn()
+PlayTellSound ()
+{
+  PlaySound(appData.soundTell);
+}
+
+void
+EchoOn ()
 {
     system("stty echo");
+    noEcho = False;
 }
 
 void
-EchoOff()
+EchoOff ()
 {
     system("stty -echo");
+    noEcho = True;
 }
 
 void
-Colorize(cc, continuation)
-     ColorClass cc;
-     int continuation;
+RunCommand (char *buf)
+{
+    system(buf);
+}
+
+void
+Colorize (ColorClass cc, int continuation)
 {
     char buf[MSG_SIZ];
     int count, outCount, error;
 
     if (textColors[(int)cc].bg > 0) {
        if (textColors[(int)cc].fg > 0) {
-           sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
-                   textColors[(int)cc].fg, textColors[(int)cc].bg);
+         snprintf(buf, MSG_SIZ, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
+                  textColors[(int)cc].fg, textColors[(int)cc].bg);
        } else {
-           sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
-                   textColors[(int)cc].bg);
+         snprintf(buf, MSG_SIZ, "\033[0;%d;%dm", textColors[(int)cc].attr,
+                  textColors[(int)cc].bg);
        }
     } else {
        if (textColors[(int)cc].fg > 0) {
-           sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
+         snprintf(buf, MSG_SIZ, "\033[0;%d;%dm", textColors[(int)cc].attr,
                    textColors[(int)cc].fg);
        } else {
-           sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
+         snprintf(buf, MSG_SIZ, "\033[0;%dm", textColors[(int)cc].attr);
        }
     }
     count = strlen(buf);
@@ -7247,16 +7191,17 @@ Colorize(cc, continuation)
     }
 }
 
-char *UserName()
+char *
+UserName ()
 {
     return getpwuid(getuid())->pw_name;
 }
 
-static char *ExpandPathName(path)
-     char *path;
+static char *
+ExpandPathName (char *path)
 {
-    static char static_buf[2000];
-    char *d, *s, buf[2000];
+    static char static_buf[4*MSG_SIZ];
+    char *d, *s, buf[4*MSG_SIZ];
     struct passwd *pwd;
 
     s = path;
@@ -7272,30 +7217,31 @@ static char *ExpandPathName(path)
 
     if (*s == '~') {
        if (*(s+1) == '/') {
-           strcpy(d, getpwuid(getuid())->pw_dir);
-           strcat(d, s+1);
+         safeStrCpy(d, getpwuid(getuid())->pw_dir, 4*MSG_SIZ );
+         strcat(d, s+1);
        }
        else {
-           strcpy(buf, s+1);
-           *strchr(buf, '/') = 0;
-           pwd = getpwnam(buf);
-           if (!pwd)
-             {
-                 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
-                         buf, path);
-                 return NULL;
-             }
-           strcpy(d, pwd->pw_dir);
-           strcat(d, strchr(s+1, '/'));
+         safeStrCpy(buf, s+1, sizeof(buf)/sizeof(buf[0]) );
+         { char *p; if(p = strchr(buf, '/')) *p = 0; }
+         pwd = getpwnam(buf);
+         if (!pwd)
+           {
+             fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
+                     buf, path);
+             return NULL;
+           }
+         safeStrCpy(d, pwd->pw_dir, 4*MSG_SIZ );
+         strcat(d, strchr(s+1, '/'));
        }
     }
     else
-      strcpy(d, s);
+      safeStrCpy(d, s, 4*MSG_SIZ );
 
     return static_buf;
 }
 
-char *HostName()
+char *
+HostName ()
 {
     static char host_name[MSG_SIZ];
 
@@ -7316,15 +7262,14 @@ XtIntervalId delayedEventTimerXID = 0;
 DelayedEventCallback delayedEventCallback = 0;
 
 void
-FireDelayedEvent()
+FireDelayedEvent ()
 {
     delayedEventTimerXID = 0;
     delayedEventCallback();
 }
 
 void
-ScheduleDelayedEvent(cb, millisec)
-     DelayedEventCallback cb; long millisec;
+ScheduleDelayedEvent (DelayedEventCallback cb, long millisec)
 {
     if(delayedEventTimerXID && delayedEventCallback == cb)
        // [HGM] alive: replace, rather than add or flush identical event
@@ -7336,7 +7281,7 @@ ScheduleDelayedEvent(cb, millisec)
 }
 
 DelayedEventCallback
-GetDelayedEvent()
+GetDelayedEvent ()
 {
   if (delayedEventTimerXID) {
     return delayedEventCallback;
@@ -7346,7 +7291,7 @@ GetDelayedEvent()
 }
 
 void
-CancelDelayedEvent()
+CancelDelayedEvent ()
 {
   if (delayedEventTimerXID) {
     XtRemoveTimeOut(delayedEventTimerXID);
@@ -7356,12 +7301,14 @@ CancelDelayedEvent()
 
 XtIntervalId loadGameTimerXID = 0;
 
-int LoadGameTimerRunning()
+int
+LoadGameTimerRunning ()
 {
     return loadGameTimerXID != 0;
 }
 
-int StopLoadGameTimer()
+int
+StopLoadGameTimer ()
 {
     if (loadGameTimerXID != 0) {
        XtRemoveTimeOut(loadGameTimerXID);
@@ -7373,17 +7320,14 @@ int StopLoadGameTimer()
 }
 
 void
-LoadGameTimerCallback(arg, id)
-     XtPointer arg;
-     XtIntervalId *id;
+LoadGameTimerCallback (XtPointer arg, XtIntervalId *id)
 {
     loadGameTimerXID = 0;
     AutoPlayGameLoop();
 }
 
 void
-StartLoadGameTimer(millisec)
-     long millisec;
+StartLoadGameTimer (long millisec)
 {
     loadGameTimerXID =
       XtAppAddTimeOut(appContext, millisec,
@@ -7394,9 +7338,7 @@ StartLoadGameTimer(millisec)
 XtIntervalId analysisClockXID = 0;
 
 void
-AnalysisClockCallback(arg, id)
-     XtPointer arg;
-     XtIntervalId *id;
+AnalysisClockCallback (XtPointer arg, XtIntervalId *id)
 {
     if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
          || appData.icsEngineAnalyze) { // [DM]
@@ -7406,7 +7348,7 @@ AnalysisClockCallback(arg, id)
 }
 
 void
-StartAnalysisClock()
+StartAnalysisClock ()
 {
     analysisClockXID =
       XtAppAddTimeOut(appContext, 2000,
@@ -7416,12 +7358,14 @@ StartAnalysisClock()
 
 XtIntervalId clockTimerXID = 0;
 
-int ClockTimerRunning()
+int
+ClockTimerRunning ()
 {
     return clockTimerXID != 0;
 }
 
-int StopClockTimer()
+int
+StopClockTimer ()
 {
     if (clockTimerXID != 0) {
        XtRemoveTimeOut(clockTimerXID);
@@ -7433,17 +7377,14 @@ int StopClockTimer()
 }
 
 void
-ClockTimerCallback(arg, id)
-     XtPointer arg;
-     XtIntervalId *id;
+ClockTimerCallback (XtPointer arg, XtIntervalId *id)
 {
     clockTimerXID = 0;
     DecrementClocks();
 }
 
 void
-StartClockTimer(millisec)
-     long millisec;
+StartClockTimer (long millisec)
 {
     clockTimerXID =
       XtAppAddTimeOut(appContext, millisec,
@@ -7452,11 +7393,7 @@ StartClockTimer(millisec)
 }
 
 void
-DisplayTimerLabel(w, color, timer, highlight)
-     Widget w;
-     char *color;
-     long timer;
-     int highlight;
+DisplayTimerLabel (Widget w, char *color, long timer, int highlight)
 {
     char buf[MSG_SIZ];
     Arg args[16];
@@ -7465,16 +7402,16 @@ DisplayTimerLabel(w, color, timer, highlight)
     Pixel foregroundOrWarningColor = timerForegroundPixel;
 
     if (timer > 0 &&
-        appData.lowTimeWarning && 
+        appData.lowTimeWarning &&
         (timer / 1000) < appData.icsAlarmTime)
       foregroundOrWarningColor = lowTimeWarningColor;
 
     if (appData.clockMode) {
-       sprintf(buf, "%s: %s", color, TimeString(timer));
-       XtSetArg(args[0], XtNlabel, buf);
+      snprintf(buf, MSG_SIZ, "%s: %s", color, TimeString(timer));
+      XtSetArg(args[0], XtNlabel, buf);
     } else {
-       sprintf(buf, "%s  ", color);
-       XtSetArg(args[0], XtNlabel, buf);
+      snprintf(buf, MSG_SIZ, "%s  ", color);
+      XtSetArg(args[0], XtNlabel, buf);
     }
 
     if (highlight) {
@@ -7490,9 +7427,7 @@ DisplayTimerLabel(w, color, timer, highlight)
 }
 
 void
-DisplayWhiteClock(timeRemaining, highlight)
-     long timeRemaining;
-     int highlight;
+DisplayWhiteClock (long timeRemaining, int highlight)
 {
     Arg args[16];
 
@@ -7506,9 +7441,7 @@ DisplayWhiteClock(timeRemaining, highlight)
 }
 
 void
-DisplayBlackClock(timeRemaining, highlight)
-     long timeRemaining;
-     int highlight;
+DisplayBlackClock (long timeRemaining, int highlight)
 {
     Arg args[16];
 
@@ -7535,10 +7468,8 @@ typedef struct {
 } ChildProc;
 
 
-int StartChildProcess(cmdLine, dir, pr)
-     char *cmdLine;
-     char *dir;
-     ProcRef *pr;
+int
+StartChildProcess (char *cmdLine, char *dir, ProcRef *pr)
 {
     char *argv[64], *p;
     int i, pid;
@@ -7547,7 +7478,7 @@ int StartChildProcess(cmdLine, dir, pr)
     char buf[MSG_SIZ];
 
     if (appData.debugMode) {
-       fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
+       fprintf(debugFP, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
     }
 
     /* We do NOT feed the cmdLine to the shell; we just
@@ -7555,11 +7486,14 @@ int StartChildProcess(cmdLine, dir, pr)
        most simple-minded way possible.
        */
     i = 0;
-    strcpy(buf, cmdLine);
+    safeStrCpy(buf, cmdLine, sizeof(buf)/sizeof(buf[0]) );
     p = buf;
     for (;;) {
+       while(*p == ' ') p++;
        argv[i++] = p;
-       p = strchr(p, ' ');
+       if(*p == '"' || *p == '\'')
+            p = strchr(++argv[i-1], *p);
+       else p = strchr(p, ' ');
        if (p == NULL) break;
        *p++ = NULLCHAR;
     }
@@ -7607,15 +7541,14 @@ int StartChildProcess(cmdLine, dir, pr)
 }
 
 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
-static RETSIGTYPE AlarmCallBack(int n)
+static RETSIGTYPE
+AlarmCallBack (int n)
 {
     return;
 }
 
 void
-DestroyChildProcess(pr, signalType)
-     ProcRef pr;
-     int signalType;
+DestroyChildProcess (ProcRef pr, int signalType)
 {
     ChildProc *cp = (ChildProc *) pr;
 
@@ -7642,8 +7575,7 @@ DestroyChildProcess(pr, signalType)
 }
 
 void
-InterruptChildProcess(pr)
-     ProcRef pr;
+InterruptChildProcess (ProcRef pr)
 {
     ChildProc *cp = (ChildProc *) pr;
 
@@ -7651,10 +7583,8 @@ InterruptChildProcess(pr)
     (void) kill(cp->pid, SIGINT); /* stop it thinking */
 }
 
-int OpenTelnet(host, port, pr)
-     char *host;
-     char *port;
-     ProcRef *pr;
+int
+OpenTelnet (char *host, char *port, ProcRef *pr)
 {
     char cmdLine[MSG_SIZ];
 
@@ -7666,58 +7596,46 @@ int OpenTelnet(host, port, pr)
     return StartChildProcess(cmdLine, "", pr);
 }
 
-int OpenTCP(host, port, pr)
-     char *host;
-     char *port;
-     ProcRef *pr;
+int
+OpenTCP (char *host, char *port, ProcRef *pr)
 {
 #if OMIT_SOCKETS
     DisplayFatalError(_("Socket support is not configured in"), 0, 2);
 #else  /* !OMIT_SOCKETS */
-    int s;
-    struct sockaddr_in sa;
-    struct hostent     *hp;
-    unsigned short uport;
+    struct addrinfo hints;
+    struct addrinfo *ais, *ai;
+    int error;
+    int s=0;
     ChildProc *cp;
 
-    if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
-       return errno;
-    }
-
-    memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
-    sa.sin_family = AF_INET;
-    sa.sin_addr.s_addr = INADDR_ANY;
-    uport = (unsigned short) 0;
-    sa.sin_port = htons(uport);
-    if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
-       return errno;
-    }
-
-    memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
-    if (!(hp = gethostbyname(host))) {
-       int b0, b1, b2, b3;
-       if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
-           hp = (struct hostent *) calloc(1, sizeof(struct hostent));
-           hp->h_addrtype = AF_INET;
-           hp->h_length = 4;
-           hp->h_addr_list = (char **) calloc(2, sizeof(char *));
-           hp->h_addr_list[0] = (char *) malloc(4);
-           hp->h_addr_list[0][0] = b0;
-           hp->h_addr_list[0][1] = b1;
-           hp->h_addr_list[0][2] = b2;
-           hp->h_addr_list[0][3] = b3;
-       } else {
-           return ENOENT;
-       }
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+
+    error = getaddrinfo(host, port, &hints, &ais);
+    if (error != 0) {
+      /* a getaddrinfo error is not an errno, so can't return it */
+      fprintf(debugFP, "getaddrinfo(%s, %s): %s\n",
+             host, port, gai_strerror(error));
+      return ENOENT;
+    }
+     
+    for (ai = ais; ai != NULL; ai = ai->ai_next) {
+      if ((s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) {
+       error = errno;
+       continue;
+      }
+      if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0) {
+       error = errno;
+       continue;
+      }
+      error = 0;
+      break;
     }
-    sa.sin_family = hp->h_addrtype;
-    uport = (unsigned short) atoi(port);
-    sa.sin_port = htons(uport);
-    memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
+    freeaddrinfo(ais);
 
-    if (connect(s, (struct sockaddr *) &sa,
-               sizeof(struct sockaddr_in)) < 0) {
-       return errno;
+    if (error != 0) {
+      return error;
     }
 
     cp = (ChildProc *) calloc(1, sizeof(ChildProc));
@@ -7726,15 +7644,13 @@ int OpenTCP(host, port, pr)
     cp->fdFrom = s;
     cp->fdTo = s;
     *pr = (ProcRef) cp;
-
 #endif /* !OMIT_SOCKETS */
 
     return 0;
 }
 
-int OpenCommPort(name, pr)
-     char *name;
-     ProcRef *pr;
+int
+OpenCommPort (char *name, ProcRef *pr)
 {
     int fd;
     ChildProc *cp;
@@ -7752,8 +7668,8 @@ int OpenCommPort(name, pr)
     return 0;
 }
 
-int OpenLoopback(pr)
-     ProcRef *pr;
+int
+OpenLoopback (ProcRef *pr)
 {
     ChildProc *cp;
     int to[2], from[2];
@@ -7770,9 +7686,8 @@ int OpenLoopback(pr)
     return 0;
 }
 
-int OpenRcmd(host, user, cmd, pr)
-     char *host, *user, *cmd;
-     ProcRef *pr;
+int
+OpenRcmd (char *host, char *user, char *cmd, ProcRef *pr)
 {
     DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
     return -1;
@@ -7792,10 +7707,7 @@ typedef struct {
 } InputSource;
 
 void
-DoInputCallback(closure, source, xid)
-     caddr_t closure;
-     int *source;
-     XtInputId *xid;
+DoInputCallback (caddr_t closure, int *source, XtInputId *xid)
 {
     InputSource *is = (InputSource *) closure;
     int count;
@@ -7833,11 +7745,8 @@ DoInputCallback(closure, source, xid)
     }
 }
 
-InputSourceRef AddInputSource(pr, lineByLine, func, closure)
-     ProcRef pr;
-     int lineByLine;
-     InputCallback func;
-     VOIDSTAR closure;
+InputSourceRef
+AddInputSource (ProcRef pr, int lineByLine, InputCallback func, VOIDSTAR closure)
 {
     InputSource *is;
     ChildProc *cp = (ChildProc *) pr;
@@ -7865,8 +7774,7 @@ InputSourceRef AddInputSource(pr, lineByLine, func, closure)
 }
 
 void
-RemoveInputSource(isr)
-     InputSourceRef isr;
+RemoveInputSource (InputSourceRef isr)
 {
     InputSource *is = (InputSource *) isr;
 
@@ -7875,11 +7783,8 @@ RemoveInputSource(isr)
     is->xid = 0;
 }
 
-int OutputToProcess(pr, message, count, outError)
-     ProcRef pr;
-     char *message;
-     int count;
-     int *outError;
+int
+OutputToProcess (ProcRef pr, char *message, int count, int *outError)
 {
     static int line = 0;
     ChildProc *cp = (ChildProc *) pr;
@@ -7923,12 +7828,8 @@ int OutputToProcess(pr, message, count, outError)
    between each character. This is needed when sending the logon
    script to ICC, which for some reason doesn't like the
    instantaneous send. */
-int OutputToProcessDelayed(pr, message, count, outError, msdelay)
-     ProcRef pr;
-     char *message;
-     int count;
-     int *outError;
-     long msdelay;
+int
+OutputToProcessDelayed (ProcRef pr, char *message, int count, int *outError, long msdelay)
 {
     ChildProc *cp = (ChildProc *) pr;
     int outCount = 0;
@@ -7970,8 +7871,7 @@ int OutputToProcessDelayed(pr, message, count, outError, msdelay)
 static int xpmDone = 0;
 
 static void
-CreateAnimMasks (pieceDepth)
-     int pieceDepth;
+CreateAnimMasks (int pieceDepth)
 {
   ChessSquare   piece;
   Pixmap       buf;
@@ -8049,9 +7949,7 @@ CreateAnimMasks (pieceDepth)
 }
 
 static void
-InitAnimState (anim, info)
-  AnimState * anim;
-  XWindowAttributes * info;
+InitAnimState (AnimState *anim, XWindowAttributes *info)
 {
   XtGCMask  mask;
   XGCValues values;
@@ -8083,11 +7981,10 @@ InitAnimState (anim, info)
 static void
 CreateAnimVars ()
 {
-  static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
   XWindowAttributes info;
 
-  if (xpmDone && gameInfo.variant == old) return;
-  if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
+  if (xpmDone && gameInfo.variant == oldVariant) return;
+  if(xpmDone) oldVariant = gameInfo.variant; // first time pieces might not be created yet
   XGetWindowAttributes(xDisplay, xBoardWindow, &info);
 
   InitAnimState(&game, &info);
@@ -8095,16 +7992,15 @@ CreateAnimVars ()
 
   /* For XPM pieces, we need bitmaps to use as masks. */
   if (useImages)
-    CreateAnimMasks(info.depth);
-   xpmDone = 1;
+    CreateAnimMasks(info.depth), xpmDone = 1;
 }
 
 #ifndef HAVE_USLEEP
 
 static Boolean frameWaiting;
 
-static RETSIGTYPE FrameAlarm (sig)
-     int sig;
+static RETSIGTYPE
+FrameAlarm (int sig)
 {
   frameWaiting = False;
   /* In case System-V style signals.  Needed?? */
@@ -8112,8 +8008,7 @@ static RETSIGTYPE FrameAlarm (sig)
 }
 
 static void
-FrameDelay (time)
-     int time;
+FrameDelay (int time)
 {
   struct itimerval delay;
 
@@ -8137,8 +8032,7 @@ FrameDelay (time)
 #else
 
 static void
-FrameDelay (time)
-     int time;
+FrameDelay (int time)
 {
   XSync(xDisplay, False);
   if (time > 0)
@@ -8147,11 +8041,16 @@ FrameDelay (time)
 
 #endif
 
+void
+DoSleep (int n)
+{
+    FrameDelay(n);
+}
+
 /*     Convert board position to corner of screen rect and color       */
 
 static void
-ScreenSquare(column, row, pt, color)
-     int column; int row; XPoint * pt; int * color;
+ScreenSquare (int column, int row, XPoint *pt, int *color)
 {
   if (flipView) {
     pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
@@ -8166,8 +8065,7 @@ ScreenSquare(column, row, pt, color)
 /*     Convert window coords to square                 */
 
 static void
-BoardSquare(x, y, column, row)
-     int x; int y; int * column; int * row;
+BoardSquare (int x, int y, int *column, int *row)
 {
   *column = EventToSquare(x, BOARD_WIDTH);
   if (flipView && *column >= 0)
@@ -8185,8 +8083,7 @@ BoardSquare(x, y, column, row)
 #define Min(a, b) ((a) < (b) ? (a) : (b))
 
 static void
-SetRect(rect, x, y, width, height)
-     XRectangle * rect; int x; int y; int width; int height;
+SetRect (XRectangle *rect, int x, int y, int width, int height)
 {
   rect->x = x;
   rect->y = y;
@@ -8199,9 +8096,7 @@ SetRect(rect, x, y, width, height)
        that rect within new. */
 
 static Boolean
-Intersect(old, new, size, area, pt)
-     XPoint * old; XPoint * new;
-     int size; XRectangle * area; XPoint * pt;
+Intersect ( XPoint *old, XPoint *new, int size, XRectangle *area, XPoint *pt)
 {
   if (old->x > new->x + size || new->x > old->x + size ||
       old->y > new->y + size || new->y > old->y + size) {
@@ -8219,9 +8114,7 @@ Intersect(old, new, size, area, pt)
        in the old that do not intersect with the new.   */
 
 static void
-CalcUpdateRects(old, new, size, update, nUpdates)
-     XPoint * old; XPoint * new; int size;
-     XRectangle update[]; int * nUpdates;
+CalcUpdateRects (XPoint *old, XPoint *new, int size, XRectangle update[], int *nUpdates)
 {
   int       count;
 
@@ -8267,10 +8160,7 @@ CalcUpdateRects(old, new, size, update, nUpdates)
        noticeable.                                             */
 
 static void
-Tween(start, mid, finish, factor, frames, nFrames)
-     XPoint * start; XPoint * mid;
-     XPoint * finish; int factor;
-     XPoint frames[]; int * nFrames;
+Tween (XPoint *start, XPoint *mid, XPoint *finish, int factor, XPoint frames[], int *nFrames)
 {
   int fraction, n, count;
 
@@ -8305,8 +8195,7 @@ Tween(start, mid, finish, factor, frames, nFrames)
 /*     Draw a piece on the screen without disturbing what's there      */
 
 static void
-SelectGCMask(piece, clip, outline, mask)
-     ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
+SelectGCMask (ChessSquare piece, GC *clip, GC *outline, Pixmap *mask)
 {
   GC source;
 
@@ -8346,8 +8235,7 @@ SelectGCMask(piece, clip, outline, mask)
 }
 
 static void
-OverlayPiece(piece, clip, outline,  dest)
-     ChessSquare piece; GC clip; GC outline; Drawable dest;
+OverlayPiece (ChessSquare piece, GC clip, GC outline,  Drawable dest)
 {
   int  kind;
 
@@ -8366,6 +8254,7 @@ OverlayPiece(piece, clip, outline,  dest)
       kind = 0;
     else
       kind = 2;
+    if(appData.upsideDown && flipView) kind ^= 2;
     XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
              dest, clip,
              0, 0, squareSize, squareSize,
@@ -8376,16 +8265,13 @@ OverlayPiece(piece, clip, outline,  dest)
 /* Animate the movement of a single piece */
 
 static void
-BeginAnimation(anim, piece, startColor, start)
-     AnimState *anim;
-     ChessSquare piece;
-     int startColor;
-     XPoint * start;
+BeginAnimation (AnimState *anim, ChessSquare piece, int startColor, XPoint *start)
 {
   Pixmap mask;
 
+  if(appData.upsideDown && flipView) piece += piece < BlackPawn ? BlackPawn : -BlackPawn;
   /* The old buffer is initialised with the start square (empty) */
-  BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
+  BlankSquare(start->x, start->y, startColor, EmptySquare, anim->saveBuf, 0);
   anim->prevFrame = *start;
 
   /* The piece will be drawn using its own bitmap as a matte   */
@@ -8394,10 +8280,7 @@ BeginAnimation(anim, piece, startColor, start)
 }
 
 static void
-AnimationFrame(anim, frame, piece)
-     AnimState *anim;
-     XPoint *frame;
-     ChessSquare piece;
+AnimationFrame (AnimState *anim, XPoint *frame, ChessSquare piece)
 {
   XRectangle updates[4];
   XRectangle overlap;
@@ -8447,9 +8330,7 @@ AnimationFrame(anim, frame, piece)
 }
 
 static void
-EndAnimation (anim, finish)
-     AnimState *anim;
-     XPoint *finish;
+EndAnimation (AnimState *anim, XPoint *finish)
 {
   XRectangle updates[4];
   XRectangle overlap;
@@ -8474,11 +8355,7 @@ EndAnimation (anim, finish)
 }
 
 static void
-FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
-     AnimState *anim;
-     ChessSquare piece; int startColor;
-     XPoint * start; XPoint * finish;
-     XPoint frames[]; int nFrames;
+FrameSequence (AnimState *anim, ChessSquare piece, int startColor, XPoint *start, XPoint *finish, XPoint frames[], int nFrames)
 {
   int n;
 
@@ -8490,15 +8367,33 @@ FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
   EndAnimation(anim, finish);
 }
 
+void
+AnimateAtomicCapture (Board board, int fromX, int fromY, int toX, int toY)
+{
+    int i, x, y;
+    ChessSquare piece = board[fromY][toY];
+    board[fromY][toY] = EmptySquare;
+    DrawPosition(FALSE, board);
+    if (flipView) {
+       x = lineGap + ((BOARD_WIDTH-1)-toX) * (squareSize + lineGap);
+       y = lineGap + toY * (squareSize + lineGap);
+    } else {
+       x = lineGap + toX * (squareSize + lineGap);
+       y = lineGap + ((BOARD_HEIGHT-1)-toY) * (squareSize + lineGap);
+    }
+    for(i=1; i<4*kFactor; i++) {
+       int r = squareSize * 9 * i/(20*kFactor - 5);
+       XFillArc(xDisplay, xBoardWindow, highlineGC,
+               x + squareSize/2 - r, y+squareSize/2 - r, 2*r, 2*r, 0, 64*360);
+       FrameDelay(appData.animSpeed);
+    }
+    board[fromY][toY] = piece;
+}
+
 /* Main control logic for deciding what to animate and how */
 
 void
-AnimateMove(board, fromX, fromY, toX, toY)
-     Board board;
-     int fromX;
-     int fromY;
-     int toX;
-     int toY;
+AnimateMove (Board board, int fromX, int fromY, int toX, int toY)
 {
   ChessSquare piece;
   int hop;
@@ -8510,8 +8405,8 @@ AnimateMove(board, fromX, fromY, toX, toY)
   if (!appData.animate || appData.blindfold)
     return;
 
-  if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing || 
-     board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing) 
+  if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
+     board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
        return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
 
   if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
@@ -8521,24 +8416,19 @@ AnimateMove(board, fromX, fromY, toX, toY)
 #if DONT_HOP
   hop = FALSE;
 #else
-  hop = (piece == WhiteKnight || piece == BlackKnight);
+  hop = abs(fromX-toX) == 1 && abs(fromY-toY) == 2 || abs(fromX-toX) == 2 && abs(fromY-toY) == 1;
 #endif
 
-  if (appData.debugMode) {
-      fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
-                             _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
-             piece, fromX, fromY, toX, toY);  }
-
   ScreenSquare(fromX, fromY, &start, &startColor);
   ScreenSquare(toX, toY, &finish, &endColor);
 
   if (hop) {
-    /* Knight: make diagonal movement then straight */
+    /* Knight: make straight movement then diagonal */
     if (abs(toY - fromY) < abs(toX - fromX)) {
        mid.x = start.x + (finish.x - start.x) / 2;
-       mid.y = finish.y;
+       mid.y = start.y;
      } else {
-       mid.x = finish.x;
+       mid.x = start.x;
        mid.y = start.y + (finish.y - start.y) / 2;
      }
   } else {
@@ -8552,14 +8442,18 @@ AnimateMove(board, fromX, fromY, toX, toY)
   else
     Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
   FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
+  if(Explode(board, fromX, fromY, toX, toY)) { // mark as damaged
+    int i,j;
+    for(i=0; i<BOARD_WIDTH; i++) for(j=0; j<BOARD_HEIGHT; j++)
+      if((i-toX)*(i-toX) + (j-toY)*(j-toY) < 6) damage[0][j][i] = True;
+  }
 
   /* Be sure end square is redrawn */
-  damage[toY][toX] = True;
+  damage[0][toY][toX] = True;
 }
 
 void
-DragPieceBegin(x, y)
-     int x; int y;
+DragPieceBegin (int x, int y, Boolean instantly)
 {
     int         boardX, boardY, color;
     XPoint corner;
@@ -8594,15 +8488,35 @@ DragPieceBegin(x, y)
            XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
                     corner.x, corner.y, squareSize, squareSize,
                     0, 0); // [HGM] zh: unstack in stead of grab
-       damage[boardY][boardX] = True;
+           if(gatingPiece != EmptySquare) {
+               /* Kludge alert: When gating we want the introduced
+                  piece to appear on the from square. To generate an
+                  image of it, we draw it on the board, copy the image,
+                  and draw the original piece again. */
+               ChessSquare piece = boards[currentMove][boardY][boardX];
+               DrawSquare(boardY, boardX, gatingPiece, 0);
+               XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
+                    corner.x, corner.y, squareSize, squareSize, 0, 0);
+               DrawSquare(boardY, boardX, piece, 0);
+           }
+       damage[0][boardY][boardX] = True;
     } else {
        player.dragActive = False;
     }
 }
 
+void
+ChangeDragPiece (ChessSquare piece)
+{
+  Pixmap mask;
+  player.dragPiece = piece;
+  /* The piece will be drawn using its own bitmap as a matte   */
+  SelectGCMask(piece, &player.pieceGC, &player.outlineGC, &mask);
+  XSetClipMask(xDisplay, player.pieceGC, mask);
+}
+
 static void
-DragPieceMove(x, y)
-     int x; int y;
+DragPieceMove (int x, int y)
 {
     XPoint corner;
 
@@ -8618,7 +8532,7 @@ DragPieceMove(x, y)
     corner.x = x - player.mouseDelta.x;
     corner.y = y - player.mouseDelta.y;
     AnimationFrame(&player, &corner, player.dragPiece);
-#if HIGHDRAG
+#if HIGHDRAG*0
     if (appData.highlightDragging) {
        int boardX, boardY;
        BoardSquare(x, y, &boardX, &boardY);
@@ -8628,8 +8542,7 @@ DragPieceMove(x, y)
 }
 
 void
-DragPieceEnd(x, y)
-     int x; int y;
+DragPieceEnd (int x, int y)
 {
     int boardX, boardY, color;
     XPoint corner;
@@ -8648,7 +8561,7 @@ DragPieceEnd(x, y)
     EndAnimation(&player, &corner);
 
     /* Be sure end square is redrawn */
-    damage[boardY][boardX] = True;
+    damage[0][boardY][boardX] = True;
 
     /* This prevents weird things happening with fast successive
        clicks which on my Sun at least can cause motion events
@@ -8669,13 +8582,14 @@ DrawDragPiece ()
      it's being dragged around the board. So we erase the square
      that the piece is on and draw it at the last known drag point. */
   BlankSquare(player.startSquare.x, player.startSquare.y,
-               player.startColor, EmptySquare, xBoardWindow);
+               player.startColor, EmptySquare, xBoardWindow, 1);
   AnimationFrame(&player, &player.prevFrame, player.dragPiece);
-  damage[player.startBoardY][player.startBoardX] = TRUE;
+  damage[0][player.startBoardY][player.startBoardX] = TRUE;
 }
 
 #include <sys/ioctl.h>
-int get_term_width()
+int
+get_term_width ()
 {
     int fd, default_width;
 
@@ -8694,17 +8608,233 @@ int get_term_width()
     return default_width;
 }
 
-void update_ics_width()
+void
+update_ics_width ()
 {
-    static int old_width = 0;
-    int new_width = get_term_width();
+  static int old_width = 0;
+  int new_width = get_term_width();
 
-    if (old_width != new_width)
-       ics_printf("set width %d\n", new_width);
-    old_width = new_width;
+  if (old_width != new_width)
+    ics_printf("set width %d\n", new_width);
+  old_width = new_width;
 }
 
-void NotifyFrontendLogin()
+void
+NotifyFrontendLogin ()
 {
     update_ics_width();
 }
+
+/* [AS] Arrow highlighting support */
+
+static double A_WIDTH = 5; /* Width of arrow body */
+
+#define A_HEIGHT_FACTOR 6   /* Length of arrow "point", relative to body width */
+#define A_WIDTH_FACTOR  3   /* Width of arrow "point", relative to body width */
+
+static double
+Sqr (double x)
+{
+    return x*x;
+}
+
+static int
+Round (double x)
+{
+    return (int) (x + 0.5);
+}
+
+void
+SquareToPos (int rank, int file, int *x, int *y)
+{
+    if (flipView) {
+       *x = lineGap + ((BOARD_WIDTH-1)-file) * (squareSize + lineGap);
+       *y = lineGap + rank * (squareSize + lineGap);
+    } else {
+       *x = lineGap + file * (squareSize + lineGap);
+       *y = lineGap + ((BOARD_HEIGHT-1)-rank) * (squareSize + lineGap);
+    }
+}
+
+/* Draw an arrow between two points using current settings */
+void
+DrawArrowBetweenPoints (int s_x, int s_y, int d_x, int d_y)
+{
+    XPoint arrow[8];
+    double dx, dy, j, k, x, y;
+
+    if( d_x == s_x ) {
+        int h = (d_y > s_y) ? +A_WIDTH*A_HEIGHT_FACTOR : -A_WIDTH*A_HEIGHT_FACTOR;
+
+        arrow[0].x = s_x + A_WIDTH + 0.5;
+        arrow[0].y = s_y;
+
+        arrow[1].x = s_x + A_WIDTH + 0.5;
+        arrow[1].y = d_y - h;
+
+        arrow[2].x = arrow[1].x + A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5;
+        arrow[2].y = d_y - h;
+
+        arrow[3].x = d_x;
+        arrow[3].y = d_y;
+
+        arrow[5].x = arrow[1].x - 2*A_WIDTH + 0.5;
+        arrow[5].y = d_y - h;
+
+        arrow[4].x = arrow[5].x - A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5;
+        arrow[4].y = d_y - h;
+
+        arrow[6].x = arrow[1].x - 2*A_WIDTH + 0.5;
+        arrow[6].y = s_y;
+    }
+    else if( d_y == s_y ) {
+        int w = (d_x > s_x) ? +A_WIDTH*A_HEIGHT_FACTOR : -A_WIDTH*A_HEIGHT_FACTOR;
+
+        arrow[0].x = s_x;
+        arrow[0].y = s_y + A_WIDTH + 0.5;
+
+        arrow[1].x = d_x - w;
+        arrow[1].y = s_y + A_WIDTH + 0.5;
+
+        arrow[2].x = d_x - w;
+        arrow[2].y = arrow[1].y + A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5;
+
+        arrow[3].x = d_x;
+        arrow[3].y = d_y;
+
+        arrow[5].x = d_x - w;
+        arrow[5].y = arrow[1].y - 2*A_WIDTH + 0.5;
+
+        arrow[4].x = d_x - w;
+        arrow[4].y = arrow[5].y - A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5;
+
+        arrow[6].x = s_x;
+        arrow[6].y = arrow[1].y - 2*A_WIDTH + 0.5;
+    }
+    else {
+        /* [AS] Needed a lot of paper for this! :-) */
+        dy = (double) (d_y - s_y) / (double) (d_x - s_x);
+        dx = (double) (s_x - d_x) / (double) (s_y - d_y);
+
+        j = sqrt( Sqr(A_WIDTH) / (1.0 + Sqr(dx)) );
+
+        k = sqrt( Sqr(A_WIDTH*A_HEIGHT_FACTOR) / (1.0 + Sqr(dy)) );
+
+        x = s_x;
+        y = s_y;
+
+        arrow[0].x = Round(x - j);
+        arrow[0].y = Round(y + j*dx);
+
+        arrow[1].x = Round(arrow[0].x + 2*j);   // [HGM] prevent width to be affected by rounding twice
+        arrow[1].y = Round(arrow[0].y - 2*j*dx);
+
+        if( d_x > s_x ) {
+            x = (double) d_x - k;
+            y = (double) d_y - k*dy;
+        }
+        else {
+            x = (double) d_x + k;
+            y = (double) d_y + k*dy;
+        }
+
+        x = Round(x); y = Round(y); // [HGM] make sure width of shaft is rounded the same way on both ends
+
+        arrow[6].x = Round(x - j);
+        arrow[6].y = Round(y + j*dx);
+
+        arrow[2].x = Round(arrow[6].x + 2*j);
+        arrow[2].y = Round(arrow[6].y - 2*j*dx);
+
+        arrow[3].x = Round(arrow[2].x + j*(A_WIDTH_FACTOR-1));
+        arrow[3].y = Round(arrow[2].y - j*(A_WIDTH_FACTOR-1)*dx);
+
+        arrow[4].x = d_x;
+        arrow[4].y = d_y;
+
+        arrow[5].x = Round(arrow[6].x - j*(A_WIDTH_FACTOR-1));
+        arrow[5].y = Round(arrow[6].y + j*(A_WIDTH_FACTOR-1)*dx);
+    }
+
+    XFillPolygon(xDisplay, xBoardWindow, highlineGC, arrow, 7, Nonconvex, CoordModeOrigin);
+    if(appData.monoMode) arrow[7] = arrow[0], XDrawLines(xDisplay, xBoardWindow, darkSquareGC, arrow, 8, CoordModeOrigin);
+//    Polygon( hdc, arrow, 7 );
+}
+
+void
+ArrowDamage (int s_col, int s_row, int d_col, int d_row)
+{
+    int hor, vert, i;
+    hor = 64*s_col + 32; vert = 64*s_row + 32;
+    for(i=0; i<= 64; i++) {
+            damage[0][vert+6>>6][hor+6>>6] = True;
+            damage[0][vert-6>>6][hor+6>>6] = True;
+            damage[0][vert+6>>6][hor-6>>6] = True;
+            damage[0][vert-6>>6][hor-6>>6] = True;
+            hor += d_col - s_col; vert += d_row - s_row;
+    }
+}
+
+/* [AS] Draw an arrow between two squares */
+void
+DrawArrowBetweenSquares (int s_col, int s_row, int d_col, int d_row)
+{
+    int s_x, s_y, d_x, d_y;
+
+    if( s_col == d_col && s_row == d_row ) {
+        return;
+    }
+
+    /* Get source and destination points */
+    SquareToPos( s_row, s_col, &s_x, &s_y);
+    SquareToPos( d_row, d_col, &d_x, &d_y);
+
+    if( d_y > s_y ) {
+        d_y += squareSize / 2 - squareSize / 4; // [HGM] round towards same centers on all sides!
+    }
+    else if( d_y < s_y ) {
+        d_y += squareSize / 2 + squareSize / 4;
+    }
+    else {
+        d_y += squareSize / 2;
+    }
+
+    if( d_x > s_x ) {
+        d_x += squareSize / 2 - squareSize / 4;
+    }
+    else if( d_x < s_x ) {
+        d_x += squareSize / 2 + squareSize / 4;
+    }
+    else {
+        d_x += squareSize / 2;
+    }
+
+    s_x += squareSize / 2;
+    s_y += squareSize / 2;
+
+    /* Adjust width */
+    A_WIDTH = squareSize / 14.; //[HGM] make float
+
+    DrawArrowBetweenPoints( s_x, s_y, d_x, d_y );
+    ArrowDamage(s_col, s_row, d_col, d_row);
+}
+
+Boolean
+IsDrawArrowEnabled ()
+{
+    return appData.highlightMoveWithArrow && squareSize >= 32;
+}
+
+void
+DrawArrowHighlight (int fromX, int fromY, int toX,int toY)
+{
+    if( IsDrawArrowEnabled() && fromX >= 0 && fromY >= 0 && toX >= 0 && toY >= 0)
+        DrawArrowBetweenSquares(fromX, fromY, toX, toY);
+}
+
+void
+UpdateLogos (int displ)
+{
+    return; // no logos in XBoard yet
+}
+