Let XBoard print version with argument --version or -v
[xboard.git] / xboard.c
index 3698728..e4c19e4 100644 (file)
--- a/xboard.c
+++ b/xboard.c
@@ -1,9 +1,11 @@
 /*
  * xboard.c -- X front end for XBoard
- * $Id$
  *
- * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
- * Enhancements Copyright 1992-2001 Free Software Foundation, Inc.
+ * Copyright 1991 by Digital Equipment Corporation, Maynard,
+ * Massachusetts. 
+ *
+ * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
+ * 2007, 2008, 2009 Free Software Foundation, Inc.
  *
  * The following terms apply to Digital Equipment Corporation's copyright
  * interest in XBoard:
  * SOFTWARE.
  * ------------------------------------------------------------------------
  *
- * The following terms apply to the enhanced version of XBoard distributed
- * by the Free Software Foundation:
+ * The following terms apply to the enhanced version of XBoard
+ * distributed by the Free Software Foundation:
  * ------------------------------------------------------------------------
- * This program is free software; you can redistribute it and/or modify
+ *
+ * GNU XBoard is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation, either version 3 of the License, or (at
+ * your option) any later version.
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * GNU XBoard is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * ------------------------------------------------------------------------
+ * along with this program. If not, see http://www.gnu.org/licenses/.  *
  *
- * See the file ChangeLog for a revision history.
- */
+ *------------------------------------------------------------------------
+ ** See the file ChangeLog for a revision history.  */
 
 #include "config.h"
 
@@ -143,6 +144,7 @@ extern char *getenv();
 #include <X11/Shell.h>
 #include <X11/cursorfont.h>
 #include <X11/Xatom.h>
+#include <X11/Xmu/Atoms.h>
 #if USE_XAW3D
 #include <X11/Xaw3d/Dialog.h>
 #include <X11/Xaw3d/Form.h>
@@ -169,6 +171,9 @@ extern char *getenv();
 #include <X11/Xaw/AsciiText.h>
 #endif
 
+// [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
+#include "common.h"
+
 #if HAVE_LIBXPM
 #include <X11/xpm.h>
 #include "pixmaps/pixmaps.h"
@@ -182,7 +187,6 @@ extern char *getenv();
 #include "bitmaps/icon_black.bm"
 #include "bitmaps/checkmark.bm"
 
-#include "common.h"
 #include "frontend.h"
 #include "backend.h"
 #include "moves.h"
@@ -193,6 +197,14 @@ extern char *getenv();
 #include "xedittags.h"
 #include "gettext.h"
 
+// must be moved to xengineoutput.h
+
+void EngineOutputProc P((Widget w, XEvent *event,
+                        String *prms, Cardinal *nprms));
+void EvalGraphProc P((Widget w, XEvent *event,
+                     String *prms, Cardinal *nprms));
+
+
 #ifdef __EMX__
 #ifndef HAVE_USLEEP
 #define HAVE_USLEEP
@@ -221,6 +233,7 @@ typedef struct {
 int main P((int argc, char **argv));
 RETSIGTYPE CmailSigHandler P((int sig));
 RETSIGTYPE IntSigHandler P((int sig));
+RETSIGTYPE TermSizeSigHandler P((int sig));
 void CreateGCs P((void));
 void CreateXIMPieces P((void));
 void CreateXPMPieces P((void));
@@ -249,7 +262,7 @@ void BlackClock P((Widget w, XEvent *event,
                   String *prms, Cardinal *nprms));
 void DrawPositionProc P((Widget w, XEvent *event,
                     String *prms, Cardinal *nprms));
-void XDrawPosition P((Widget w, /*Boolean*/int repaint, 
+void XDrawPosition P((Widget w, /*Boolean*/int repaint,
                     Board board));
 void CommentPopUp P((char *title, char *label));
 void CommentPopDown P((void));
@@ -269,7 +282,6 @@ void AskQuestionReplyAction P((Widget w, XEvent *event,
 void AskQuestionProc P((Widget w, XEvent *event,
                          String *prms, Cardinal *nprms));
 void AskQuestionPopDown P((void));
-void PromotionPopUp P((void));
 void PromotionPopDown P((void));
 void PromotionCallback P((Widget w, XtPointer client_data,
                          XtPointer call_data));
@@ -335,6 +347,9 @@ void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 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 EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void StopObservingProc P((Widget w, XEvent *event, String *prms,
                          Cardinal *nprms));
@@ -392,8 +407,12 @@ void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
                       Cardinal *nprms));
 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
                         Cardinal *nprms));
+void HideThinkingProc P((Widget w, XEvent *event, String *prms,
+                        Cardinal *nprms));
 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
                          Cardinal *nprms));
+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 HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
@@ -411,12 +430,24 @@ void ErrorPopUp P((char *title, char *text, int modal));
 void ErrorPopDown P((void));
 static char *ExpandPathName P((char *path));
 static void CreateAnimVars P((void));
-static void DragPieceBegin P((int x, int y));
 static void DragPieceMove P((int x, int y));
-static void DragPieceEnd P((int x, int y));
 static void DrawDragPiece P((void));
 char *ModeToWidgetName P((GameMode mode));
-
+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 NewVariantProc 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 update_ics_width P(());
+int get_term_width P(());
 /*
 * XBoard depends on Xt R4 or higher
 */
@@ -427,30 +458,38 @@ Display *xDisplay;
 Window xBoardWindow;
 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
   jailSquareColor, highlightSquareColor, premoveHighlightColor;
+Pixel lowTimeWarningColor;
 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
   bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
-  wjPieceGC, bjPieceGC, prelineGC;
+  wjPieceGC, bjPieceGC, prelineGC, countGC;
 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
-Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget, 
-  whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16], 
+Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
+  whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
   commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
   menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
   ICSInputShell, fileNameShell, askQuestionShell;
-XSegment gridSegments[(BOARD_SIZE + 1) * 2];
-XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
-Font clockFontID, coordFontID;
-XFontStruct *clockFontStruct, *coordFontStruct;
+Widget historyShell, evalGraphShell, gameListShell;
+XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
+XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
+Font clockFontID, coordFontID, countFontID;
+XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
 XtAppContext appContext;
 char *layoutName;
 char *oldICSInteractionTitle;
 
 FileProc fileProc;
 char *fileOpenMode;
+char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
 
 Position commentX = -1, commentY = -1;
 Dimension commentW, commentH;
+typedef unsigned int BoardSize;
+BoardSize boardSize;
+Boolean chessProgram;
 
+int  minX, minY; // [HGM] placement: volatile limits on upper-left corner
 int squareSize, smallLayout = 0, tinyLayout = 0,
+  marginW, marginH, // [HGM] for run-time resizing
   fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
   ICSInputBoxUp = False, askQuestionUp = False,
   filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
@@ -459,20 +498,39 @@ Pixel timerForegroundPixel, timerBackgroundPixel;
 Pixel buttonForegroundPixel, buttonBackgroundPixel;
 char *chessDir, *programName, *programVersion,
   *gameCopyFilename, *gamePasteFilename;
+Boolean alwaysOnTop = False;
+Boolean saveSettingsOnExit;
+char *settingsFileName;
+char *icsTextMenuString;
+char *icsNames;
+char *firstChessProgramNames;
+char *secondChessProgramNames;
+
+WindowPlacement wpMain;
+WindowPlacement wpConsole;
+WindowPlacement wpComment;
+WindowPlacement wpMoveHistory;
+WindowPlacement wpEvalGraph;
+WindowPlacement wpEngineOutput;
+WindowPlacement wpGameList;
+WindowPlacement wpTags;
 
 #define SOLID 0
 #define OUTLINE 1
-Pixmap pieceBitmap[2][6];
-Pixmap xpmPieceBitmap[4][6];   /* LL, LD, DL, DD */
+Pixmap pieceBitmap[2][(int)BlackPawn];
+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;
-XImage *ximPieceBitmap[4][6];  /* LL, LD, DL, DD */
-Pixmap ximMaskPm[6];            /* clipmasks, used for XIM pieces */
+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 */
 XImage *ximLightSquare, *ximDarkSquare;
 XImage *xim_Cross;
 
-#define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % 6]
-#define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % 6]
+#define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
+#define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
 
 #define White(piece) ((int)(piece) < (int)BlackPawn)
 
@@ -508,7 +566,9 @@ static Pixmap xpmMask[BlackKing + 1];
 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
 
 MenuItem fileMenu[] = {
-    {N_("Reset Game"), ResetProc},
+    {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},
@@ -546,8 +606,11 @@ MenuItem modeMenu[] = {
     {N_("Edit Position"), EditPositionProc},
     {N_("Training"), TrainingProc},
     {"----", NothingProc},
+    {N_("Show Engine Output"), EngineOutputProc},
+    {N_("Show Evaluation Graph"), EvalGraphProc},
     {N_("Show Game List"), ShowGameListProc},
-    {N_("Show Move List"), HistoryShowProc},
+    {N_("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},
@@ -559,15 +622,19 @@ MenuItem actionMenu[] = {
     {N_("Accept"), AcceptProc},
     {N_("Decline"), DeclineProc},
     {N_("Rematch"), RematchProc},
-    {"----", NothingProc},    
+    {"----", NothingProc},
     {N_("Call Flag"), CallFlagProc},
     {N_("Draw"), DrawProc},
     {N_("Adjourn"), AdjournProc},
     {N_("Abort"), AbortProc},
     {N_("Resign"), ResignProc},
-    {"----", NothingProc},    
+    {"----", 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}
 };
 
@@ -578,13 +645,21 @@ MenuItem stepMenu[] = {
     {N_("Forward to End"), ToEndProc},
     {N_("Revert"), RevertProc},
     {N_("Truncate Game"), TruncateGameProc},
-    {"----", NothingProc},    
+    {"----", NothingProc},
     {N_("Move Now"), MoveNowProc},
     {N_("Retract Move"), RetractMoveProc},
     {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},
@@ -596,7 +671,6 @@ MenuItem optionsMenu[] = {
     {N_("Auto Save"), AutosaveProc},
     {N_("Blindfold"), BlindfoldProc},
     {N_("Flash Moves"), FlashMovesProc},
-    {N_("Flip View"), FlipViewProc},
     {N_("Get Move List"), GetMoveListProc},
 #if HIGHDRAG
     {N_("Highlight Dragging"), HighlightDraggingProc},
@@ -605,15 +679,18 @@ MenuItem optionsMenu[] = {
     {N_("Move Sound"), MoveSoundProc},
     {N_("ICS Alarm"), IcsAlarmProc},
     {N_("Old Save Style"), OldSaveStyleProc},
-    {N_("Periodic Updates"), PeriodicUpdatesProc},     
+    {N_("Periodic Updates"), PeriodicUpdatesProc},
     {N_("Ponder Next Move"), PonderNextMoveProc},
-    {N_("Popup Exit Message"), PopupExitMessageProc},  
-    {N_("Popup Move Errors"), PopupMoveErrorsProc},    
+    {N_("Popup Exit Message"), PopupExitMessageProc},
+    {N_("Popup Move Errors"), PopupMoveErrorsProc},
     {N_("Premove"), PremoveProc},
     {N_("Quiet Play"), QuietPlayProc},
     {N_("Show Coords"), ShowCoordsProc},
-    {N_("Show Thinking"), ShowThinkingProc},
+    {N_("Hide Thinking"), HideThinkingProc},
     {N_("Test Legality"), TestLegalityProc},
+    {"----", NothingProc},
+    {N_("Save Settings Now"), SaveSettingsProc},
+    {N_("Save Settings on Exit"), SaveOnExitProc},
     {NULL, NULL}
 };
 
@@ -638,8 +715,6 @@ Menu menuBar[] = {
     {NULL, NULL}
 };
 
-
-/* Label on pause button */
 #define PAUSE_BUTTON N_("P")
 MenuItem buttonBar[] = {
     {"<<", ToStartProc},
@@ -650,21 +725,27 @@ MenuItem buttonBar[] = {
     {NULL, NULL}
 };
 
-#define PIECE_MENU_SIZE 11
+#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_("Empty square"), N_("Clear board") },
+      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_("Empty square"), N_("Clear board") },
-  };
+      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! */
 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
     { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
-       WhiteRook, WhiteQueen, WhiteKing,
-       (ChessSquare) 0, EmptySquare, ClearBoard },
+       WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
+       WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0, 
+       PromotePiece, DemotePiece, EmptySquare, ClearBoard },
     { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
-       BlackRook, BlackQueen, BlackKing,
-       (ChessSquare) 0, EmptySquare, ClearBoard },
+       BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
+       BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0, 
+       PromotePiece, DemotePiece, EmptySquare, ClearBoard },
 };
 
 #define DROP_MENU_SIZE 6
@@ -735,715 +816,17 @@ Arg timerArgs[] = {
 };
 
 XtResource clientResources[] = {
-    { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, whitePieceColor), XtRString,
-       WHITE_PIECE_COLOR },
-    { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, blackPieceColor), XtRString,
-       BLACK_PIECE_COLOR },
-    { "lightSquareColor", "lightSquareColor", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
-       XtRString, LIGHT_SQUARE_COLOR }, 
-    { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, darkSquareColor), XtRString,
-       DARK_SQUARE_COLOR },
-    { "highlightSquareColor", "highlightSquareColor", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
-       XtRString, HIGHLIGHT_SQUARE_COLOR },
-    { "premoveHighlightColor", "premoveHighlightColor", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
-       XtRString, PREMOVE_HIGHLIGHT_COLOR },
-    { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
-       XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
-       (XtPointer) MOVES_PER_SESSION },
-    { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
-       XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
-       (XtPointer) TIME_INCREMENT },
-    { "initString", "initString", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
-    { "secondInitString", "secondInitString", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
-    { "firstComputerString", "firstComputerString", XtRString,
-        sizeof(String),        XtOffset(AppDataPtr, firstComputerString), XtRString,
-      COMPUTER_STRING },
-    { "secondComputerString", "secondComputerString", XtRString,
-        sizeof(String),        XtOffset(AppDataPtr, secondComputerString), XtRString,
-      COMPUTER_STRING },
-    { "firstChessProgram", "firstChessProgram", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
-       XtRString, FIRST_CHESS_PROGRAM },
-    { "secondChessProgram", "secondChessProgram", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
-       XtRString, SECOND_CHESS_PROGRAM },
-    { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
-       XtRImmediate, (XtPointer) False },
-    { "noChessProgram", "noChessProgram", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
-       XtRImmediate, (XtPointer) False },
-    { "firstHost", "firstHost", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
-    { "secondHost", "secondHost", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
-    { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, firstDirectory), XtRString, "" },
-    { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, secondDirectory), XtRString, "" },
-    { "bitmapDirectory", "bitmapDirectory", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
-       XtRString, "" },
-    { "remoteShell", "remoteShell", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
-    { "remoteUser", "remoteUser", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, remoteUser), XtRString, "" },
-    { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
-       XtOffset(AppDataPtr, timeDelay), XtRString,
-       (XtPointer) TIME_DELAY_QUOTE },
-    { "timeControl", "timeControl", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, timeControl), XtRString,
-       (XtPointer) TIME_CONTROL },
-    { "internetChessServerMode", "internetChessServerMode",
-       XtRBoolean, sizeof(Boolean),
-       XtOffset(AppDataPtr, icsActive), XtRImmediate,
-       (XtPointer) False },
-    { "internetChessServerHost", "internetChessServerHost",
-       XtRString, sizeof(String),
-       XtOffset(AppDataPtr, icsHost),
-       XtRString, (XtPointer) ICS_HOST },
-    { "internetChessServerPort", "internetChessServerPort",
-       XtRString, sizeof(String),
-       XtOffset(AppDataPtr, icsPort), XtRString,
-       (XtPointer) ICS_PORT },
-    { "internetChessServerCommPort", "internetChessServerCommPort",
-       XtRString, sizeof(String),
-       XtOffset(AppDataPtr, icsCommPort), XtRString,
-       ICS_COMM_PORT },
-    { "internetChessServerLogonScript", "internetChessServerLogonScript",
-       XtRString, sizeof(String),
-       XtOffset(AppDataPtr, icsLogon), XtRString,
-       ICS_LOGON },
-    { "internetChessServerHelper", "internetChessServerHelper",
-       XtRString, sizeof(String),
-       XtOffset(AppDataPtr, icsHelper), XtRString, "" },
-    { "internetChessServerInputBox", "internetChessServerInputBox",
-       XtRBoolean, sizeof(Boolean),
-       XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
-       (XtPointer) False },
-    { "icsAlarm", "icsAlarm",
-       XtRBoolean, sizeof(Boolean),
-       XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
-       (XtPointer) True },
-    { "icsAlarmTime", "icsAlarmTime",
-       XtRInt, sizeof(int),
-       XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
-       (XtPointer) 5000 },
-    { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
-       XtOffset(AppDataPtr, useTelnet), XtRImmediate,
-       (XtPointer) False },
-    { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
-    { "gateway", "gateway", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, gateway), XtRString, "" },
-    { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
-    { "loadGameIndex", "loadGameIndex",
-       XtRInt, sizeof(int),
-       XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
-       (XtPointer) 0 },
-    { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
-    { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
-       XtRImmediate, (XtPointer) True },
-    { "autoSaveGames", "autoSaveGames", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
-       XtRImmediate, (XtPointer) False },
-    { "blindfold", "blindfold", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
-       XtRImmediate, (XtPointer) False },
-    { "loadPositionFile", "loadPositionFile", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
-       XtRString, "" },
-    { "loadPositionIndex", "loadPositionIndex",
-       XtRInt, sizeof(int),
-       XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
-       (XtPointer) 1 },
-    { "savePositionFile", "savePositionFile", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, savePositionFile),
-       XtRString, "" },
-    { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
-       XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
-    { "matchGames", "matchGames", XtRInt, sizeof(int),
-       XtOffset(AppDataPtr, matchGames), XtRImmediate,
-       (XtPointer) 0 },
-    { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
-       XtOffset(AppDataPtr, monoMode), XtRImmediate,
-       (XtPointer) False },
-    { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
-       XtOffset(AppDataPtr, debugMode), XtRImmediate,
-       (XtPointer) False },
-    { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
-       XtOffset(AppDataPtr, clockMode), XtRImmediate,
-       (XtPointer) True },
-    { "boardSize", "boardSize", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, boardSize), XtRString, "" },
-    { "searchTime", "searchTime", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, searchTime), XtRString,
-       (XtPointer) "" },
-    { "searchDepth", "searchDepth", XtRInt, sizeof(int),
-       XtOffset(AppDataPtr, searchDepth), XtRImmediate, 
-       (XtPointer) 0 },
-    { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
-       XtOffset(AppDataPtr, showCoords), XtRImmediate,
-       (XtPointer) False },
-    { "showJail", "showJail", XtRInt, sizeof(int),
-       XtOffset(AppDataPtr, showJail), XtRImmediate,
-       (XtPointer) 0 },
-    { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
-       XtOffset(AppDataPtr, showThinking), XtRImmediate,
-       (XtPointer) False },
-    { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
-       XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
-       (XtPointer) True },
-    { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
-       XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
-       (XtPointer) True },
-    { "clockFont", "clockFont", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
-    { "coordFont", "coordFont", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
-    { "font", "font", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
-    { "ringBellAfterMoves", "ringBellAfterMoves",
-       XtRBoolean, sizeof(Boolean),
-       XtOffset(AppDataPtr, ringBellAfterMoves),
-       XtRImmediate, (XtPointer) False },
-    { "autoCallFlag", "autoCallFlag", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
-       XtRImmediate, (XtPointer) False },
-    { "autoFlipView", "autoFlipView", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
-       XtRImmediate, (XtPointer) True },
-    { "autoObserve", "autoObserve", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
-       XtRImmediate, (XtPointer) False },
-    { "autoComment", "autoComment", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
-       XtRImmediate, (XtPointer) False },
-    { "getMoveList", "getMoveList", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
-       XtRImmediate, (XtPointer) True },
-#if HIGHDRAG
-    { "highlightDragging", "highlightDragging", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
-       XtRImmediate, (XtPointer) False },
-#endif
-    { "highlightLastMove", "highlightLastMove", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
-       XtRImmediate, (XtPointer) False },
-    { "premove", "premove", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, premove),
-        XtRImmediate, (XtPointer) True },
-    { "testLegality", "testLegality", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
-       XtRImmediate, (XtPointer) True },
-    { "flipView", "flipView", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, flipView),
-       XtRImmediate, (XtPointer) False },
-    { "cmail", "cmailGameName", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
-    { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
-       XtRImmediate, (XtPointer) False },
-    { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
-       XtRImmediate, (XtPointer) False },
-    { "quietPlay", "quietPlay", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
-       XtRImmediate, (XtPointer) False },
-    { "titleInWindow", "titleInWindow", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
-       XtRImmediate, (XtPointer) False },
-    { "localLineEditing", "localLineEditing", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
-       XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
-#ifdef ZIPPY
-    { "zippyTalk", "zippyTalk", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
-       XtRImmediate, (XtPointer) ZIPPY_TALK },
-    { "zippyPlay", "zippyPlay", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
-       XtRImmediate, (XtPointer) ZIPPY_PLAY },
-    { "zippyLines", "zippyLines", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
-    { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
-        XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
-    { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
-    { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
-    { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
-        ZIPPY_WRONG_PASSWORD },
-    { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
-    { "zippyUseI", "zippyUseI", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
-        XtRImmediate, (XtPointer) ZIPPY_USE_I },
-    { "zippyBughouse", "zippyBughouse", XtRInt,
-       sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
-       XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
-    { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
-        XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
-    { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
-    { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
-    { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
-       XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
-    { "zippyAbort", "zippyAbort", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
-       XtRImmediate, (XtPointer) ZIPPY_ABORT },
-    { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
-       XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
-    { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
-       XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
-        (XtPointer) ZIPPY_MAX_GAMES },
-    { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
-       XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
-        (XtPointer) ZIPPY_REPLAY_TIMEOUT },
-#endif
     { "flashCount", "flashCount", XtRInt, sizeof(int),
        XtOffset(AppDataPtr, flashCount), XtRImmediate,
        (XtPointer) FLASH_COUNT  },
-    { "flashRate", "flashRate", XtRInt, sizeof(int),
-       XtOffset(AppDataPtr, flashRate), XtRImmediate,
-       (XtPointer) FLASH_RATE },
-    { "pixmapDirectory", "pixmapDirectory", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
-       XtRString, "" },
-    { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
-       XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
-       (XtPointer) MS_LOGIN_DELAY },
-    { "colorizeMessages", "colorizeMessages", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, colorize),
-       XtRImmediate, (XtPointer) False },      
-    { "colorShout", "colorShout", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, colorShout),
-       XtRString, COLOR_SHOUT },
-    { "colorSShout", "colorSShout", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, colorSShout),
-       XtRString, COLOR_SSHOUT },
-    { "colorChannel1", "colorChannel1", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, colorChannel1),
-       XtRString, COLOR_CHANNEL1 },
-    { "colorChannel", "colorChannel", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, colorChannel),
-       XtRString, COLOR_CHANNEL },
-    { "colorKibitz", "colorKibitz", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, colorKibitz),
-       XtRString, COLOR_KIBITZ },
-    { "colorTell", "colorTell", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, colorTell),
-       XtRString, COLOR_TELL },
-    { "colorChallenge", "colorChallenge", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, colorChallenge),
-       XtRString, COLOR_CHALLENGE },
-    { "colorRequest", "colorRequest", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, colorRequest),
-       XtRString, COLOR_REQUEST },
-    { "colorSeek", "colorSeek", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, colorSeek),
-       XtRString, COLOR_SEEK },
-    { "colorNormal", "colorNormal", XtRString,
-       sizeof(String), XtOffset(AppDataPtr, colorNormal),
-       XtRString, COLOR_NORMAL },      
-    { "soundProgram", "soundProgram", XtRString,
-      sizeof(String), XtOffset(AppDataPtr, soundProgram),
-      XtRString, "play" },
-    { "soundShout", "soundShout", XtRString,
-      sizeof(String), XtOffset(AppDataPtr, soundShout),
-      XtRString, "" },
-    { "soundSShout", "soundSShout", XtRString,
-      sizeof(String), XtOffset(AppDataPtr, soundSShout),
-      XtRString, "" },
-    { "soundChannel1", "soundChannel1", XtRString,
-      sizeof(String), XtOffset(AppDataPtr, soundChannel1),
-      XtRString, "" },
-    { "soundChannel", "soundChannel", XtRString,
-      sizeof(String), XtOffset(AppDataPtr, soundChannel),
-      XtRString, "" },
-    { "soundKibitz", "soundKibitz", XtRString,
-      sizeof(String), XtOffset(AppDataPtr, soundKibitz),
-      XtRString, "" },
-    { "soundTell", "soundTell", XtRString,
-      sizeof(String), XtOffset(AppDataPtr, soundTell),
-      XtRString, "" },
-    { "soundChallenge", "soundChallenge", XtRString,
-      sizeof(String), XtOffset(AppDataPtr, soundChallenge),
-      XtRString, "" },
-    { "soundRequest", "soundRequest", XtRString,
-      sizeof(String), XtOffset(AppDataPtr, soundRequest),
-      XtRString, "" },
-    { "soundSeek", "soundSeek", XtRString,
-      sizeof(String), XtOffset(AppDataPtr, soundSeek),
-      XtRString, "" },
-    { "soundMove", "soundMove", XtRString,
-      sizeof(String), XtOffset(AppDataPtr, soundMove),
-      XtRString, "$" },
-    { "soundIcsWin", "soundIcsWin", XtRString,
-      sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
-      XtRString, "" },
-    { "soundIcsLoss", "soundIcsLoss", XtRString,
-      sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
-      XtRString, "" },
-    { "soundIcsDraw", "soundIcsDraw", XtRString,
-      sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
-      XtRString, "" },
-    { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
-      sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
-      XtRString, "" },
-    { "soundIcsAlarm", "soundIcsAlarm", XtRString,
-      sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
-      XtRString, "$" },
-    { "reuseFirst", "reuseFirst", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
-       XtRImmediate, (XtPointer) True },
-    { "reuseSecond", "reuseSecond", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
-       XtRImmediate, (XtPointer) True },
-    { "animateDragging", "animateDragging", XtRBoolean,
-        sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
-       XtRImmediate, (XtPointer) True },
-    { "animateMoving", "animateMoving", XtRBoolean,
-        sizeof(Boolean), XtOffset(AppDataPtr, animate),
-       XtRImmediate, (XtPointer) True },
-    { "animateSpeed", "animateSpeed", XtRInt,
-        sizeof(int), XtOffset(AppDataPtr, animSpeed),
-       XtRImmediate, (XtPointer)10 },
-    { "popupExitMessage", "popupExitMessage", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
-       XtRImmediate, (XtPointer) True },
-    { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
-       XtRImmediate, (XtPointer) False },
-    { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
-        sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
-       XtRImmediate, (XtPointer)4 },
-    { "initialMode", "initialMode", XtRString,
-        sizeof(String), XtOffset(AppDataPtr, initialMode),
-       XtRImmediate, (XtPointer) "" },
-    { "variant", "variant", XtRString,
-        sizeof(String), XtOffset(AppDataPtr, variant),
-       XtRImmediate, (XtPointer) "normal" },
-    { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
-        sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
-       XtRImmediate, (XtPointer)PROTOVER },
-    { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
-        sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
-       XtRImmediate, (XtPointer)PROTOVER },
-    { "showButtonBar", "showButtonBar", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
-       XtRImmediate, (XtPointer) True },
-       /* icsEngineAnalyze */
-    {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean,
-       sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
-       XtRImmediate, (XtPointer) False },
 };
 
 XrmOptionDescRec shellOptions[] = {
-    { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
-    { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
-    { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
-    { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
-    { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
-    { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
-    { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
-    { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
-    { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
-    { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
-    { "-initString", "initString", XrmoptionSepArg, NULL },
-    { "-firstInitString", "initString", XrmoptionSepArg, NULL },
-    { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
-    { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
-    { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
-    { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
-    { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
-    { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
-    { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
-    { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
-    { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
-    { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
-    { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
-    { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
-    { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
-    { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
-    { "-fh", "firstHost", XrmoptionSepArg, NULL },
-    { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
-    { "-sh", "secondHost", XrmoptionSepArg, NULL },
-    { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
-    { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
-    { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
-    { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
-    { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
-    { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
-    { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
-    { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
-    { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
-    { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
-    { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
-    { "-td", "timeDelay", XrmoptionSepArg, NULL },
-    { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
-    { "-tc", "timeControl", XrmoptionSepArg, NULL },
-    { "-internetChessServerMode", "internetChessServerMode",
-       XrmoptionSepArg, NULL },
-    { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
-    { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
-    { "-internetChessServerHost", "internetChessServerHost",
-       XrmoptionSepArg, NULL },
-    { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
-    { "-internetChessServerPort", "internetChessServerPort",
-       XrmoptionSepArg, NULL },
-    { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
-    { "-internetChessServerCommPort", "internetChessServerCommPort",
-       XrmoptionSepArg, NULL },
-    { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
-    { "-internetChessServerLogonScript", "internetChessServerLogonScript",
-       XrmoptionSepArg, NULL },
-    { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
-    { "-internetChessServerHelper", "internetChessServerHelper",
-       XrmoptionSepArg, NULL },
-    { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
-    { "-internetChessServerInputBox", "internetChessServerInputBox",
-       XrmoptionSepArg, NULL },
-    { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
-    { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
-    { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
-    { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
-    { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
-    { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
-    { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
-    { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
-    { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
-    { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
-    { "-gateway", "gateway", XrmoptionSepArg, NULL },
-    { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
-    { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
-    { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
-    { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
-    { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
-    { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
-    { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
-    { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
-    { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
-    { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
-    { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
-    { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
-    { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
-    { "-blind", "blindfold", XrmoptionNoArg, "True" },
-    { "-xblind", "blindfold", XrmoptionNoArg, "False" },
-    { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
-    { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
-    { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
-    { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
-    { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
-    { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
-    { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
-    { "-mm", "matchMode", XrmoptionNoArg, "True" },
-    { "-xmm", "matchMode", XrmoptionNoArg, "False" },
-    { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
-    { "-mg", "matchGames", XrmoptionSepArg, NULL },
-    { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
-    { "-mono", "monoMode", XrmoptionNoArg, "True" },
-    { "-xmono", "monoMode", XrmoptionNoArg, "False" },
-    { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
-    { "-debug", "debugMode", XrmoptionNoArg, "True" },
-    { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
-    { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
-    { "-clock", "clockMode", XrmoptionNoArg, "True" },
-    { "-xclock", "clockMode", XrmoptionNoArg, "False" },
-    { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
-    { "-size", "boardSize", XrmoptionSepArg, NULL },
-    { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
-    { "-st", "searchTime", XrmoptionSepArg, NULL },
-    { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
-    { "-depth", "searchDepth", XrmoptionSepArg, NULL },
-    { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
-    { "-coords", "showCoords", XrmoptionNoArg, "True" },
-    { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
-#if JAIL
-    { "-showJail", "showJail", XrmoptionSepArg, NULL },
-    { "-jail", "showJail", XrmoptionNoArg, "1" },
-    { "-sidejail", "showJail", XrmoptionNoArg, "2" },
-    { "-xjail", "showJail", XrmoptionNoArg, "0" },
-#endif
-    { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
-    { "-thinking", "showThinking", XrmoptionNoArg, "True" },
-    { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
-    { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
-    { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
-    { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
-    { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
-    { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
-    { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
-    { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
-    { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
-    { "-font", "font", XrmoptionSepArg, NULL },
-    { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
-    { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
-    { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
-    { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
-    { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
-    { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
-    { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
-    { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
-    { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
-    { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
-    { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
-    { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
-    { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
-    { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
-    { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
-    { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
-    { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
-    { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
-    { "-moves", "getMoveList", XrmoptionNoArg, "True" },
-    { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
-#if HIGHDRAG
-    { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
-    { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
-    { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
-#endif
-    { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
-    { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
-    { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
-    { "-premove", "premove", XrmoptionSepArg, NULL },
-    { "-pre", "premove", XrmoptionNoArg, "True" },
-    { "-xpre", "premove", XrmoptionNoArg, "False" },
-    { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
-    { "-legal", "testLegality", XrmoptionNoArg, "True" },
-    { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
-    { "-flipView", "flipView", XrmoptionSepArg, NULL },
-    { "-flip", "flipView", XrmoptionNoArg, "True" },
-    { "-xflip", "flipView", XrmoptionNoArg, "False" },
-    { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
-    { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
-       XrmoptionSepArg, NULL },
-    { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
-    { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
-    { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
-    { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
-    { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
-    { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
-    { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
-    { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
-    { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
-    { "-title", "titleInWindow", XrmoptionNoArg, "True" },
-    { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
-#ifdef ZIPPY
-    { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
-    { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
-    { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
-    { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
-    { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
-    { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
-    { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
-    { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
-    { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
-    { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
-    { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
-    { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
-    { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
-    { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
-    { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
-    { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
-    { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
-    { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
-    { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
-    { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
-    { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
-    { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
-    { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
-    { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
-    { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
-    { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
-    { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
-    { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
-    { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
-    { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
-#endif
     { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
     { "-flash", "flashCount", XrmoptionNoArg, "3" },
     { "-xflash", "flashCount", XrmoptionNoArg, "0" },
-    { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
-    { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
-    { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
-    { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
-    { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
-    { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
-    { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
-    { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
-    { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
-    { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
-    { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
-    { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
-    { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
-    { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
-    { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
-    { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
-    { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
-    { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
-    { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
-    { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
-    { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
-    { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
-    { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
-    { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
-    { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
-    { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
-    { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
-    { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
-    { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
-    { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
-    { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
-    { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
-    { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
-    { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
-    { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
-    { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
-    { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
-    { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
-    { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
-    { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
-    { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
-    { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
-    { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
-    { "-animate", "animateMoving", XrmoptionNoArg, "True" },
-    { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
-    { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
-    { "-drag", "animateDragging", XrmoptionNoArg, "True" },
-    { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
-    { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
-    { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
-    { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
-    { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
-    { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
-    { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
-    { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
-    { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
-    { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
-    { "-mode", "initialMode", XrmoptionSepArg, NULL },
-    { "-variant", "variant", XrmoptionSepArg, NULL },
-    { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
-    { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
-    { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
-    { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
-    { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
 };
 
-
 XtActionsRec boardActions[] = {
     { "DrawPosition", DrawPositionProc },
     { "HandleUserMove", HandleUserMove },
@@ -1483,6 +866,8 @@ XtActionsRec boardActions[] = {
     { "EditGameProc", EditGameProc },
     { "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 },
@@ -1498,6 +883,9 @@ XtActionsRec boardActions[] = {
     { "AdjournProc", AdjournProc },
     { "AbortProc", AbortProc },
     { "ResignProc", ResignProc },
+    { "AdjuWhiteProc", AdjuWhiteProc },
+    { "AdjuBlackProc", AdjuBlackProc },
+    { "AdjuDrawProc", AdjuDrawProc },
     { "EnterKeyProc", EnterKeyProc },
     { "StopObservingProc", StopObservingProc },
     { "StopExaminingProc", StopExaminingProc },
@@ -1528,15 +916,18 @@ XtActionsRec boardActions[] = {
     { "IcsAlarmProc", IcsAlarmProc },
     { "MoveSoundProc", MoveSoundProc },
     { "OldSaveStyleProc", OldSaveStyleProc },
-    { "PeriodicUpdatesProc", PeriodicUpdatesProc },    
+    { "PeriodicUpdatesProc", PeriodicUpdatesProc },
     { "PonderNextMoveProc", PonderNextMoveProc },
-    { "PopupExitMessageProc", PopupExitMessageProc },  
-    { "PopupMoveErrorsProc", PopupMoveErrorsProc },    
+    { "PopupExitMessageProc", PopupExitMessageProc },
+    { "PopupMoveErrorsProc", PopupMoveErrorsProc },
     { "PremoveProc", PremoveProc },
     { "QuietPlayProc", QuietPlayProc },
     { "ShowCoordsProc", ShowCoordsProc },
     { "ShowThinkingProc", ShowThinkingProc },
+    { "HideThinkingProc", HideThinkingProc },
     { "TestLegalityProc", TestLegalityProc },
+    { "SaveSettingsProc", SaveSettingsProc },
+    { "SaveOnExitProc", SaveOnExitProc },
     { "InfoProc", InfoProc },
     { "ManProc", ManProc },
     { "HintProc", HintProc },
@@ -1550,14 +941,21 @@ XtActionsRec boardActions[] = {
     { "TagsPopDown", (XtActionProc) TagsPopDown },
     { "ErrorPopDown", (XtActionProc) ErrorPopDown },
     { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
-    { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
     { "FileNamePopDown", (XtActionProc) FileNamePopDown },
     { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
     { "GameListPopDown", (XtActionProc) GameListPopDown },
     { "PromotionPopDown", (XtActionProc) PromotionPopDown },
     { "HistoryPopDown", (XtActionProc) HistoryPopDown },
+    { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
+    { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
+    { "ShufflePopDown", (XtActionProc) ShufflePopDown },
+    { "EnginePopDown", (XtActionProc) EnginePopDown },
+    { "UciPopDown", (XtActionProc) UciPopDown },
+    { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
+    { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
+    { "SettingsPopDown", (XtActionProc) SettingsPopDown },
 };
-     
+
 char globalTranslations[] =
   ":<Key>R: ResignProc() \n \
    :<Key>r: ResetProc() \n \
@@ -1596,10 +994,10 @@ char boardTranslations[] =
                  PieceMenuPopup(menuW) \n \
    Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
                  PieceMenuPopup(menuB) \n";
-     
+
 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
-     
+
 char ICSInputTranslations[] =
     "<Key>Return: EnterKeyProc() \n";
 
@@ -1609,7 +1007,7 @@ String xboardResources[] = {
     "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
     NULL
   };
-     
+
 
 /* Max possible square size */
 #define MAXSQSIZE 256
@@ -1627,14 +1025,14 @@ xpm_getsize(name, len, ext)
 {
     char *p, *d;
     char buf[10];
-  
+
     if (len < 4)
       return 0;
 
     if ((p=strchr(name, '.')) == NULL ||
        StrCaseCmp(p+1, ext) != 0)
       return 0;
-  
+
     p = name + 3;
     d = buf;
 
@@ -1660,15 +1058,15 @@ xpm_getavail(dirname, ext)
 
     if (appData.debugMode)
       fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
-  
+
     dir = opendir(dirname);
     if (!dir)
       {
-         fprintf(stderr, _("%s: Can't access XPM directory %s\n"), 
+         fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
                  programName, dirname);
          exit(1);
       }
-  
+
     while ((ent=readdir(dir)) != NULL) {
        i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
        if (i > 0 && i < MAXSQSIZE)
@@ -1705,12 +1103,12 @@ xpm_closest_to(dirname, size, ext)
     int sm_diff = MAXSQSIZE;
     int sm_index = 0;
     int diff;
-  
+
     xpm_getavail(dirname, ext);
 
     if (appData.debugMode)
       xpm_print_avail(stderr, ext);
-  
+
     for (i=1; i<MAXSQSIZE; ++i) {
        if (xpm_avail[i]) {
            diff = size - i;
@@ -1763,7 +1161,7 @@ parse_color(str, which)
 {
     char *p, buf[100], *d;
     int i;
-  
+
     if (strlen(str) > 99)      /* watch bounds on buf */
       return -1;
 
@@ -1785,10 +1183,10 @@ parse_color(str, which)
     if (*p == ',') {
        return -1;              /* Use default for empty field */
     }
-    
+
     if (which == 2 || isdigit(*p))
       return atoi(p);
+
     while (*p && isalpha(*p))
       *(d++) = *(p++);
 
@@ -1831,7 +1229,7 @@ CatchDeleteWindow(Widget w, String procname)
 {
   char buf[MSG_SIZ];
   XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
-  sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);
+  snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
   XtAugmentTranslations(w, XtParseTranslationTable(buf));
 }
 
@@ -1845,6 +1243,407 @@ BoardToTop()
   XtPopup(shellWidget, XtGrabNone); /* Raise if lowered  */
 }
 
+//---------------------------------------------------------------------------------------------------------
+// some symbol definitions to provide the proper (= XBoard) context for the code in args.h
+#define XBOARD True
+#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 MoveHistoryIsUp();
+Boolean GameListIsUp();
+
+// The option definition and parsing code common to XBoard and WinBoard is collected in this file
+#include "args.h"
+
+// 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.lightSquareColor,
+  &appData.darkSquareColor, 
+  &appData.highlightSquareColor,
+  &appData.premoveHighlightColor,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  &crWhite,
+  &crBlack,
+  NULL
+};
+
+void
+ParseFont(char *name, int number)
+{ // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
+  switch(number) {
+    case 0: // CLOCK_FONT
+       appData.clockFont = strdup(name);
+      break;
+    case 1: // MESSAGE_FONT
+       appData.font = strdup(name);
+      break;
+    case 2: // COORD_FONT
+       appData.coordFont = strdup(name);
+      break;
+    default:
+      return;
+  }
+}
+
+void
+SetFontDefaults()
+{ // only 2 fonts currently
+  appData.clockFont = CLOCK_FONT_NAME;
+  appData.coordFont = COORD_FONT_NAME;
+  appData.font  =   DEFAULT_FONT_NAME;
+}
+
+void
+CreateFonts()
+{ // no-op, until we identify the code for this already in XBoard and move it here
+}
+
+void
+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)
+{   
+    (&appData.colorShout)[cc] = strdup(s);
+}
+
+void
+ParseBoardSize(void *addr, char *name)
+{
+    appData.boardSize = strdup(name);
+}
+
+void
+LoadAllSounds()
+{ // In XBoard the sound-playing program takes care of obtaining the actual sound
+}
+
+void
+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)
+{
+  char *name;
+  switch((int)ad->argLoc) {
+    case 0: // CLOCK_FONT
+       name = appData.clockFont;
+      break;
+    case 1: // MESSAGE_FONT
+       name = appData.font;
+      break;
+    case 2: // COORD_FONT
+       name = appData.coordFont;
+      break;
+    default:
+      return;
+  }
+//  Do not save fonts for now, as the saved font would be board-size specific
+//  and not suitable for a re-start at another board size
+//  fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, name); 
+}
+
+void
+ExportSounds()
+{ // nothing to do, as the sounds are at all times represented by their text-string names already
+}
+
+void
+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]);
+}
+
+void
+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]);
+}
+
+void
+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)
+{ // no such option in XBoard (yet)
+}
+
+extern Widget engineOutputShell;
+extern Widget tagsShell, editTagsShell;
+void
+GetActualPlacement(Widget wg, WindowPlacement *wp)
+{
+  Arg args[16];
+  Dimension w, h;
+  Position x, y;
+  int i;
+
+  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;
+}
+
+void
+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(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);
+}
+
+void
+PrintCommPortSettings(FILE *f, char *name)
+{ // This option does not exist in XBoard
+}
+
+int
+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 {
+    sprintf(fullname, "%s%c%s", installDir, '/', name);
+  }
+  return 1;
+}
+
+int
+MyGetFullPathName(char *name, char *fullname)
+{ // should use ExpandPath?
+  name = ExpandPathName(name);
+  strcpy(fullname, name);
+  return 1;
+}
+
+void
+EnsureOnScreen(int *x, int *y, int minX, int minY)
+{
+  return;
+}
+
+int
+MainWindowUp()
+{ // [HGM] args: allows testing if main window is realized from back-end
+  return xBoardWindow != 0;
+}
+
+void
+PopUpStartupDialog()
+{  // start menu not implemented in XBoard
+}
+char *
+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;
+  return line;
+}
+
+//--------------------------------------------------------------------------------------------
+
+#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)
+{   // [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;
+
+    if(!formWidget) return;
+
+    /*
+     * Enable shell resizing.
+     */
+    shellArgs[0].value = (XtArgVal) &w;
+    shellArgs[1].value = (XtArgVal) &h;
+    XtGetValues(shellWidget, shellArgs, 2);
+
+    shellArgs[4].value = 2*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);
+    CreateGrid();
+
+    XtSetArg(args[0], XtNwidth, boardWidth);
+    XtSetArg(args[1], XtNheight, boardHeight);
+    XtSetValues(boardWidget, args, 2);
+
+    timerWidth = (boardWidth - sep) / 2;
+    XtSetArg(args[0], XtNwidth, timerWidth);
+    XtSetValues(whiteTimerWidget, args, 1);
+    XtSetValues(blackTimerWidget, args, 1);
+
+    XawFormDoLayout(formWidget, False);
+
+    if (appData.titleInWindow) {
+       i = 0;
+       XtSetArg(args[i], XtNborderWidth, &bor); i++;
+       XtSetArg(args[i], XtNheight, &h);  i++;
+       XtGetValues(titleWidget, args, i);
+       if (smallLayout) {
+           w = boardWidth - 2*bor;
+       } else {
+           XtSetArg(args[0], XtNwidth, &w);
+           XtGetValues(menuBarWidget, args, 1);
+           w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
+       }
+
+       gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
+       if (gres != XtGeometryYes && appData.debugMode) {
+           fprintf(stderr,
+                   _("%s: titleWidget geometry error %d %d %d %d %d\n"),
+                   programName, gres, w, h, wr, hr);
+       }
+    }
+
+    XawFormDoLayout(formWidget, True);
+
+    /*
+     * Inhibit shell resizing.
+     */
+    shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
+    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);
+
+    // [HGM] pieces: tailor piece bitmaps to needs of specific variant
+    // (only for xpm)
+    if(useImages) {
+      for(i=0; i<4; i++) {
+       int p;
+       for(p=0; p<=(int)WhiteKing; p++)
+          xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
+       if(gameInfo.variant == VariantShogi) {
+          xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
+          xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
+          xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
+          xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
+          xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
+       }
+#ifdef GOTHIC
+       if(gameInfo.variant == VariantGothic) {
+          xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
+       }
+#endif
+#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++)
+          ximMaskPm[p] = ximMaskPm2[p]; // defaults
+       if(gameInfo.variant == VariantShogi) {
+          ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
+          ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
+          ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
+          ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
+          ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
+       }
+#ifdef GOTHIC
+       if(gameInfo.variant == VariantGothic) {
+           ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
+       }
+#endif
+#endif
+      }
+    } else {
+      for(i=0; i<2; i++) {
+       int p;
+       for(p=0; p<=(int)WhiteKing; p++)
+          pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
+       if(gameInfo.variant == VariantShogi) {
+          pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
+          pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
+          pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
+          pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
+          pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
+       }
+#ifdef GOTHIC
+       if(gameInfo.variant == VariantGothic) {
+          pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
+       }
+#endif
+      }
+    }
+#if HAVE_LIBXPM
+    CreateAnimVars();
+#endif
+}
+#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;
+           }
+}
+
 int
 main(argc, argv)
      int argc;
@@ -1853,17 +1652,24 @@ main(argc, argv)
     int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
     XSetWindowAttributes window_attributes;
     Arg args[16];
-    Dimension timerWidth, boardWidth, w, h, sep, bor, wr, hr;
+    Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
     XrmValue vFrom, vTo;
     XtGeometryResult gres;
     char *p;
     XrmDatabase xdb;
     int forceMono = False;
 
+    srandom(time(0)); // [HGM] book: make random truly random
+
     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];
@@ -1872,21 +1678,40 @@ main(argc, argv)
 
 #ifdef ENABLE_NLS
     XtSetLanguageProc(NULL, NULL, NULL);
-    bindtextdomain(PRODUCT, LOCALEDIR);
-    bind_textdomain_codeset(PRODUCT, "UTF-8");
-    textdomain(PRODUCT);
+    bindtextdomain(PACKAGE, LOCALEDIR);
+    textdomain(PACKAGE);
 #endif
 
     shellWidget =
       XtAppInitialize(&appContext, "XBoard", shellOptions,
                      XtNumber(shellOptions),
                      &argc, argv, xboardResources, NULL, 0);
-    if (argc > 1) {
-       fprintf(stderr, _("%s: unrecognized argument %s\n"),
-               programName, argv[1]);
-       exit(2);
+    appData.boardSize = "";
+    InitAppData(ConvertToLine(argc, argv));
+    p = getenv("HOME");
+    if (p == NULL) p = "/tmp";
+    i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
+    gameCopyFilename = (char*) malloc(i);
+    gamePasteFilename = (char*) malloc(i);
+    snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
+    snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
+
+    XtGetApplicationResources(shellWidget, (XtPointer) &appData,
+                             clientResources, XtNumber(clientResources),
+                             NULL, 0);
+
+    { // [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.secondInitString);
+       appData.secondInitString = strdup(buf);
+       EscapeExpand(buf, appData.firstComputerString);
+       appData.firstComputerString = strdup(buf);
+       EscapeExpand(buf, appData.secondComputerString);
+       appData.secondComputerString = strdup(buf);
     }
-    
+
     if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
        chessDir = ".";
     } else {
@@ -1896,27 +1721,21 @@ main(argc, argv)
            exit(1);
        }
     }
-    
-    p = getenv("HOME");
-    if (p == NULL) p = "/tmp";
-    i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
-    gameCopyFilename = (char*) malloc(i);
-    gamePasteFilename = (char*) malloc(i);
-    sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
-    sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
 
-    XtGetApplicationResources(shellWidget, (XtPointer) &appData,
-                             clientResources, XtNumber(clientResources),
-                             NULL, 0);
-                             
-    if (appData.debugMode) {
-       if ((debugFP = fopen("xboard.debug", "w")) == NULL)  {
-          printf(_("Failed to open file xboard.debug \n"));
-          exit(errno);
-       }
+    if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
+       /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
+        if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL)  {
+           printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
+           exit(errno);
+        }
         setbuf(debugFP, NULL);
     }
-    
+
+    /* [HGM,HR] make sure board size is acceptable */
+    if(appData.NrFiles > BOARD_FILES ||
+       appData.NrRanks > BOARD_RANKS   )
+        DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
+
 #if !HIGHDRAG
     /* This feature does not work; animation needs a rewrite */
     appData.highlightDragging = FALSE;
@@ -1927,9 +1746,12 @@ main(argc, argv)
     xScreen = DefaultScreen(xDisplay);
     wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
 
-    /*
-     * Determine boardSize
-     */
+       gameInfo.variant = StringToVariant(appData.variant);
+       InitPosition(FALSE);
+
+#ifdef IDSIZE
+    InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
+#else
     if (isdigit(appData.boardSize[0])) {
         i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
                   &lineGap, &clockFontPxlSize, &coordFontPxlSize,
@@ -1967,6 +1789,7 @@ main(argc, argv)
              szd++;
            }
            if (szd->name == NULL) szd--;
+           appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
        } else {
            while (szd->name != NULL &&
                   StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
@@ -1994,7 +1817,7 @@ main(argc, argv)
            exit(1);
        }
        if (appData.debugMode) {
-           fprintf(stderr, _("\
+          fprintf(stderr, _("\
 XBoard square size (hint): %d\n\
 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
        }
@@ -2003,22 +1826,24 @@ XBoard square size (hint): %d\n\
            fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
        }
     }
-               
-    boardWidth = lineGap + BOARD_SIZE * (squareSize + lineGap);
+
+    /* [HR] height treated separately (hacked) */
+    boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
+    boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
     if (appData.showJail == 1) {
        /* Jail on top and bottom */
        XtSetArg(boardArgs[1], XtNwidth, boardWidth);
        XtSetArg(boardArgs[2], XtNheight,
-                boardWidth + 2*(lineGap + squareSize));
+                boardHeight + 2*(lineGap + squareSize));
     } else if (appData.showJail == 2) {
        /* Jail on sides */
        XtSetArg(boardArgs[1], XtNwidth,
                 boardWidth + 2*(lineGap + squareSize));
-       XtSetArg(boardArgs[2], XtNheight, boardWidth);
+       XtSetArg(boardArgs[2], XtNheight, boardHeight);
     } else {
        /* No jail */
        XtSetArg(boardArgs[1], XtNwidth, boardWidth);
-       XtSetArg(boardArgs[2], XtNheight, boardWidth);
+       XtSetArg(boardArgs[2], XtNheight, boardHeight);
     }
 
     /*
@@ -2031,6 +1856,9 @@ XBoard square size (hint): %d\n\
     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);
 
     xdb = XtDatabase(xDisplay);
     XrmPutStringResource(&xdb, "*font", appData.font);
@@ -2114,6 +1942,20 @@ XBoard square size (hint): %d\n\
     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;
+    }
+
+    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) 
+               appData.monoMode = True;
+      else
+               lowTimeWarningColor = *(Pixel *) vTo.addr;
     }
 
     if (appData.monoMode && appData.debugMode) {
@@ -2121,7 +1963,7 @@ XBoard square size (hint): %d\n\
                (unsigned long) XWhitePixel(xDisplay, xScreen),
                (unsigned long) XBlackPixel(xDisplay, xScreen));
     }
-    
+
     if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
        parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
        parse_cpair(ColorChannel1, appData.colorChannel1) < 0  ||
@@ -2142,9 +1984,9 @@ XBoard square size (hint): %d\n\
       }
     textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
     textColors[ColorNone].attr = 0;
-    
+
     XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
-    
+
     /*
      * widget hierarchy
      */
@@ -2165,51 +2007,70 @@ XBoard square size (hint): %d\n\
                            formArgs, XtNumber(formArgs));
     XtSetArg(args[0], XtNdefaultDistance, &sep);
     XtGetValues(formWidget, args, 1);
-    
+
     j = 0;
     widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
+    XtSetArg(args[0], XtNtop,    XtChainTop);
+    XtSetArg(args[1], XtNbottom, XtChainTop);
+    XtSetArg(args[2], XtNright,  XtChainLeft);
+    XtSetValues(menuBarWidget, args, 3);
 
     widgetList[j++] = whiteTimerWidget =
       XtCreateWidget("whiteTime", labelWidgetClass,
                     formWidget, timerArgs, XtNumber(timerArgs));
     XtSetArg(args[0], XtNfont, clockFontStruct);
-    XtSetValues(whiteTimerWidget, args, 1);
-    
+    XtSetArg(args[1], XtNtop,    XtChainTop);
+    XtSetArg(args[2], XtNbottom, XtChainTop);
+    XtSetValues(whiteTimerWidget, args, 3);
+
     widgetList[j++] = blackTimerWidget =
       XtCreateWidget("blackTime", labelWidgetClass,
                     formWidget, timerArgs, XtNumber(timerArgs));
     XtSetArg(args[0], XtNfont, clockFontStruct);
-    XtSetValues(blackTimerWidget, args, 1);
-    
+    XtSetArg(args[1], XtNtop,    XtChainTop);
+    XtSetArg(args[2], XtNbottom, XtChainTop);
+    XtSetValues(blackTimerWidget, args, 3);
+
     if (appData.titleInWindow) {
-       widgetList[j++] = titleWidget = 
+       widgetList[j++] = titleWidget =
          XtCreateWidget("title", labelWidgetClass, formWidget,
                         titleArgs, XtNumber(titleArgs));
+       XtSetArg(args[0], XtNtop,    XtChainTop);
+       XtSetArg(args[1], XtNbottom, XtChainTop);
+       XtSetValues(titleWidget, args, 2);
     }
 
     if (appData.showButtonBar) {
       widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
+      XtSetArg(args[0], XtNleft,  XtChainRight); // [HGM] glue to right window edge
+      XtSetArg(args[1], XtNright, XtChainRight); //       for good run-time sizing
+      XtSetArg(args[2], XtNtop,    XtChainTop);
+      XtSetArg(args[3], XtNbottom, XtChainTop);
+      XtSetValues(buttonBarWidget, args, 4);
     }
 
     widgetList[j++] = messageWidget =
       XtCreateWidget("message", labelWidgetClass, formWidget,
                     messageArgs, XtNumber(messageArgs));
-    
+    XtSetArg(args[0], XtNtop,    XtChainTop);
+    XtSetArg(args[1], XtNbottom, XtChainTop);
+    XtSetValues(messageWidget, args, 2);
+
     widgetList[j++] = boardWidget =
       XtCreateWidget("board", widgetClass, formWidget, boardArgs,
                     XtNumber(boardArgs));
 
     XtManageChildren(widgetList, j);
-    
+
     timerWidth = (boardWidth - sep) / 2;
     XtSetArg(args[0], XtNwidth, timerWidth);
     XtSetValues(whiteTimerWidget, args, 1);
     XtSetValues(blackTimerWidget, args, 1);
-    
+
     XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
     XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
     XtGetValues(whiteTimerWidget, args, 2);
-    
+
     if (appData.showButtonBar) {
       XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
       XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
@@ -2289,16 +2150,27 @@ XBoard square size (hint): %d\n\
     }
     i = 0;
     XtSetArg(args[0], XtNfromVert, messageWidget);
-    XtSetValues(boardWidget, args, 1);
+    XtSetArg(args[1], XtNtop,    XtChainTop);
+    XtSetArg(args[2], XtNbottom, XtChainBottom);
+    XtSetArg(args[3], XtNleft,   XtChainLeft);
+    XtSetArg(args[4], XtNright,  XtChainRight);
+    XtSetValues(boardWidget, args, 5);
 
     XtRealizeWidget(shellWidget);
 
+    if(wpMain.x > 0) {
+      XtSetArg(args[0], XtNx, wpMain.x);
+      XtSetArg(args[1], XtNy, wpMain.y);
+      XtSetValues(shellWidget, args, 2);
+    }
+
     /*
      * Correct the width of the message and title widgets.
      * It is not known why some systems need the extra fudge term.
      * The value "2" is probably larger than needed.
      */
     XawFormDoLayout(formWidget, False);
+
 #define WIDTH_FUDGE 2
     i = 0;
     XtSetArg(args[i], XtNborderWidth, &bor);  i++;
@@ -2318,7 +2190,7 @@ XBoard square size (hint): %d\n\
       fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
              programName, gres, w, h, wr, hr);
     }
-    
+
     /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
     /* The size used for the child widget in layout lags one resize behind
        its true size, so we resize a second time, 1 pixel smaller.  Yeech! */
@@ -2329,6 +2201,9 @@ XBoard square size (hint): %d\n\
              programName, gres, w, h, wr, hr);
     }
     /* !! end hack */
+    XtSetArg(args[0], XtNleft,  XtChainLeft);  // [HGM] glue ends for good run-time sizing
+    XtSetArg(args[1], XtNright, XtChainRight);
+    XtSetValues(messageWidget, args, 2);
 
     if (appData.titleInWindow) {
        i = 0;
@@ -2353,8 +2228,12 @@ XBoard square size (hint): %d\n\
     XawFormDoLayout(formWidget, True);
 
     xBoardWindow = XtWindow(boardWidget);
-    
-    /* 
+
+    // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
+    //       not need to go into InitDrawingSizes().
+#endif
+
+    /*
      * Create X checkmark bitmap and initialize option menu checks.
      */
     ReadBitmap(&xMarkPixmap, "checkmark.bm",
@@ -2445,19 +2324,19 @@ XBoard square size (hint): %d\n\
     if (appData.periodicUpdates) {
        XtSetValues(XtNameToWidget(menuBarWidget,
                                   "menuOptions.Periodic Updates"), args, 1);
-    }  
+    }
     if (appData.ponderNextMove) {
        XtSetValues(XtNameToWidget(menuBarWidget,
                                   "menuOptions.Ponder Next Move"), args, 1);
-    }  
+    }
     if (appData.popupExitMessage) {
        XtSetValues(XtNameToWidget(menuBarWidget,
                                   "menuOptions.Popup Exit Message"), args, 1);
-    }  
+    }
     if (appData.popupMoveErrors) {
        XtSetValues(XtNameToWidget(menuBarWidget,
                                   "menuOptions.Popup Move Errors"), args, 1);
-    }  
+    }
     if (appData.premove) {
        XtSetValues(XtNameToWidget(menuBarWidget,
                                   "menuOptions.Premove"), args, 1);
@@ -2470,14 +2349,18 @@ XBoard square size (hint): %d\n\
        XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
                    args, 1);
     }
-    if (appData.showThinking) {
-       XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
+    if (appData.hideThinkingFromHuman) {
+       XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
                    args, 1);
     }
     if (appData.testLegality) {
        XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
                    args, 1);
     }
+    if (saveSettingsOnExit) {
+       XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
+                   args, 1);
+    }
 
     /*
      * Create an icon.
@@ -2490,14 +2373,14 @@ XBoard square size (hint): %d\n\
     i = 0;
     XtSetArg(args[i], XtNiconPixmap, iconPixmap);  i++;
     XtSetValues(shellWidget, args, i);
-    
+
     /*
      * Create a cursor for the board widget.
      */
     window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
     XChangeWindowAttributes(xDisplay, xBoardWindow,
                            CWCursor, &window_attributes);
-    
+
     /*
      * Inhibit shell resizing.
      */
@@ -2507,7 +2390,9 @@ XBoard square size (hint): %d\n\
     shellArgs[4].value = shellArgs[2].value = w;
     shellArgs[5].value = shellArgs[3].value = h;
     XtSetValues(shellWidget, &shellArgs[2], 4);
-    
+    marginW =  w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
+    marginH =  h - boardHeight;
+
     CatchDeleteWindow(shellWidget, "QuitProc");
 
     CreateGCs();
@@ -2522,13 +2407,13 @@ XBoard square size (hint): %d\n\
     CreateXIMPieces();
     /* Create regular pieces */
     if (!useImages) CreatePieces();
-#endif  
+#endif
 
     CreatePieceMenus();
 
     if (appData.animate || appData.animateDragging)
       CreateAnimVars();
-    
+
     XtAugmentTranslations(formWidget,
                          XtParseTranslationTable(globalTranslations));
     XtAugmentTranslations(boardWidget,
@@ -2544,8 +2429,22 @@ XBoard square size (hint): %d\n\
                      (XtEventHandler) EventProc, NULL);
     /* end why */
 
-    InitBackEnd2();
+    /* [AS] Restore layout */
+    if( wpMoveHistory.visible ) {
+      HistoryPopUp();
+    }
+
+    if( wpEvalGraph.visible ) 
+      {
+       EvalGraphPopUp();
+      };
     
+    if( wpEngineOutput.visible ) {
+      EngineOutputPopUp();
+    }
+
+    InitBackEnd2();
+
     if (errorExitStatus == -1) {
        if (appData.icsActive) {
            /* We now wait until we see "login:" from the ICS before
@@ -2554,16 +2453,20 @@ XBoard square size (hint): %d\n\
            if (appData.icsInputBox) ICSInputBoxPopUp();
        }
 
+    #ifdef SIGWINCH
+    signal(SIGWINCH, TermSizeSigHandler);
+    #endif
        signal(SIGINT, IntSigHandler);
        signal(SIGTERM, IntSigHandler);
        if (*appData.cmailGameName != NULLCHAR) {
            signal(SIGUSR1, CmailSigHandler);
        }
     }
+    gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
+    InitPosition(TRUE);
 
     XtAppMainLoop(appContext);
-    if (appData.debugMode) fclose(debugFP);
-    
+    if (appData.debugMode) fclose(debugFP); // [DM] debug
     return 0;
 }
 
@@ -2573,10 +2476,16 @@ ShutDownFrontEnd()
     if (appData.icsActive && oldICSInteractionTitle != NULL) {
         DisplayIcsInteractionTitle(oldICSInteractionTitle);
     }
+    if (saveSettingsOnExit) SaveSettings(settingsFileName);
     unlink(gameCopyFilename);
     unlink(gamePasteFilename);
 }
 
+RETSIGTYPE TermSizeSigHandler(int sig)
+{
+    update_ics_width();
+}
+
 RETSIGTYPE
 IntSigHandler(sig)
      int sig;
@@ -2648,6 +2557,20 @@ typedef struct {
     Boolean value;
 } Enables;
 
+void
+GreyRevert(grey)
+     Boolean grey;
+{
+    Widget w;
+    if (!menuBarWidget) return;
+    w = XtNameToWidget(menuBarWidget, "menuStep.Revert");
+    if (w == NULL) {
+      DisplayError("menuStep.Revert", 0);
+    } else {
+      XtSetSensitive(w, !grey);
+    }
+}
+
 void
 SetMenuEnables(enab)
      Enables *enab;
@@ -2677,14 +2600,14 @@ Enables icsEnables[] = {
     { "menuHelp.Hint", False },
     { "menuHelp.Book", False },
     { "menuStep.Move Now", False },
-    { "menuOptions.Periodic Updates", False }, 
-    { "menuOptions.Show Thinking", False },
+    { "menuOptions.Periodic Updates", False },
+    { "menuOptions.Hide Thinking", False },
     { "menuOptions.Ponder Next Move", False },
 #endif
     { NULL, False }
 };
 
-Enables ncpEnables[] = {    
+Enables ncpEnables[] = {
     { "menuFile.Mail Move", False },
     { "menuFile.Reload CMail Message", False },
     { "menuMode.Machine White", False },
@@ -2707,15 +2630,15 @@ Enables ncpEnables[] = {
     { "menuOptions.ICS Alarm", False },
     { "menuOptions.Move Sound", False },
     { "menuOptions.Quiet Play", False },
-    { "menuOptions.Show Thinking", False },
-    { "menuOptions.Periodic Updates", False }, 
+    { "menuOptions.Hide Thinking", False },
+    { "menuOptions.Periodic Updates", False },
     { "menuOptions.Ponder Next Move", False },
     { "menuHelp.Hint", False },
     { "menuHelp.Book", False },
     { NULL, False }
 };
 
-Enables gnuEnables[] = {    
+Enables gnuEnables[] = {
     { "menuMode.ICS Client", False },
     { "menuMode.ICS Input Box", False },
     { "menuAction.Accept", False },
@@ -2741,7 +2664,7 @@ Enables gnuEnables[] = {
     { NULL, False }
 };
 
-Enables cmailEnables[] = {    
+Enables cmailEnables[] = {
     { "Action", True },
     { "menuAction.Call Flag", False },
     { "menuAction.Draw", True },
@@ -2754,7 +2677,7 @@ Enables cmailEnables[] = {
     { NULL, False }
 };
 
-Enables trainingOnEnables[] = {    
+Enables trainingOnEnables[] = {
   { "menuMode.Edit Comment", False },
   { "menuMode.Pause", False },
   { "menuStep.Forward", False },
@@ -2766,7 +2689,7 @@ Enables trainingOnEnables[] = {
   { NULL, False }
 };
 
-Enables trainingOffEnables[] = {    
+Enables trainingOffEnables[] = {
   { "menuMode.Edit Comment", True },
   { "menuMode.Pause", True },
   { "menuStep.Forward", True },
@@ -2818,11 +2741,10 @@ void SetICSMode()
 {
   SetMenuEnables(icsEnables);
 
- #ifdef ZIPPY
-  /* icsEngineAnalyze */
-  if (appData.zippyPlay && !appData.noChessProgram) 
+#ifdef ZIPPY
+  if (appData.zippyPlay && !appData.noChessProgram)   /* [DM] icsEngineAnalyze */
      XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
- #endif
+#endif
 }
 
 void
@@ -2892,7 +2814,7 @@ SetMachineThinkingEnables()
  * Find a font that matches "pattern" that is as close as
  * possible to the targetPxlSize.  Prefer fonts that are k
  * pixels smaller to fonts that are k pixels larger.  The
- * pattern must be in the X Consortium standard format, 
+ * pattern must be in the X Consortium standard format,
  * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
  * The return value should be freed with XtFree when no
  * longer needed.
@@ -2918,14 +2840,14 @@ char *FindFont(pattern, targetPxlSize)
     strcat(base_fnt_lst, strInt);
     strcat(base_fnt_lst, strchr(p + 2, '-'));
 
-    if ((fntSet = XCreateFontSet(xDisplay, 
-                                 base_fnt_lst, 
-                                 &missing_list, 
-                                 &missing_count, 
+    if ((fntSet = XCreateFontSet(xDisplay,
+                                 base_fnt_lst,
+                                 &missing_list,
+                                 &missing_count,
                                  &def_string)) == NULL) {
 
-       fprintf(stderr, _("Unable to create font set.\n"));
-       exit (2);
+       fprintf(stderr, _("Unable to create font set.\n"));
+       exit (2);
     }
 
     nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
@@ -2980,10 +2902,10 @@ char *FindFont(pattern, targetPxlSize)
     }
 #ifdef ENABLE_NLS
     if (missing_count > 0)
-       XFreeStringList(missing_list);
+       XFreeStringList(missing_list);
     XFreeFontSet(xDisplay, fntSet);
 #else
-    XFreeFontNames(fonts);
+     XFreeFontNames(fonts);
 #endif
     return p;
 }
@@ -2994,29 +2916,35 @@ void CreateGCs()
       | GCBackground | GCFunction | GCPlaneMask;
     XGCValues gc_values;
     GC copyInvertedGC;
-    
+
     gc_values.plane_mask = AllPlanes;
     gc_values.line_width = lineGap;
     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);
-    
+
     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
+    gc_values.foreground = XWhitePixel(xDisplay, xScreen);
+    gc_values.background = XBlackPixel(xDisplay, xScreen);
+    countGC = XtGetGC(shellWidget, value_mask, &gc_values);
+    XSetFont(xDisplay, countGC, countFontID);
+
     if (appData.monoMode) {
        gc_values.foreground = XWhitePixel(xDisplay, xScreen);
        gc_values.background = XWhitePixel(xDisplay, xScreen);
-       highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);      
+       highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
 
        gc_values.foreground = XWhitePixel(xDisplay, xScreen);
        gc_values.background = XBlackPixel(xDisplay, xScreen);
-       lightSquareGC = wbPieceGC 
+       lightSquareGC = wbPieceGC
          = XtGetGC(shellWidget, value_mask, &gc_values);
 
        gc_values.foreground = XBlackPixel(xDisplay, xScreen);
@@ -3040,16 +2968,16 @@ void CreateGCs()
     } else {
        gc_values.foreground = highlightSquareColor;
        gc_values.background = highlightSquareColor;
-       highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);      
+       highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
 
        gc_values.foreground = premoveHighlightColor;
        gc_values.background = premoveHighlightColor;
-       prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);       
+       prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
 
        gc_values.foreground = lightSquareColor;
        gc_values.background = darkSquareColor;
        lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
-       
+
        gc_values.foreground = darkSquareColor;
        gc_values.background = lightSquareColor;
        darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
@@ -3061,19 +2989,19 @@ void CreateGCs()
        gc_values.foreground = whitePieceColor;
        gc_values.background = darkSquareColor;
        wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
-       
+
        gc_values.foreground = whitePieceColor;
        gc_values.background = lightSquareColor;
        wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
-       
+
        gc_values.foreground = whitePieceColor;
        gc_values.background = jailSquareColor;
        wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
-       
+
        gc_values.foreground = blackPieceColor;
        gc_values.background = darkSquareColor;
        bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
-       
+
        gc_values.foreground = blackPieceColor;
        gc_values.background = lightSquareColor;
        blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
@@ -3102,31 +3030,31 @@ void loadXIM(xim, xmask, filename, dest, mask)
        fprintf(stderr, _("%s: error loading XIM!\n"), programName);
        exit(1);
     }
-         
+
     w = fgetc(fp);
     h = fgetc(fp);
-  
+
     for (y=0; y<h; ++y) {
        for (x=0; x<h; ++x) {
            p = fgetc(fp);
 
            switch (p) {
-             case 0:   
-               XPutPixel(xim, x, y, blackPieceColor); 
+             case 0:
+               XPutPixel(xim, x, y, blackPieceColor);
                if (xmask)
                  XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
                break;
-             case 1:   
-               XPutPixel(xim, x, y, darkSquareColor); 
+             case 1:
+               XPutPixel(xim, x, y, darkSquareColor);
                if (xmask)
                  XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
                break;
-             case 2:   
-               XPutPixel(xim, x, y, whitePieceColor); 
+             case 2:
+               XPutPixel(xim, x, y, whitePieceColor);
                if (xmask)
                  XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
                break;
-             case 3:   
+             case 3:
                XPutPixel(xim, x, y, lightSquareColor);
                if (xmask)
                  XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
@@ -3139,9 +3067,9 @@ void loadXIM(xim, xmask, filename, dest, mask)
     *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
                          w, h, xim->depth);
     XPutImage(xDisplay, *dest, lightSquareGC, xim,
-             0, 0, 0, 0, w, h);  
+             0, 0, 0, 0, w, h);
 
-    /* create Pixmap of clipmask 
+    /* create Pixmap of clipmask
        Note: We assume the white/black pieces have the same
              outline, so we make only 6 masks. This is okay
              since the XPM clipmask routines do the same. */
@@ -3149,7 +3077,7 @@ void loadXIM(xim, xmask, filename, dest, mask)
       temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
                            w, h, xim->depth);
       XPutImage(xDisplay, temp, lightSquareGC, xmask,
-             0, 0, 0, 0, w, h);  
+             0, 0, 0, 0, w, h);
 
       /* now create the 1-bit version */
       *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
@@ -3159,14 +3087,17 @@ void loadXIM(xim, xmask, filename, dest, mask)
       values.background = 0;
 
       /* Don't use XtGetGC, not read only */
-      maskGC = XCreateGC(xDisplay, *mask, 
+      maskGC = XCreateGC(xDisplay, *mask,
                    GCForeground | GCBackground, &values);
-      XCopyPlane(xDisplay, temp, *mask, maskGC, 
+      XCopyPlane(xDisplay, temp, *mask, maskGC,
                  0, 0, squareSize, squareSize, 0, 0, 1);
       XFreePixmap(xDisplay, temp);
     }
 }
 
+
+char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
+
 void CreateXIMPieces()
 {
     int piece, kind;
@@ -3181,7 +3112,7 @@ void CreateXIMPieces()
        Not sure if needed, but can't hurt */
     XSynchronize(xDisplay, True); /* Work-around for xlib/xt
                                     buffering bug */
-  
+
     /* temp needed by loadXIM() */
     ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
                 0, 0, ss, ss, AllPlanes, XYPixmap);
@@ -3197,36 +3128,39 @@ void CreateXIMPieces()
        }
        fprintf(stderr, _("\nLoading XIMs...\n"));
        /* Load pieces */
-       for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
+       for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
            fprintf(stderr, "%d", piece+1);
            for (kind=0; kind<4; kind++) {
                fprintf(stderr, ".");
-               sprintf(buf, "%s/%c%s%u.xim",
+               snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
                        ExpandPathName(appData.pixmapDirectory),
-                       ToLower(PieceToChar((ChessSquare)piece)),
+                       piece <= (int) WhiteKing ? "" : "w",
+                       pieceBitmapNames[piece],
                        ximkind[kind], ss);
                ximPieceBitmap[kind][piece] =
                  XGetImage(xDisplay, DefaultRootWindow(xDisplay),
                            0, 0, ss, ss, AllPlanes, XYPixmap);
                if (appData.debugMode)
                  fprintf(stderr, _("(File:%s:) "), buf);
-               loadXIM(ximPieceBitmap[kind][piece], 
+               loadXIM(ximPieceBitmap[kind][piece],
                        ximtemp, buf,
-                       &(xpmPieceBitmap[kind][piece]),
-                       &(ximMaskPm[piece%6]));
+                       &(xpmPieceBitmap2[kind][piece]),
+                       &(ximMaskPm2[piece]));
+               if(piece <= (int)WhiteKing)
+                   xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
            }
            fprintf(stderr," ");
        }
        /* Load light and dark squares */
-       /* If the LSQ and DSQ pieces don't exist, we will 
+       /* If the LSQ and DSQ pieces don't exist, we will
           draw them with solid squares. */
-       sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
+       snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
        if (access(buf, 0) != 0) {
            useImageSqs = 0;
        } else {
            useImageSqs = 1;
            fprintf(stderr, _("light square "));
-           ximLightSquare= 
+           ximLightSquare=
              XGetImage(xDisplay, DefaultRootWindow(xDisplay),
                        0, 0, ss, ss, AllPlanes, XYPixmap);
            if (appData.debugMode)
@@ -3234,11 +3168,11 @@ void CreateXIMPieces()
 
            loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
            fprintf(stderr, _("dark square "));
-           sprintf(buf, "%s/dsq%u.xim",
+           snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
                    ExpandPathName(appData.pixmapDirectory), ss);
            if (appData.debugMode)
              fprintf(stderr, _("(File:%s:) "), buf);
-           ximDarkSquare= 
+           ximDarkSquare=
              XGetImage(xDisplay, DefaultRootWindow(xDisplay),
                        0, 0, ss, ss, AllPlanes, XYPixmap);
            loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
@@ -3259,18 +3193,10 @@ void CreateXPMPieces()
     static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
     XpmColorSymbol symbols[4];
 
-#if 0
-    /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
-    if (appData.debugMode) {
-       fprintf(stderr, "XPM Library Version: %d.%d%c\n", 
-               XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
-    }
-#endif
-  
     /* The XSynchronize calls were copied from CreatePieces.
        Not sure if needed, but can't hurt */
     XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
-  
+
     /* Setup translations so piece colors match square colors */
     symbols[0].name = "light_piece";
     symbols[0].value = appData.whitePieceColor;
@@ -3299,51 +3225,70 @@ void CreateXPMPieces()
          fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
          exit(1);
        }
-       for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
+       for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
            for (kind=0; kind<4; kind++) {
 
                if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
                                               pieces->xpm[piece][kind],
-                                              &(xpmPieceBitmap[kind][piece]),
+                                              &(xpmPieceBitmap2[kind][piece]),
                                               NULL, &attr)) != 0) {
                  fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
                          r, buf);
-                 exit(1); 
-               }       
-           }   
+                 exit(1);
+               }
+               if(piece <= (int) WhiteKing)
+                   xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
+           }
        }
        useImageSqs = 0;
        xpmJailSquare = xpmLightSquare;
     } else {
        useImages = 1;
-       
+
        fprintf(stderr, _("\nLoading XPMs...\n"));
 
        /* Load pieces */
-       for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
+       for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
            fprintf(stderr, "%d ", piece+1);
            for (kind=0; kind<4; kind++) {
-               sprintf(buf, "%s/%c%s%u.xpm",
+             snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
                        ExpandPathName(appData.pixmapDirectory),
-                       ToLower(PieceToChar((ChessSquare)piece)),
+                       piece > (int) WhiteKing ? "w" : "",
+                       pieceBitmapNames[piece],
                        xpmkind[kind], ss);
                if (appData.debugMode) {
                    fprintf(stderr, _("(File:%s:) "), buf);
                }
                if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
-                                          &(xpmPieceBitmap[kind][piece]),
+                                          &(xpmPieceBitmap2[kind][piece]),
                                           NULL, &attr)) != 0) {
-                   fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
-                           r, buf);
-                   exit(1); 
-               }       
-           }   
+                   if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
+                     // [HGM] missing: read of unorthodox piece failed; substitute King.
+                     snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
+                               ExpandPathName(appData.pixmapDirectory),
+                               xpmkind[kind], ss);
+                       if (appData.debugMode) {
+                           fprintf(stderr, _("(Replace by File:%s:) "), buf);
+                       }
+                       r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
+                                               &(xpmPieceBitmap2[kind][piece]),
+                                               NULL, &attr);
+                   }
+                   if (r != 0) {
+                       fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
+                               r, buf);
+                       exit(1);
+                   }
+               }
+               if(piece <= (int) WhiteKing) 
+                   xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
+           }
        }
        /* Load light and dark squares */
-       /* If the LSQ and DSQ pieces don't exist, we will 
+       /* If the LSQ and DSQ pieces don't exist, we will
           draw them with solid squares. */
        fprintf(stderr, _("light square "));
-       sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
+       snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
        if (access(buf, 0) != 0) {
            useImageSqs = 0;
        } else {
@@ -3357,7 +3302,7 @@ void CreateXPMPieces()
                exit(1);
            }
            fprintf(stderr, _("dark square "));
-           sprintf(buf, "%s/dsq%u.xpm",
+           snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
                    ExpandPathName(appData.pixmapDirectory), ss);
            if (appData.debugMode) {
                fprintf(stderr, _("(File:%s:) "), buf);
@@ -3372,7 +3317,7 @@ void CreateXPMPieces()
        fprintf(stderr, _("Done.\n"));
     }
     XSynchronize(xDisplay, False); /* Work-around for xlib/xt
-                                     buffering bug */  
+                                     buffering bug */
 }
 #endif /* HAVE_LIBXPM */
 
@@ -3383,18 +3328,21 @@ void CreatePieces()
     int piece, kind;
     char buf[MSG_SIZ];
     u_int ss = squareSize;
-       
+
     XSynchronize(xDisplay, True); /* Work-around for xlib/xt
                                     buffering bug */
 
     for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
-       for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
-           sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
+       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(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
+           ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
+           if(piece <= (int)WhiteKing)
+               pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
        }
     }
-    
+
     XSynchronize(xDisplay, False); /* Work-around for xlib/xt
                                      buffering bug */
 }
@@ -3406,21 +3354,24 @@ void CreatePieces()
     int piece, kind;
     char buf[MSG_SIZ];
     u_int ss = squareSize;
-       
+
     XSynchronize(xDisplay, True); /* Work-around for xlib/xt
                                     buffering bug */
 
     while (bib->squareSize != ss && bib->squareSize != 0) bib++;
 
     for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
-       for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
-           sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
+       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(&pieceBitmap[kind][piece], buf,
+           ReadBitmap(&pieceBitmap2[kind][piece], buf,
                       bib->bits[kind][piece], ss, ss);
+           if(piece <= (int)WhiteKing)
+               pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
        }
     }
-    
+
     XSynchronize(xDisplay, False); /* Work-around for xlib/xt
                                      buffering bug */
 }
@@ -3436,27 +3387,28 @@ void ReadBitmap(pm, name, bits, wreq, hreq)
     u_int w, h;
     int errcode;
     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);
        if (errcode != BitmapSuccess) {
            switch (errcode) {
              case BitmapOpenFailed:
-               sprintf(msg, _("Can't open bitmap file %s"), fullname);
+               snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
                break;
              case BitmapFileInvalid:
-               sprintf(msg, _("Invalid bitmap in file %s"), fullname);
+               snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
                break;
              case BitmapNoMemory:
-               sprintf(msg, _("Ran out of memory reading bitmap file %s"),
+               snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
                        fullname);
                break;
              default:
-               sprintf(msg, _("Unknown XReadBitmapFile error %d on file %s"),
+               snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
                        errcode, fullname);
                break;
            }
@@ -3470,11 +3422,7 @@ void ReadBitmap(pm, name, bits, wreq, hreq)
            return;
        }
     }
-    if (bits == NULL) {
-       fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
-               programName, name);
-       exit(1);
-    } else {
+    if (bits != NULL) {
        *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
                                    wreq, hreq);
     }
@@ -3482,22 +3430,26 @@ void ReadBitmap(pm, name, bits, wreq, hreq)
 
 void CreateGrid()
 {
-    int i;
-    
+    int i, j;
+
     if (lineGap == 0) return;
-    for (i = 0; i < BOARD_SIZE + 1; i++) {
-       gridSegments[i].x1 = 0;
-       gridSegments[i].x2 =
-         lineGap + BOARD_SIZE * (squareSize + lineGap);
-       gridSegments[i].y1 = gridSegments[i].y2
-         = lineGap / 2 + (i * (squareSize + lineGap));
 
-       gridSegments[i + BOARD_SIZE + 1].y1 = 0;
-       gridSegments[i + BOARD_SIZE + 1].y2 =
-         BOARD_SIZE * (squareSize + lineGap);
-       gridSegments[i + BOARD_SIZE + 1].x1 =
-         gridSegments[i + BOARD_SIZE + 1].x2
-           = lineGap / 2 + (i * (squareSize + lineGap));
+    /* [HR] Split this into 2 loops for non-square boards. */
+
+    for (i = 0; i < BOARD_HEIGHT + 1; i++) {
+        gridSegments[i].x1 = 0;
+        gridSegments[i].x2 =
+          lineGap + BOARD_WIDTH * (squareSize + lineGap);
+        gridSegments[i].y1 = gridSegments[i].y2
+          = lineGap / 2 + (i * (squareSize + lineGap));
+    }
+
+    for (j = 0; j < BOARD_WIDTH + 1; j++) {
+        gridSegments[j + i].y1 = 0;
+        gridSegments[j + i].y2 =
+          lineGap + BOARD_HEIGHT * (squareSize + lineGap);
+        gridSegments[j + i].x1 = gridSegments[j + i].x2
+          = lineGap / 2 + (j * (squareSize + lineGap));
     }
 }
 
@@ -3532,7 +3484,7 @@ void CreateMenuBarPopup(parent, name, mb)
            entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
                                          menu, args, j);
        } else {
-           XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
+          XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
            entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
                                          menu, args, j+1);
            XtAddCallback(entry, XtNcallback,
@@ -3541,7 +3493,7 @@ void CreateMenuBarPopup(parent, name, mb)
        }
        mi++;
     }
-}      
+}
 
 Widget CreateMenuBar(mb)
      Menu *mb;
@@ -3565,13 +3517,13 @@ Widget CreateMenuBar(mb)
        XtSetArg(args[j], XtNmenuName, XtNewString(menuName));  j++;
        if (tinyLayout) {
            char shortName[2];
-           shortName[0] = _(mb->name)[0];
+            shortName[0] = _(mb->name)[0];
            shortName[1] = NULLCHAR;
            XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
        }
-       else {
-           XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
-       }
+      else {
+          XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
+      }
 
        XtSetArg(args[j], XtNborderWidth, 0);                   j++;
        anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
@@ -3605,7 +3557,7 @@ Widget CreateButtonBar(mi)
            XtSetArg(args[j], XtNinternalWidth, 2); j++;
            XtSetArg(args[j], XtNborderWidth, 0); j++;
        }
-       XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
+      XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
        button = XtCreateManagedWidget(mi->string, commandWidgetClass,
                                       buttonBar, args, j);
        XtAddCallback(button, XtNcallback,
@@ -3614,7 +3566,7 @@ Widget CreateButtonBar(mi)
        mi++;
     }
     return buttonBar;
-}     
+}
 
 Widget
 CreatePieceMenu(name, color)
@@ -3628,17 +3580,17 @@ CreatePieceMenu(name, color)
 
     menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
                              boardWidget, args, 0);
-    
+
     for (i = 0; i < PIECE_MENU_SIZE; i++) {
        String item = pieceMenuStrings[color][i];
-       
+
        if (strcmp(item, "----") == 0) {
            entry = XtCreateManagedWidget(item, smeLineObjectClass,
                                          menu, NULL, 0);
        } else {
-           XtSetArg(args[0], XtNlabel, XtNewString(_(item))); 
+          XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
            entry = XtCreateManagedWidget(item, smeBSBObjectClass,
-                                         menu, args, 1);
+                                menu, args, 1);
            selection = pieceMenuTranslation[color][i];
            XtAddCallback(entry, XtNcallback,
                          (XtCallbackProc) PieceMenuSelect,
@@ -3662,7 +3614,7 @@ CreatePieceMenus()
 
     whitePieceMenu = CreatePieceMenu("menuW", 0);
     blackPieceMenu = CreatePieceMenu("menuB", 1);
-    
+
     XtRegisterGrabAction(PieceMenuPopup, True,
                         (unsigned)(ButtonPressMask|ButtonReleaseMask),
                         GrabModeAsync, GrabModeAsync);
@@ -3672,21 +3624,21 @@ CreatePieceMenus()
                                  boardWidget, args, 1);
     for (i = 0; i < DROP_MENU_SIZE; i++) {
        String item = dropMenuStrings[i];
-       
+
        if (strcmp(item, "----") == 0) {
            entry = XtCreateManagedWidget(item, smeLineObjectClass,
                                          dropMenu, NULL, 0);
        } else {
-           XtSetArg(args[0], XtNlabel, XtNewString(_(item))); 
+          XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
            entry = XtCreateManagedWidget(item, smeBSBObjectClass,
-                                         dropMenu, args, 1);
+                                dropMenu, args, 1);
            selection = dropMenuTranslation[i];
            XtAddCallback(entry, XtNcallback,
                          (XtCallbackProc) DropMenuSelect,
                          (caddr_t) selection);
        }
     }
-}      
+}
 
 void SetupDropMenu()
 {
@@ -3705,7 +3657,7 @@ void SetupDropMenu()
                                       && !appData.icsActive));
        count = 0;
        while (p && *p++ == dmEnables[i].piece) count++;
-       sprintf(label, "%s  %d", dmEnables[i].widget, count);
+       snprintf(label, sizeof(label), "%s  %d", dmEnables[i].widget, count);
        j = 0;
        XtSetArg(args[j], XtNlabel, label); j++;
        XtSetValues(entry, args, j);
@@ -3740,17 +3692,17 @@ void PieceMenuPopup(w, event, params, num_params)
       default:
        return;
     }
-    
-    if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_SIZE)) < 0) ||
-       ((pmFromY = EventToSquare(event->xbutton.y, BOARD_SIZE)) < 0)) {
+
+    if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
+       ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
        pmFromX = pmFromY = -1;
        return;
     }
     if (flipView)
-      pmFromX = BOARD_SIZE - 1 - pmFromX;
+      pmFromX = BOARD_WIDTH - 1 - pmFromX;
     else
-      pmFromY = BOARD_SIZE - 1 - pmFromY;
-    
+      pmFromY = BOARD_HEIGHT - 1 - pmFromY;
+
     XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
 }
 
@@ -3806,7 +3758,7 @@ void BlackClock(w, event, prms, nprms)
 int EventToSquare(x, limit)
      int x;
 {
-    if (x <= 0) 
+    if (x <= 0)
       return -2;
     if (x < lineGap)
       return -1;
@@ -3832,17 +3784,17 @@ static void drawHighlight(file, rank, gc)
     int x, y;
 
     if (lineGap == 0 || appData.blindfold) return;
-    
+
     if (flipView) {
-       x = lineGap/2 + ((BOARD_SIZE-1)-file) * 
+       x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
          (squareSize + lineGap);
        y = lineGap/2 + rank * (squareSize + lineGap);
     } else {
        x = lineGap/2 + file * (squareSize + lineGap);
-       y = lineGap/2 + ((BOARD_SIZE-1)-rank) * 
+       y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
          (squareSize + lineGap);
     }
-    
+
     XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
                   squareSize+lineGap, squareSize+lineGap);
 }
@@ -4014,6 +3966,7 @@ static void colorDrawPiece(piece, square_color, x, y, dest)
      int square_color, x, y;
      Drawable dest;
 {
+    if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
     switch (square_color) {
       case 1: /* light */
        XCopyPlane(xDisplay, *pieceToSolid(piece),
@@ -4066,7 +4019,7 @@ static void colorDrawPieceImage(piece, square_color, x, y, dest)
     }
     XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
              dest, wlPieceGC, 0, 0,
-             squareSize, squareSize, x, y);            
+             squareSize, squareSize, x, y);
 }
 
 typedef void (*DrawFunc)();
@@ -4087,6 +4040,32 @@ DrawFunc ChooseDrawFunc()
     }
 }
 
+/* [HR] determine square color depending on chess variant. */
+static int SquareColor(row, column)
+     int row, column;
+{
+    int square_color;
+
+    if (gameInfo.variant == VariantXiangqi) {
+        if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
+            square_color = 1;
+        } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
+            square_color = 0;
+        } else if (row <= 4) {
+            square_color = 0;
+        } else {
+            square_color = 1;
+        }
+    } else {
+        square_color = ((column + row) % 2) == 1;
+    }
+
+    /* [hgm] holdings: next line makes all holdings squares light */
+    if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
+
+    return square_color;
+}
+
 void DrawSquare(row, column, piece, do_flash)
      int row, column, do_flash;
      ChessSquare piece;
@@ -4100,56 +4079,93 @@ void DrawSquare(row, column, piece, do_flash)
 
     /* Calculate delay in milliseconds (2-delays per complete flash) */
     flash_delay = 500 / appData.flashRate;
-       
+
     if (flipView) {
-       x = lineGap + ((BOARD_SIZE-1)-column) * 
+       x = lineGap + ((BOARD_WIDTH-1)-column) *
          (squareSize + lineGap);
        y = lineGap + row * (squareSize + lineGap);
     } else {
        x = lineGap + column * (squareSize + lineGap);
-       y = lineGap + ((BOARD_SIZE-1)-row) * 
+       y = lineGap + ((BOARD_HEIGHT-1)-row) *
          (squareSize + lineGap);
     }
-    
-    square_color = ((column + row) % 2) == 1;
-    
-    if (piece == EmptySquare || appData.blindfold) {
-       BlankSquare(x, y, square_color, piece, xBoardWindow);
-    } 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);
-               XSync(xDisplay, False);
-               do_flash_delay(flash_delay);
-           }
+    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);
+
+                       // [HGM] print piece counts next to holdings
+                       string[1] = NULLCHAR;
+                       if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
+                           string[0] = '0' + piece;
+                           XTextExtents(countFontStruct, string, 1, &direction,
+                                &font_ascent, &font_descent, &overall);
+                           if (appData.monoMode) {
+                               XDrawImageString(xDisplay, xBoardWindow, countGC,
+                                                x + squareSize - overall.width - 2,
+                                                y + font_ascent + 1, string, 1);
+                           } else {
+                               XDrawString(xDisplay, xBoardWindow, countGC,
+                                           x + squareSize - overall.width - 2,
+                                           y + font_ascent + 1, string, 1);
+                           }
+                       }
+                       if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
+                           string[0] = '0' + piece;
+                           XTextExtents(countFontStruct, string, 1, &direction,
+                                        &font_ascent, &font_descent, &overall);
+                           if (appData.monoMode) {
+                               XDrawImageString(xDisplay, xBoardWindow, countGC,
+                                                x + 2, y + font_ascent + 1, string, 1);
+                           } else {
+                               XDrawString(xDisplay, xBoardWindow, countGC,
+                                           x + 2, y + font_ascent + 1, string, 1);
+                           }
+                       }
+    } else {
+           if (piece == EmptySquare || appData.blindfold) {
+                       BlankSquare(x, y, square_color, piece, xBoardWindow);
+           } 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);
+                                       XSync(xDisplay, False);
+                                       do_flash_delay(flash_delay);
+                           }
+                       }
+                       drawfunc(piece, square_color, x, y, xBoardWindow);
+       }
        }
-       drawfunc(piece, square_color, x, y, xBoardWindow);
-    }
-       
+
     string[1] = NULLCHAR;
-    if (appData.showCoords && row == (flipView ? 7 : 0)) {
-       string[0] = 'a' + column;
-       XTextExtents(coordFontStruct, string, 1, &direction, 
+    if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
+               && column >= BOARD_LEFT && column < BOARD_RGHT) {
+       string[0] = 'a' + column - BOARD_LEFT;
+       XTextExtents(coordFontStruct, string, 1, &direction,
                     &font_ascent, &font_descent, &overall);
        if (appData.monoMode) {
            XDrawImageString(xDisplay, xBoardWindow, coordGC,
-                            x + squareSize - overall.width - 2, 
+                            x + squareSize - overall.width - 2,
                             y + squareSize - font_descent - 1, string, 1);
        } else {
            XDrawString(xDisplay, xBoardWindow, coordGC,
-                       x + squareSize - overall.width - 2, 
+                       x + squareSize - overall.width - 2,
                        y + squareSize - font_descent - 1, string, 1);
        }
     }
-    if (appData.showCoords && column == (flipView ? 7 : 0)) {
-       string[0] = '1' + row;
-       XTextExtents(coordFontStruct, string, 1, &direction, 
+    if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
+       string[0] = ONE + row;
+       XTextExtents(coordFontStruct, string, 1, &direction,
                     &font_ascent, &font_descent, &overall);
        if (appData.monoMode) {
            XDrawImageString(xDisplay, xBoardWindow, coordGC,
@@ -4157,8 +4173,8 @@ void DrawSquare(row, column, piece, do_flash)
        } else {
            XDrawString(xDisplay, xBoardWindow, coordGC,
                        x + 2, y + font_ascent + 1, string, 1);
-       }           
-    }   
+       }
+    }
 }
 
 
@@ -4196,9 +4212,9 @@ static int too_many_diffs(b1, b2)
 {
     int i, j;
     int c = 0;
-  
-    for (i=0; i<BOARD_SIZE; ++i) {
-       for (j=0; j<BOARD_SIZE; ++j) {
+
+    for (i=0; i<BOARD_HEIGHT; ++i) {
+       for (j=0; j<BOARD_WIDTH; ++j) {
            if (b1[i][j] != b2[i][j]) {
                if (++c > 4)    /* Castling causes 4 diffs */
                  return 1;
@@ -4220,9 +4236,9 @@ static int castling_matrix[4][5] = {
 
 /* Checks whether castling occurred. If it did, *rrow and *rcol
    are set to the destination (row,col) of the rook that moved.
-   
+
    Returns 1 if castling occurred, 0 if not.
-   
+
    Note: Only handles a max of 1 castling move, so be sure
    to call too_many_diffs() first.
    */
@@ -4256,7 +4272,7 @@ static int check_castle_draw(newb, oldb, rrow, rcol)
     return 0;
 }
 
-static int damage[BOARD_SIZE][BOARD_SIZE];
+static int damage[BOARD_RANKS][BOARD_FILES];
 
 /*
  * event handler for redrawing the board
@@ -4272,7 +4288,7 @@ void XDrawPosition(w, repaint, board)
     static Board lastBoard;
     Arg args[16];
     int rrow, rcol;
-    
+
     if (board == NULL) {
        if (!lastBoardValid) return;
        board = lastBoard;
@@ -4287,7 +4303,7 @@ void XDrawPosition(w, repaint, board)
      * It would be simpler to clear the window with XClearWindow()
      * but this causes a very distracting flicker.
      */
-    
+
     if (!repaint && lastBoardValid && lastFlipView == flipView) {
 
        /* If too much changes (begin observing new game, etc.), don't
@@ -4304,11 +4320,11 @@ void XDrawPosition(w, repaint, board)
            }
        }
 
-       /* First pass -- Draw (newly) empty squares and repair damage. 
-          This prevents you from having a piece show up twice while it 
+       /* First pass -- Draw (newly) empty squares and repair damage.
+          This prevents you from having a piece show up twice while it
           is flashing on its new square */
-       for (i = 0; i < BOARD_SIZE; i++)
-         for (j = 0; j < BOARD_SIZE; j++)
+       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]) {
                DrawSquare(i, j, board[i][j], 0);
@@ -4316,18 +4332,18 @@ void XDrawPosition(w, repaint, board)
            }
 
        /* Second pass -- Draw piece(s) in new position and flash them */
-       for (i = 0; i < BOARD_SIZE; i++)
-         for (j = 0; j < BOARD_SIZE; j++)
+       for (i = 0; i < BOARD_HEIGHT; i++)
+         for (j = 0; j < BOARD_WIDTH; j++)
            if (board[i][j] != lastBoard[i][j]) {
-               DrawSquare(i, j, board[i][j], do_flash);          
+               DrawSquare(i, j, board[i][j], do_flash);
            }
     } else {
        if (lineGap > 0)
          XDrawSegments(xDisplay, xBoardWindow, lineGC,
-                       gridSegments, (BOARD_SIZE + 1) * 2);
-       
-       for (i = 0; i < BOARD_SIZE; i++)
-         for (j = 0; j < BOARD_SIZE; j++) {
+                       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;
          }
@@ -4374,20 +4390,21 @@ void DrawPositionProc(w, event, prms, nprms)
 /*
  * event handler for parsing user moves
  */
+// [HGM] This routine will need quite some reworking. Although the backend still supports the old
+//       way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
+//       it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
+//       should be made to use the new way, of calling UserMoveTest early  to determine the legality of the
+//       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;
 {
-    int x, y;
-    Boolean saveAnimate;
-    static int second = 0;
-       
     if (w != boardWidget || errorExitStatus != -1) return;
 
-    if (event->type == ButtonPress) ErrorPopDown();
-
     if (promotionUp) {
        if (event->type == ButtonPress) {
            XtPopdown(promotionShell);
@@ -4399,123 +4416,10 @@ void HandleUserMove(w, event, prms, nprms)
            return;
        }
     }
-    
-    x = EventToSquare(event->xbutton.x, BOARD_SIZE);
-    y = EventToSquare(event->xbutton.y, BOARD_SIZE);
-    if (!flipView && y >= 0) {
-       y = BOARD_SIZE - 1 - y;
-    }
-    if (flipView && x >= 0) {
-       x = BOARD_SIZE - 1 - x;
-    }
-
-    if (fromX == -1) {
-       if (event->type == ButtonPress) {
-           /* First square */ 
-           if (OKToStartUserMove(x, y)) {
-               fromX = x;
-               fromY = y;
-               second = 0;
-               DragPieceBegin(event->xbutton.x, event->xbutton.y);
-               if (appData.highlightDragging) {
-                   SetHighlights(x, y, -1, -1);
-               }
-           } 
-       }
-       return;
-    }
-
-    /* fromX != -1 */
-    if (event->type == ButtonPress && gameMode != EditPosition &&
-       x >= 0 && y >= 0) {
-       ChessSquare fromP;
-       ChessSquare toP;
-       /* Check if clicking again on the same color piece */
-       fromP = boards[currentMove][fromY][fromX];
-       toP = boards[currentMove][y][x];
-       if ((WhitePawn <= fromP && fromP <= WhiteKing &&
-            WhitePawn <= toP && toP <= WhiteKing) ||
-           (BlackPawn <= fromP && fromP <= BlackKing &&
-            BlackPawn <= toP && toP <= BlackKing)) {
-           /* Clicked again on same color piece -- changed his mind */
-           second = (x == fromX && y == fromY);
-           if (appData.highlightDragging) {
-               SetHighlights(x, y, -1, -1);
-           } else {
-               ClearHighlights();
-           }
-           if (OKToStartUserMove(x, y)) {
-               fromX = x;
-               fromY = y;
-               DragPieceBegin(event->xbutton.x, event->xbutton.y);
-           }
-           return;
-       }
-    }
 
-    if (event->type == ButtonRelease &&        x == fromX && y == fromY) {
-       DragPieceEnd(event->xbutton.x, event->xbutton.y);
-       if (appData.animateDragging) {
-           /* Undo animation damage if any */
-           DrawPosition(FALSE, NULL);
-       }
-       if (second) {
-           /* Second up/down in same square; just abort move */
-           second = 0;
-           fromX = fromY = -1;
-           ClearHighlights();
-           gotPremove = 0;
-           ClearPremoveHighlights();
-       } else {
-           /* First upclick in same square; start click-click mode */
-           SetHighlights(x, y, -1, -1);
-       }
-       return;
-    }  
-
-    /* Completed move */
-    toX = x;
-    toY = y;
-    saveAnimate = appData.animate;
-    if (event->type == ButtonPress) {
-       /* Finish clickclick move */
-       if (appData.animate || appData.highlightLastMove) {
-           SetHighlights(fromX, fromY, toX, toY);
-       } else {
-           ClearHighlights();
-       }
-    } else {
-       /* Finish drag move */
-       if (appData.highlightLastMove) {
-           SetHighlights(fromX, fromY, toX, toY);
-       } else {
-           ClearHighlights();
-       }
-       DragPieceEnd(event->xbutton.x, event->xbutton.y);
-       /* Don't animate move and drag both */
-       appData.animate = FALSE;
-    }
-    if (IsPromotion(fromX, fromY, toX, toY)) {
-       if (appData.alwaysPromoteToQueen) {
-           UserMoveEvent(fromX, fromY, toX, toY, 'q');
-           if (!appData.highlightLastMove || gotPremove) ClearHighlights();
-           if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
-           fromX = fromY = -1;
-       } else {
-           SetHighlights(fromX, fromY, toX, toY);
-           PromotionPopUp();
-       }
-    } else {
-       UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
-       if (!appData.highlightLastMove || gotPremove) ClearHighlights();
-       if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
-       fromX = fromY = -1;
-    }
-    appData.animate = saveAnimate;
-    if (appData.animate || appData.animateDragging) {
-       /* Undo animation damage if needed */
-       DrawPosition(FALSE, NULL);
-    }
+    // [HGM] mouse: the rest of the mouse handler is moved to the backend, and called here
+    if(event->type == ButtonPress)   LeftClick(Press,   event->xbutton.x, event->xbutton.y);
+    if(event->type == ButtonRelease) LeftClick(Release, event->xbutton.x, event->xbutton.y);
 }
 
 void AnimateUserMove (Widget w, XEvent * event,
@@ -4569,12 +4473,8 @@ Widget CommentCreate(name, text, mutable, callback, lines)
     XtSetArg(args[j], XtNright, XtChainRight);  j++;
     XtSetArg(args[j], XtNresizable, True);  j++;
     XtSetArg(args[j], XtNwidth, bw_width);  j++; /*force wider than buttons*/
-#if 0
-    XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded);  j++;
-#else
     /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
     XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways);  j++;
-#endif
     XtSetArg(args[j], XtNautoFill, True);  j++;
     XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
     edit =
@@ -4672,6 +4572,14 @@ Widget CommentCreate(name, text, mutable, callback, lines)
 #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++;
@@ -4727,12 +4635,8 @@ Widget MiscCreate(name, text, mutable, callback, lines)
     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
     XtSetArg(args[j], XtNright, XtChainRight);  j++;
     XtSetArg(args[j], XtNresizable, True);  j++;
-#if 0
-    XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded);  j++;
-#else
     /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
     XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways);  j++;
-#endif
     XtSetArg(args[j], XtNautoFill, True);  j++;
     XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
     edit =
@@ -4796,7 +4700,7 @@ void EditCommentPopUp(index, title, text)
 
     if (editShell == NULL) {
        editShell =
-         CommentCreate(title, text, True, EditCommentCallback, 4); 
+         CommentCreate(title, text, True, EditCommentCallback, 4);
        XtRealizeWidget(editShell);
        CatchDeleteWindow(editShell, "EditCommentPopDown");
     } else {
@@ -4875,7 +4779,7 @@ void ICSInputBoxPopUp()
     int j;
     char *title = _("ICS Input");
     XtTranslations tr;
-       
+
     if (ICSInputShell == NULL) {
        ICSInputShell = MiscCreate(title, "", True, NULL, 1);
        tr = XtParseTranslationTable(ICSInputTranslations);
@@ -4883,7 +4787,7 @@ void ICSInputBoxPopUp()
        XtOverrideTranslations(edit, tr);
        XtRealizeWidget(ICSInputShell);
        CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
-       
+
     } else {
        edit = XtNameToWidget(ICSInputShell, "*form.text");
        j = 0;
@@ -4911,7 +4815,7 @@ void ICSInputSendText()
     int j;
     Arg args[16];
     String val;
-  
+
     edit = XtNameToWidget(ICSInputShell, "*form.text");
     j = 0;
     XtSetArg(args[j], XtNstring, &val); j++;
@@ -4965,37 +4869,6 @@ void CommentPopUp(title, text)
     commentUp = True;
 }
 
-void AnalysisPopUp(title, text)
-     char *title, *text;
-{
-    Arg args[16];
-    int j;
-    Widget edit;
-
-    if (analysisShell == NULL) {
-       analysisShell = MiscCreate(title, text, False, NULL, 4);
-       XtRealizeWidget(analysisShell);
-       CatchDeleteWindow(analysisShell, "AnalysisPopDown");
-
-    } else {
-       edit = XtNameToWidget(analysisShell, "*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(analysisShell, args, j);
-    }
-
-    if (!analysisUp) {
-       XtPopup(analysisShell, XtGrabNone);
-    }
-    XSync(xDisplay, False);
-
-    analysisUp = True;
-}
-
 void CommentCallback(w, client_data, call_data)
      Widget w;
      XtPointer client_data, call_data;
@@ -5034,17 +4907,6 @@ void CommentPopDown()
     commentUp = False;
 }
 
-void AnalysisPopDown()
-{
-    if (!analysisUp) return;
-    XtPopdown(analysisShell);
-    XSync(xDisplay, False);
-    analysisUp = False;
-    /* icsEngineAnalyze */
-    if (appData.icsEngineAnalyze) ExitAnalyzeMode();
-}
-
-
 void FileNamePopUp(label, def, proc, openMode)
      char *label;
      char *def;
@@ -5057,10 +4919,10 @@ void FileNamePopUp(label, def, proc, openMode)
     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++;
@@ -5068,11 +4930,11 @@ void FileNamePopUp(label, def, proc, openMode)
     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++;
@@ -5082,21 +4944,21 @@ void FileNamePopUp(label, def, proc, openMode)
 
     XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
     XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
-                       (XtPointer) dialog);
+                      (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);
 }
@@ -5116,15 +4978,15 @@ void FileNameCallback(w, client_data, call_data)
 {
     String name;
     Arg args[16];
-    
+
     XtSetArg(args[0], XtNlabel, &name);
     XtGetValues(w, args, 1);
-    
+
     if (strcmp(name, _("cancel")) == 0) {
         FileNamePopDown();
         return;
     }
-    
+
     FileNameAction(w, NULL, NULL, NULL);
 }
 
@@ -5141,7 +5003,7 @@ void FileNameAction(w, event, prms, nprms)
     int index;
 
     name = XawDialogGetValueString(w = XtParent(w));
-    
+
     if ((name != NULL) && (*name != NULLCHAR)) {
        strcpy(buf, name);
        XtPopdown(w = XtParent(XtParent(w)));
@@ -5170,7 +5032,7 @@ void FileNameAction(w, event, prms, nprms)
        ModeHighlight();
        return;
     }
-    
+
     XtPopdown(w = XtParent(XtParent(w)));
     XtDestroyWidget(w);
     filenameUp = False;
@@ -5188,7 +5050,7 @@ void PromotionPopUp()
     j = 0;
     XtSetArg(args[j], XtNwidth, &bw_width); j++;
     XtGetValues(boardWidget, args, j);
-    
+
     j = 0;
     XtSetArg(args[j], XtNresizable, True); j++;
     XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
@@ -5198,48 +5060,64 @@ void PromotionPopUp()
     layout =
       XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
                            layoutArgs, XtNumber(layoutArgs));
-    
+
     j = 0;
-    XtSetArg(args[j], XtNlabel, _("Promote pawn to what?")); j++;
+    XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
     XtSetArg(args[j], XtNborderWidth, 0); j++;
     dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
                                   layout, args, j);
-    
-    XawDialogAddButton(dialog, _("Queen"), PromotionCallback, 
+
+  if(gameInfo.variant != VariantShogi) {
+    XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
                       (XtPointer) dialog);
-    XawDialogAddButton(dialog, _("Rook"), PromotionCallback, 
+    XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
                       (XtPointer) dialog);
-    XawDialogAddButton(dialog, _("Bishop"), PromotionCallback, 
+    XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
                       (XtPointer) dialog);
-    XawDialogAddButton(dialog, _("Knight"), PromotionCallback, 
+    XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
                       (XtPointer) dialog);
     if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
         gameInfo.variant == VariantGiveaway) {
-      XawDialogAddButton(dialog, _("King"), PromotionCallback, 
+      XawDialogAddButton(dialog, _("King"), PromotionCallback,
+                        (XtPointer) dialog);
+    }
+    if(gameInfo.variant == VariantCapablanca || 
+       gameInfo.variant == VariantGothic || 
+       gameInfo.variant == VariantCapaRandom) {
+      XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
+                        (XtPointer) dialog);
+      XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
                         (XtPointer) dialog);
     }
-    XawDialogAddButton(dialog, _("cancel"), PromotionCallback, 
+  } else // [HGM] shogi
+  {
+      XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
+                        (XtPointer) dialog);
+      XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
+                        (XtPointer) dialog);
+  }
+    XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
                       (XtPointer) dialog);
-    
+
     XtRealizeWidget(promotionShell);
     CatchDeleteWindow(promotionShell, "PromotionPopDown");
-    
+
     j = 0;
     XtSetArg(args[j], XtNwidth, &pw_width); j++;
     XtGetValues(promotionShell, args, j);
-    
+
     XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
                      lineGap + squareSize/3 +
-                     ((toY == 7) ^ (flipView) ?
+                     ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
                       0 : 6*(squareSize + lineGap)), &x, &y);
-    
+
     j = 0;
     XtSetArg(args[j], XtNx, x); j++;
     XtSetArg(args[j], XtNy, y); j++;
     XtSetValues(promotionShell, args, j);
-    
+
     XtPopup(promotionShell, XtGrabNone);
-    
+
     promotionUp = True;
 }
 
@@ -5258,20 +5136,24 @@ void PromotionCallback(w, client_data, call_data)
     String name;
     Arg args[16];
     int promoChar;
-    
+
     XtSetArg(args[0], XtNlabel, &name);
     XtGetValues(w, args, 1);
-    
+
     PromotionPopDown();
-    
+
     if (fromX == -1) return;
-    
+
     if (strcmp(name, _("cancel")) == 0) {
        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]);
     }
@@ -5316,28 +5198,28 @@ void ErrorPopUp(title, label, modal)
     Dimension bw_width, pw_width;
     Dimension pw_height;
     int i;
-    
+
     i = 0;
     XtSetArg(args[i], XtNresizable, True);  i++;
     XtSetArg(args[i], XtNtitle, title); i++;
-    errorShell = 
+    errorShell =
       XtCreatePopupShell("errorpopup", transientShellWidgetClass,
                         shellWidget, args, i);
     layout =
       XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
                            layoutArgs, XtNumber(layoutArgs));
-    
+
     i = 0;
     XtSetArg(args[i], XtNlabel, label); i++;
     XtSetArg(args[i], XtNborderWidth, 0); i++;
     dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
                                   layout, args, i);
-    
+
     XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
-    
+
     XtRealizeWidget(errorShell);
     CatchDeleteWindow(errorShell, "ErrorPopDown");
-    
+
     i = 0;
     XtSetArg(args[i], XtNwidth, &bw_width);  i++;
     XtGetValues(boardWidget, args, i);
@@ -5430,7 +5312,7 @@ char *ModeToWidgetName(mode)
       case EndOfGame:
        return NULL;
     }
-}     
+}
 
 void ModeHighlight()
 {
@@ -5438,7 +5320,7 @@ void ModeHighlight()
     static int oldPausing = FALSE;
     static GameMode oldmode = (GameMode) -1;
     char *wname;
-    
+
     if (!boardWidget || !XtIsRealized(boardWidget)) return;
 
     if (pausing != oldPausing) {
@@ -5452,15 +5334,6 @@ void ModeHighlight()
                    args, 1);
 
        if (appData.showButtonBar) {
-#if 0
-         if (pausing) {
-           XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
-           XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
-         } else {
-           XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
-           XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
-         }
-#else
          /* Always toggle, don't set.  Previous code messes up when
             invoked while the button is pressed, as releasing it
             toggles the state again. */
@@ -5473,7 +5346,6 @@ void ModeHighlight()
            XtSetArg(args[0], XtNbackground, oldfg);
            XtSetArg(args[1], XtNforeground, oldbg);
          }
-#endif
          XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
        }
     }
@@ -5495,6 +5367,7 @@ void ModeHighlight()
                   gameMode == Training || gameMode == PlayFromGameFile);
 }
 
+
 /*
  * Button/menu procedures
  */
@@ -5505,7 +5378,6 @@ void ResetProc(w, event, prms, nprms)
      Cardinal *nprms;
 {
     ResetGameEvent();
-    AnalysisPopDown();
 }
 
 int LoadGamePopUp(f, gameNumber, title)
@@ -5658,7 +5530,7 @@ SendPositionSelection(Widget w, Atom *selection, Atom *target,
   char *selection_tmp;
 
   if (!selected_fen_position) return False; /* should never happen */
-  if (*target == XA_STRING){
+  if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){
     /* note: since no XtSelectionDoneProc was registered, Xt will
      * automatically call XtFree on the value returned.  So have to
      * make a copy of it allocated with XtMalloc */
@@ -5667,12 +5539,25 @@ SendPositionSelection(Widget w, Atom *selection, Atom *target,
 
     *value_return=selection_tmp;
     *length_return=strlen(selection_tmp);
-    *type_return=XA_STRING;
+    *type_return=*target;
     *format_return = 8; /* bits per byte */
     return True;
+  } else if (*target == XA_TARGETS(xDisplay)) {
+    Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom));
+    targets_tmp[0] = XA_UTF8_STRING(xDisplay);
+    targets_tmp[1] = XA_STRING;
+    *value_return = targets_tmp;
+    *type_return = XA_ATOM;
+    *length_return = 2;
+    *format_return = 8 * sizeof(Atom);
+    if (*format_return > 32) {
+      *length_return *= *format_return / 32;
+      *format_return = 32;
+    }
+    return True;
   } else {
     return False;
-  } 
+  }
 }
 
 /* note: when called from menu all parameters are NULL, so no clue what the
@@ -5684,20 +5569,25 @@ void CopyPositionProc(w, event, prms, nprms)
   String *prms;
   Cardinal *nprms;
   {
-    int ret;
-
+    /*
+     * 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);
+    selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
     if (!selected_fen_position) return;
-    ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
-                        CurrentTime,
-                        SendPositionSelection,
-                        NULL/* lose_ownership_proc */ ,
-                        NULL/* transfer_done_proc */);
-    if (!ret) {
-      free(selected_fen_position);
-      selected_fen_position=NULL;
-    }
+    XtOwnSelection(menuBarWidget, XA_PRIMARY,
+                  CurrentTime,
+                  SendPositionSelection,
+                  NULL/* lose_ownership_proc */ ,
+                  NULL/* transfer_done_proc */);
+    XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
+                  CurrentTime,
+                  SendPositionSelection,
+                  NULL/* lose_ownership_proc */ ,
+                  NULL/* transfer_done_proc */);
   }
 
 /* function called when the data to Paste is ready */
@@ -5720,7 +5610,8 @@ void PastePositionProc(w, event, prms, nprms)
   String *prms;
   Cardinal *nprms;
 {
-    XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
+    XtGetSelectionValue(menuBarWidget, 
+      appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
       /* (XtSelectionCallbackProc) */ PastePositionCB,
       NULL, /* client_data passed to PastePositionCB */
 
@@ -5739,7 +5630,7 @@ SendGameSelection(Widget w, Atom *selection, Atom *target,
 {
   char *selection_tmp;
 
-  if (*target == XA_STRING){
+  if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){
     FILE* f = fopen(gameCopyFilename, "r");
     long len;
     size_t count;
@@ -5756,12 +5647,25 @@ SendGameSelection(Widget w, Atom *selection, Atom *target,
     selection_tmp[len] = NULLCHAR;
     *value_return = selection_tmp;
     *length_return = len;
-    *type_return = XA_STRING;
+    *type_return = *target;
     *format_return = 8; /* bits per byte */
     return True;
+  } else if (*target == XA_TARGETS(xDisplay)) {
+    Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom));
+    targets_tmp[0] = XA_UTF8_STRING(xDisplay);
+    targets_tmp[1] = XA_STRING;
+    *value_return = targets_tmp;
+    *type_return = XA_ATOM;
+    *length_return = 2;
+    *format_return = 8 * sizeof(Atom);
+    if (*format_return > 32) {
+      *length_return *= *format_return / 32;
+      *format_return = 32;
+    }
+    return True;
   } else {
     return False;
-  } 
+  }
 }
 
 /* note: when called from menu all parameters are NULL, so no clue what the
@@ -5778,11 +5682,21 @@ void CopyGameProc(w, event, prms, nprms)
   ret = SaveGameToFile(gameCopyFilename, FALSE);
   if (!ret) return;
 
-  ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
-                      CurrentTime,
-                      SendGameSelection,
-                      NULL/* lose_ownership_proc */ ,
-                      NULL/* transfer_done_proc */);
+  /*
+   * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
+   * have a notion of a game that is selected but not copied.
+   * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki
+   */
+  XtOwnSelection(menuBarWidget, XA_PRIMARY,
+                CurrentTime,
+                SendGameSelection,
+                NULL/* lose_ownership_proc */ ,
+                NULL/* transfer_done_proc */);
+  XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
+                CurrentTime,
+                SendGameSelection,
+                NULL/* lose_ownership_proc */ ,
+                NULL/* transfer_done_proc */);
 }
 
 /* function called when the data to Paste is ready */
@@ -5813,7 +5727,8 @@ void PasteGameProc(w, event, prms, nprms)
   String *prms;
   Cardinal *nprms;
 {
-    XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
+    XtGetSelectionValue(menuBarWidget,
+      appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
       /* (XtSelectionCallbackProc) */ PasteGameCB,
       NULL, /* client_data passed to PasteGameCB */
 
@@ -5876,40 +5791,39 @@ void AnalyzeModeProc(w, event, prms, nprms)
      Cardinal *nprms;
 {
     char buf[MSG_SIZ];
-    
+
     if (!first.analysisSupport) {
-      sprintf(buf, _("%s does not support analysis"), first.tidy);
+      snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
       DisplayError(buf, 0);
       return;
     }
-    /* icsEngineAnalyze */
+    /* [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"));
-       DisplayError(buf, 0);
-       /* secure check */
-       if (appData.icsEngineAnalyze) {
-         if (appData.debugMode)
-           fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
-           ExitAnalyzeMode();
-           ModeHighlight();
-           return;
-       }
-       return;
-     } else {
-        /* if enable, use want disable icsEngineAnalyze */
-       if (appData.icsEngineAnalyze) {
-          ExitAnalyzeMode();
-          ModeHighlight();
-          return;
+        if (gameMode != IcsObserving) {
+            sprintf(buf,_("You are not observing a game"));
+            DisplayError(buf, 0);
+            /* secure check */
+            if (appData.icsEngineAnalyze) {
+                if (appData.debugMode)
+                    fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
+                ExitAnalyzeMode();
+                ModeHighlight();
+            }
+            return;
+        }
+        /* if enable, use want disable icsEngineAnalyze */
+        if (appData.icsEngineAnalyze) {
+                ExitAnalyzeMode();
+                ModeHighlight();
+                return;
         }
         appData.icsEngineAnalyze = TRUE;
         if (appData.debugMode)
-          fprintf(debugFP, "ICS engine analyze starting... \n");
-      }
-   }   
+            fprintf(debugFP, _("ICS engine analyze starting... \n"));
+    }
     if (!appData.showThinking)
       ShowThinkingProc(w,event,prms,nprms);
+
     AnalyzeModeEvent();
 }
 
@@ -5921,7 +5835,7 @@ void AnalyzeFileProc(w, event, prms, nprms)
 {
     if (!first.analysisSupport) {
       char buf[MSG_SIZ];
-      sprintf(buf, _("%s does not support analysis"), first.tidy);
+      snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
       DisplayError(buf, 0);
       return;
     }
@@ -6078,6 +5992,33 @@ void ResignProc(w, event, prms, nprms)
     ResignEvent();
 }
 
+void AdjuWhiteProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+    UserAdjudicationEvent(+1);
+}
+
+void AdjuBlackProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+    UserAdjudicationEvent(-1);
+}
+
+void AdjuDrawProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+    UserAdjudicationEvent(0);
+}
+
 void EnterKeyProc(w, event, prms, nprms)
      Widget w;
      XEvent *event;
@@ -6555,7 +6496,7 @@ void PeriodicUpdatesProc(w, event, prms, nprms)
     Arg args[16];
 
     PeriodicUpdatesEvent(!appData.periodicUpdates);
-       
+
     if (appData.periodicUpdates) {
        XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
     } else {
@@ -6686,20 +6627,59 @@ void ShowThinkingProc(w, event, prms, nprms)
      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;
+{
+    Arg args[16];
+
+    appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
+    ShowThinkingEvent();
+
+    if (appData.hideThinkingFromHuman) {
+       XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+    } else {
+       XtSetArg(args[0], XtNleftBitmap, None);
+    }
+    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
+               args, 1);
+}
+
+void SaveOnExitProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
 {
     Arg args[16];
 
-    ShowThinkingEvent(!appData.showThinking);
+    saveSettingsOnExit = !saveSettingsOnExit;
 
-    if (appData.showThinking) {
+    if (saveSettingsOnExit) {
        XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
     } else {
        XtSetArg(args[0], XtNleftBitmap, None);
     }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
+    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Save Settings on Exit"),
                args, 1);
 }
 
+void SaveSettingsProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+     SaveSettings(settingsFileName);
+}
+
 void InfoProc(w, event, prms, nprms)
      Widget w;
      XEvent *event;
@@ -6707,7 +6687,7 @@ void InfoProc(w, event, prms, nprms)
      Cardinal *nprms;
 {
     char buf[MSG_SIZ];
-    sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
+    snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
            INFODIR, INFOFILE);
     system(buf);
 }
@@ -6724,7 +6704,7 @@ void ManProc(w, event, prms, nprms)
       name = prms[0];
     else
       name = "xboard";
-    sprintf(buf, "xterm -e man %s &", name);
+    snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
     system(buf);
 }
 
@@ -6758,11 +6738,12 @@ void AboutProc(w, event, prms, nprms)
 #else
     char *zippy = "";
 #endif
-    sprintf(buf, "%s%s\n\n%s\n%s\n\n%s%s\n%s",
+    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-2001 Free Software Foundation",
-           PRODUCT, " is free software and carries NO WARRANTY;",
+           "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.");
     ErrorPopUp(_("About XBoard"), buf, FALSE);
 }
@@ -6801,7 +6782,7 @@ void Iconify(w, event, prms, nprms)
      Cardinal *nprms;
 {
     Arg args[16];
-    
+
     fromX = fromY = -1;
     XtSetArg(args[0], XtNiconic, True);
     XtSetValues(shellWidget, args, 1);
@@ -6810,19 +6791,34 @@ void Iconify(w, event, prms, nprms)
 void DisplayMessage(message, extMessage)
      char *message, *extMessage;
 {
-    char buf[MSG_SIZ];
-    Arg arg;
-    
-    if (extMessage) {
-       if (*message) {
-           sprintf(buf, "%s  %s", message, extMessage);
-           message = buf;
-       } else {
-           message = extMessage;
-       }
-    }
-    XtSetArg(arg, XtNlabel, message);
-    XtSetValues(messageWidget, &arg, 1);
+  /* display a message in the message widget */
+  
+  char buf[MSG_SIZ];
+  Arg arg;
+  
+  if (extMessage) 
+    {
+      if (*message) 
+       {
+         snprintf(buf, sizeof(buf), "%s  %s", message, extMessage);
+         message = buf;
+       } 
+      else 
+       {
+         message = extMessage;
+       };
+    };
+  
+  /* 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 */
+  if(messageWidget)
+    {
+      XtSetArg(arg, XtNlabel, message);
+      XtSetValues(messageWidget, &arg, 1);
+    };
+  
+  return;
 }
 
 void DisplayTitle(text)
@@ -6845,17 +6841,28 @@ void DisplayTitle(text)
        strcpy(icon, text);
        strcpy(title, text);
     } else if (appData.icsActive) {
-       sprintf(icon, "%s", appData.icsHost);
-       sprintf(title, "%s: %s", programName, appData.icsHost);
+        snprintf(icon, sizeof(icon), "%s", appData.icsHost);
+       snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
     } else if (appData.cmailGameName[0] != NULLCHAR) {
-       sprintf(icon, "%s", "CMail");
-       sprintf(title, "%s: %s", programName, "CMail");
+        snprintf(icon, sizeof(icon), "%s", "CMail");
+       snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
+#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);
+#endif
+#ifdef FALCON
+    } else if (gameInfo.variant == VariantFalcon) {
+       strcpy(icon, programName);
+       strcpy(title, FALCON);
+#endif
     } else if (appData.noChessProgram) {
        strcpy(icon, programName);
        strcpy(title, programName);
     } else {
        strcpy(icon, first.tidy);
-       sprintf(title, "%s: %s", programName, first.tidy);
+       snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
     }
     i = 0;
     XtSetArg(args[i], XtNiconName, (XtArgVal) icon);    i++;
@@ -6879,9 +6886,9 @@ void DisplayError(message, error)
            fprintf(stderr, "%s: %s: %s\n",
                    programName, message, strerror(error));
        }
-       sprintf(buf, "%s: %s", message, strerror(error));
+       snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
        message = buf;
-    }  
+    }
     ErrorPopUp(_("Error"), message, FALSE);
 }
 
@@ -6915,7 +6922,7 @@ void DisplayFatalError(message, error, status)
     } else {
        fprintf(stderr, "%s: %s: %s\n",
                programName, message, strerror(error));
-       sprintf(buf, "%s: %s", message, strerror(error));
+       snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
        message = buf;
     }
     if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
@@ -6969,9 +6976,9 @@ void DisplayIcsInteractionTitle(message)
       XSetErrorHandler(oldHandler);
     }
     if (oldICSInteractionTitle == NULL) {
-      oldICSInteractionTitle = "xterm"; 
+      oldICSInteractionTitle = "xterm";
     }
-  }  
+  }
   printf("\033]0;%s\007", message);
   fflush(stdout);
 }
@@ -7031,7 +7038,7 @@ void AskQuestionCallback(w, client_data, call_data)
 
     XtSetArg(args[0], XtNlabel, &name);
     XtGetValues(w, args, 1);
-    
+
     if (strcmp(name, _("cancel")) == 0) {
         AskQuestionPopDown();
     } else {
@@ -7049,28 +7056,28 @@ void AskQuestion(title, question, replyPrefix, pr)
     int x, y, i;
     int win_x, win_y;
     unsigned int mask;
-    
+
     strcpy(pendingReplyPrefix, replyPrefix);
     pendingReplyPR = pr;
-    
+
     i = 0;
     XtSetArg(args[i], XtNresizable, True); i++;
     XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
     askQuestionShell = popup =
       XtCreatePopupShell(title, transientShellWidgetClass,
                         shellWidget, args, i);
-    
+
     layout =
       XtCreateManagedWidget(layoutName, formWidgetClass, popup,
                            layoutArgs, XtNumber(layoutArgs));
-  
+
     i = 0;
     XtSetArg(args[i], XtNlabel, question); i++;
     XtSetArg(args[i], XtNvalue, ""); i++;
     XtSetArg(args[i], XtNborderWidth, 0); i++;
     dialog = XtCreateManagedWidget("question", dialogWidgetClass,
                                   layout, args, i);
-    
+
     XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
                       (XtPointer) dialog);
     XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
@@ -7078,17 +7085,17 @@ void AskQuestion(title, question, replyPrefix, pr)
 
     XtRealizeWidget(popup);
     CatchDeleteWindow(popup, "AskQuestionPopDown");
-    
+
     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);
     askQuestionUp = True;
-    
+
     edit = XtNameToWidget(dialog, "*value");
     XtSetKeyboardFocus(popup, edit);
 }
@@ -7104,7 +7111,7 @@ PlaySound(name)
     putc(BELLCHAR, stderr);
   } else {
     char buf[2048];
-    sprintf(buf, "%s '%s' &", appData.soundProgram, name);
+    snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
     system(buf);
   }
 }
@@ -7234,7 +7241,7 @@ static char *ExpandPathName(path)
     static char static_buf[2000];
     char *d, *s, buf[2000];
     struct passwd *pwd;
-  
+
     s = path;
     d = static_buf;
 
@@ -7269,12 +7276,12 @@ static char *ExpandPathName(path)
       strcpy(d, s);
 
     return static_buf;
-}  
+}
 
 char *HostName()
 {
     static char host_name[MSG_SIZ];
-    
+
 #if HAVE_GETHOSTNAME
     gethostname(host_name, MSG_SIZ);
     return host_name;
@@ -7302,6 +7309,9 @@ void
 ScheduleDelayedEvent(cb, millisec)
      DelayedEventCallback cb; long millisec;
 {
+    if(delayedEventTimerXID && delayedEventCallback == cb)
+       // [HGM] alive: replace, rather than add or flush identical event
+       XtRemoveTimeOut(delayedEventTimerXID);
     delayedEventCallback = cb;
     delayedEventTimerXID =
       XtAppAddTimeOut(appContext, millisec,
@@ -7371,8 +7381,8 @@ AnalysisClockCallback(arg, id)
      XtPointer arg;
      XtIntervalId *id;
 {
-    if (gameMode == AnalyzeMode || gameMode == AnalyzeFile 
-         || appData.icsEngineAnalyze) {
+    if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
+         || appData.icsEngineAnalyze) { // [DM]
        AnalysisPeriodicEvent(0);
        StartAnalysisClock();
     }
@@ -7433,7 +7443,15 @@ DisplayTimerLabel(w, color, timer, highlight)
 {
     char buf[MSG_SIZ];
     Arg args[16];
-    
+
+    /* check for low time warning */
+    Pixel foregroundOrWarningColor = timerForegroundPixel;
+
+    if (timer > 0 &&
+        appData.lowTimeWarning && 
+        (timer / 1000) < appData.icsAlarmTime)
+      foregroundOrWarningColor = lowTimeWarningColor;
+
     if (appData.clockMode) {
        sprintf(buf, "%s: %s", color, TimeString(timer));
        XtSetArg(args[0], XtNlabel, buf);
@@ -7441,15 +7459,16 @@ DisplayTimerLabel(w, color, timer, highlight)
        sprintf(buf, "%s  ", color);
        XtSetArg(args[0], XtNlabel, buf);
     }
-    
+
     if (highlight) {
-       XtSetArg(args[1], XtNbackground, timerForegroundPixel);
+
+       XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
        XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
     } else {
        XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
-       XtSetArg(args[2], XtNforeground, timerForegroundPixel);
+       XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
     }
-    
+
     XtSetValues(w, args, 3);
 }
 
@@ -7459,6 +7478,8 @@ DisplayWhiteClock(timeRemaining, highlight)
      int highlight;
 {
     Arg args[16];
+
+    if(appData.noGUI) return;
     DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
     if (highlight && iconPixmap == bIconPixmap) {
        iconPixmap = wIconPixmap;
@@ -7473,6 +7494,8 @@ DisplayBlackClock(timeRemaining, highlight)
      int highlight;
 {
     Arg args[16];
+
+    if(appData.noGUI) return;
     DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
     if (highlight && iconPixmap == wIconPixmap) {
        iconPixmap = bIconPixmap;
@@ -7491,12 +7514,12 @@ typedef int CPKind;
 typedef struct {
     CPKind kind;
     int pid;
-    int fdTo, fdFrom;  
+    int fdTo, fdFrom;
 } ChildProc;
 
 
 int StartChildProcess(cmdLine, dir, pr)
-     char *cmdLine; 
+     char *cmdLine;
      char *dir;
      ProcRef *pr;
 {
@@ -7505,7 +7528,7 @@ int StartChildProcess(cmdLine, dir, pr)
     int to_prog[2], from_prog[2];
     ChildProc *cp;
     char buf[MSG_SIZ];
-    
+
     if (appData.debugMode) {
        fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
     }
@@ -7518,8 +7541,11 @@ int StartChildProcess(cmdLine, dir, pr)
     strcpy(buf, cmdLine);
     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;
     }
@@ -7529,30 +7555,34 @@ int StartChildProcess(cmdLine, dir, pr)
 
     if ((pid = fork()) == 0) {
        /* Child process */
-       dup2(to_prog[0], 0);
-       dup2(from_prog[1], 1);
-       close(to_prog[0]);
-       close(to_prog[1]);
+       // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
+       close(to_prog[1]);     // first close the unused pipe ends
        close(from_prog[0]);
-       close(from_prog[1]);
-       dup2(1, fileno(stderr)); /* force stderr to the pipe */
+       dup2(to_prog[0], 0);   // to_prog was created first, nd is the only one to use 0 or 1
+       dup2(from_prog[1], 1);
+       if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
+       close(from_prog[1]);                   // and closing again loses one of the pipes!
+       if(fileno(stderr) >= 2) // better safe than sorry...
+               dup2(1, fileno(stderr)); /* force stderr to the pipe */
 
        if (dir[0] != NULLCHAR && chdir(dir) != 0) {
            perror(dir);
            exit(1);
        }
 
+       nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
+
         execvp(argv[0], argv);
-       
+
        /* If we get here, exec failed */
        perror(argv[0]);
        exit(1);
     }
-    
+
     /* Parent process */
     close(to_prog[0]);
     close(from_prog[1]);
-    
+
     cp = (ChildProc *) calloc(1, sizeof(ChildProc));
     cp->kind = CPReal;
     cp->pid = pid;
@@ -7562,22 +7592,37 @@ int StartChildProcess(cmdLine, dir, pr)
     return 0;
 }
 
+// [HGM] kill: implement the 'hard killing' of AS's Winboard_x
+static RETSIGTYPE AlarmCallBack(int n)
+{
+    return;
+}
+
 void
-DestroyChildProcess(pr, signal)
+DestroyChildProcess(pr, signalType)
      ProcRef pr;
-     int signal;
+     int signalType;
 {
     ChildProc *cp = (ChildProc *) pr;
 
     if (cp->kind != CPReal) return;
     cp->kind = CPNone;
-    if (signal) {
-      kill(cp->pid, SIGTERM);
+    if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
+       signal(SIGALRM, AlarmCallBack);
+       alarm(3);
+       if(wait((int *) 0) == -1) { // process does not terminate on its own accord
+           kill(cp->pid, SIGKILL); // kill it forcefully
+           wait((int *) 0);        // and wait again
+       }
+    } else {
+       if (signalType) {
+           kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
+       }
+       /* Process is exiting either because of the kill or because of
+          a quit command sent by the backend; either way, wait for it to die.
+       */
+       wait((int *) 0);
     }
-    /* Process is exiting either because of the kill or because of
-       a quit command sent by the backend; either way, wait for it to die.
-    */
-    wait((int *) 0);
     close(cp->fdFrom);
     close(cp->fdTo);
 }
@@ -7600,9 +7645,9 @@ int OpenTelnet(host, port, pr)
     char cmdLine[MSG_SIZ];
 
     if (port[0] == NULLCHAR) {
-       sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
+      snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
     } else {
-       sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
+      snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
     }
     return StartChildProcess(cmdLine, "", pr);
 }
@@ -7656,7 +7701,7 @@ int OpenTCP(host, port, pr)
     sa.sin_port = htons(uport);
     memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
 
-    if (connect(s, (struct sockaddr *) &sa, 
+    if (connect(s, (struct sockaddr *) &sa,
                sizeof(struct sockaddr_in)) < 0) {
        return errno;
     }
@@ -7717,7 +7762,7 @@ int OpenRcmd(host, user, cmd, pr)
 {
     DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
     return -1;
-}    
+}
 
 #define INPUT_SOURCE_BUF_SIZE 8192
 
@@ -7733,7 +7778,7 @@ typedef struct {
 } InputSource;
 
 void
-DoInputCallback(closure, source, xid) 
+DoInputCallback(closure, source, xid)
      caddr_t closure;
      int *source;
      XtInputId *xid;
@@ -7771,7 +7816,7 @@ DoInputCallback(closure, source, xid)
        else
          error = 0;
        (is->func)(is, is->closure, is->buf, count, error);
-    }  
+    }
 }
 
 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
@@ -7796,7 +7841,7 @@ InputSourceRef AddInputSource(pr, lineByLine, func, closure)
     if (lineByLine) {
        is->unused = is->buf;
     }
-    
+
     is->xid = XtAppAddInput(appContext, is->fd,
                            (XtPointer) (XtInputReadMask),
                            (XtInputCallbackProc) DoInputCallback,
@@ -7822,11 +7867,33 @@ int OutputToProcess(pr, message, count, outError)
      int count;
      int *outError;
 {
+    static int line = 0;
     ChildProc *cp = (ChildProc *) pr;
     int outCount;
 
     if (pr == NoProc)
-      outCount = fwrite(message, 1, count, stdout);
+    {
+        if (appData.noJoin || !appData.useInternalWrap)
+            outCount = fwrite(message, 1, count, stdout);
+        else
+        {
+            int width = get_term_width();
+            int len = wrap(NULL, message, count, width, &line);
+            char *msg = malloc(len);
+            int dbgchk;
+
+            if (!msg)
+                outCount = fwrite(message, 1, count, stdout);
+            else
+            {
+                dbgchk = wrap(msg, message, count, width, &line);
+                if (dbgchk != len && appData.debugMode)
+                    fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len);
+                outCount = fwrite(msg, 1, dbgchk, stdout);
+                free(msg);
+            }
+        }
+    }
     else
       outCount = write(cp->fdTo, message, count);
 
@@ -7852,7 +7919,7 @@ int OutputToProcessDelayed(pr, message, count, outError, msdelay)
     ChildProc *cp = (ChildProc *) pr;
     int outCount = 0;
     int r;
-    
+
     while (count--) {
        r = write(cp->fdTo, message++, 1);
        if (r == -1) {
@@ -7886,6 +7953,8 @@ int OutputToProcessDelayed(pr, message, count, outError, msdelay)
        and dark squares, and all pieces must use the same
        background square colors/images.                */
 
+static int xpmDone = 0;
+
 static void
 CreateAnimMasks (pieceDepth)
      int pieceDepth;
@@ -7908,7 +7977,7 @@ CreateAnimMasks (pieceDepth)
   XFreePixmap(xDisplay, buf);
 
   buf = XCreatePixmap(xDisplay, xBoardWindow,
-                     squareSize, squareSize, pieceDepth);            
+                     squareSize, squareSize, pieceDepth);
   values.foreground = XBlackPixel(xDisplay, xScreen);
   values.background = XWhitePixel(xDisplay, xScreen);
   bufGC = XCreateGC(xDisplay, buf,
@@ -7916,22 +7985,23 @@ CreateAnimMasks (pieceDepth)
 
   for (piece = WhitePawn; piece <= BlackKing; piece++) {
     /* Begin with empty mask */
+    if(!xpmDone) // [HGM] pieces: keep using existing
     xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
                                 squareSize, squareSize, 1);
     XSetFunction(xDisplay, maskGC, GXclear);
     XFillRectangle(xDisplay, xpmMask[piece], maskGC,
                   0, 0, squareSize, squareSize);
-                  
+
     /* Take a copy of the piece */
     if (White(piece))
       kind = 0;
     else
       kind = 2;
     XSetFunction(xDisplay, bufGC, GXcopy);
-    XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
+    XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
              buf, bufGC,
              0, 0, squareSize, squareSize, 0, 0);
-             
+
     /* XOR the background (light) over the piece */
     XSetFunction(xDisplay, bufGC, GXxor);
     if (useImageSqs)
@@ -7941,7 +8011,7 @@ CreateAnimMasks (pieceDepth)
       XSetForeground(xDisplay, bufGC, lightSquareColor);
       XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
     }
-    
+
     /* We now have an inverted piece image with the background
        erased. Construct mask by just selecting all the non-zero
        pixels - no need to reconstruct the original image.     */
@@ -7971,7 +8041,7 @@ InitAnimState (anim, info)
 {
   XtGCMask  mask;
   XGCValues values;
-  
+
   /* Each buffer is square size, same depth as window */
   anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
                        squareSize, squareSize, info->depth);
@@ -7999,19 +8069,20 @@ InitAnimState (anim, info)
 static void
 CreateAnimVars ()
 {
-  static int done = 0;
+  static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
   XWindowAttributes info;
 
-  if (done) return;
-  done = 1;
+  if (xpmDone && gameInfo.variant == old) return;
+  if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
   XGetWindowAttributes(xDisplay, xBoardWindow, &info);
-  
+
   InitAnimState(&game, &info);
   InitAnimState(&player, &info);
-  
+
   /* For XPM pieces, we need bitmaps to use as masks. */
   if (useImages)
     CreateAnimMasks(info.depth);
+   xpmDone = 1;
 }
 
 #ifndef HAVE_USLEEP
@@ -8031,23 +8102,18 @@ FrameDelay (time)
      int time;
 {
   struct itimerval delay;
-  
+
   XSync(xDisplay, False);
 
   if (time > 0) {
     frameWaiting = True;
     signal(SIGALRM, FrameAlarm);
-    delay.it_interval.tv_sec = 
+    delay.it_interval.tv_sec =
       delay.it_value.tv_sec = time / 1000;
-    delay.it_interval.tv_usec = 
+    delay.it_interval.tv_usec =
       delay.it_value.tv_usec = (time % 1000) * 1000;
     setitimer(ITIMER_REAL, &delay, NULL);
-#if 0
-    /* Ugh -- busy-wait! --tpm */
-    while (frameWaiting); 
-#else
     while (frameWaiting) pause();
-#endif
     delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
     delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
     setitimer(ITIMER_REAL, &delay, NULL);
@@ -8074,13 +8140,13 @@ ScreenSquare(column, row, pt, color)
      int column; int row; XPoint * pt; int * color;
 {
   if (flipView) {
-    pt->x = lineGap + ((BOARD_SIZE-1)-column) * (squareSize + lineGap);
+    pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
     pt->y = lineGap + row * (squareSize + lineGap);
   } else {
     pt->x = lineGap + column * (squareSize + lineGap);
-    pt->y = lineGap + ((BOARD_SIZE-1)-row) * (squareSize + lineGap);
+    pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
   }
-  *color = ((column + row) % 2) == 1;
+  *color = SquareColor(row, column);
 }
 
 /*     Convert window coords to square                 */
@@ -8089,12 +8155,12 @@ static void
 BoardSquare(x, y, column, row)
      int x; int y; int * column; int * row;
 {
-  *column = EventToSquare(x, BOARD_SIZE);
+  *column = EventToSquare(x, BOARD_WIDTH);
   if (flipView && *column >= 0)
-    *column = BOARD_SIZE - 1 - *column;
-  *row = EventToSquare(y, BOARD_SIZE);
+    *column = BOARD_WIDTH - 1 - *column;
+  *row = EventToSquare(y, BOARD_HEIGHT);
   if (!flipView && *row >= 0)
-    *row = BOARD_SIZE - 1 - *row;
+    *row = BOARD_HEIGHT - 1 - *row;
 }
 
 /*   Utilities */
@@ -8117,7 +8183,7 @@ SetRect(rect, x, y, width, height)
 /*     Test if two frames overlap. If they do, return
        intersection rect within old and location of
        that rect within new. */
-       
+
 static Boolean
 Intersect(old, new, size, area, pt)
      XPoint * old; XPoint * new;
@@ -8137,7 +8203,7 @@ Intersect(old, new, size, area, pt)
 
 /*     For two overlapping frames, return the rect(s)
        in the old that do not intersect with the new.   */
-       
+
 static void
 CalcUpdateRects(old, new, size, update, nUpdates)
      XPoint * old; XPoint * new; int size;
@@ -8206,11 +8272,11 @@ Tween(start, mid, finish, factor, frames, nFrames)
     count ++;
     fraction = fraction / 2;
   }
-  
+
   /* Midpoint */
   frames[count] = *mid;
   count ++;
-  
+
   /* Slow out, stepping 1/2, then 1/4, ... */
   fraction = 2;
   for (n = 0; n < factor; n++) {
@@ -8237,7 +8303,7 @@ SelectGCMask(piece, clip, outline, mask)
 #if HAVE_LIBXPM
       *mask = xpmMask[piece];
 #else
-      *mask = ximMaskPm[piece%6];
+      *mask = ximMaskPm[piece];
 #endif
   } else {
       *mask = *pieceToSolid(piece);
@@ -8257,7 +8323,7 @@ SelectGCMask(piece, clip, outline, mask)
       source = blPieceGC;
   }
   XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
-  
+
   /* Outline only used in mono mode and is not modified */
   if (White(piece))
     *outline = bwPieceGC;
@@ -8270,7 +8336,7 @@ OverlayPiece(piece, clip, outline,  dest)
      ChessSquare piece; GC clip; GC outline; Drawable dest;
 {
   int  kind;
-  
+
   if (!useImages) {
     /* Draw solid rectangle which will be clipped to shape of piece */
     XFillRectangle(xDisplay, dest, clip,
@@ -8286,16 +8352,16 @@ OverlayPiece(piece, clip, outline,  dest)
       kind = 0;
     else
       kind = 2;
-    XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
+    XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
              dest, clip,
              0, 0, squareSize, squareSize,
-             0, 0);            
+             0, 0);
   }
 }
 
 /* Animate the movement of a single piece */
 
-static void 
+static void
 BeginAnimation(anim, piece, startColor, start)
      AnimState *anim;
      ChessSquare piece;
@@ -8303,11 +8369,11 @@ BeginAnimation(anim, piece, startColor, start)
      XPoint * start;
 {
   Pixmap mask;
-  
+
   /* The old buffer is initialised with the start square (empty) */
   BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
   anim->prevFrame = *start;
-  
+
   /* The piece will be drawn using its own bitmap as a matte   */
   SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
   XSetClipMask(xDisplay, anim->pieceGC, mask);
@@ -8323,12 +8389,12 @@ AnimationFrame(anim, frame, piece)
   XRectangle overlap;
   XPoint     pt;
   int       count, i;
-  
+
   /* Save what we are about to draw into the new buffer */
   XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
            frame->x, frame->y, squareSize, squareSize,
            0, 0);
-               
+
   /* Erase bits of the previous frame */
   if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
     /* Where the new frame overlapped the previous,
@@ -8357,7 +8423,7 @@ AnimationFrame(anim, frame, piece)
                0, 0, squareSize, squareSize,
                0, 0);
   anim->prevFrame = *frame;
-  
+
   /* Draw piece over original screen contents, not current,
      and copy entire rect. Wipes out overlapping piece images. */
   OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
@@ -8430,6 +8496,10 @@ 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) 
+       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;
   piece = board[fromY][fromX];
   if (piece >= EmptySquare) return;
@@ -8441,10 +8511,9 @@ AnimateMove(board, fromX, fromY, toX, toY)
 #endif
 
   if (appData.debugMode) {
-      printf(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);
-  }
+      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);
@@ -8462,19 +8531,19 @@ AnimateMove(board, fromX, fromY, toX, toY)
     mid.x = start.x + (finish.x - start.x) / 2;
     mid.y = start.y + (finish.y - start.y) / 2;
   }
-  
+
   /* Don't use as many frames for very short moves */
   if (abs(toY - fromY) + abs(toX - fromX) <= 2)
     Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
   else
     Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
   FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
-  
+
   /* Be sure end square is redrawn */
   damage[toY][toX] = True;
 }
 
-static void
+void
 DragPieceBegin(x, y)
      int x; int y;
 {
@@ -8484,7 +8553,7 @@ DragPieceBegin(x, y)
     /* Are we animating? */
     if (!appData.animateDragging || appData.blindfold)
       return;
-     
+
     /* Figure out which square we start in and the
        mouse position relative to top left corner. */
     BoardSquare(x, y, &boardX, &boardY);
@@ -8493,19 +8562,10 @@ DragPieceBegin(x, y)
     ScreenSquare(boardX, boardY, &corner, &color);
     player.startSquare  = corner;
     player.startColor   = color;
-#if 0
-    /* Start from exactly where the piece is.  This can be confusing
-       if you start dragging far from the center of the square; most
-       or all of the piece can be over a different square from the one
-       the mouse pointer is in. */
-    player.mouseDelta.x = x - corner.x;
-    player.mouseDelta.y = y - corner.y;
-#else
     /* As soon as we start dragging, the piece will jump slightly to
        be centered over the mouse pointer. */
     player.mouseDelta.x = squareSize/2;
     player.mouseDelta.y = squareSize/2;
-#endif
     /* Initialise animation */
     player.dragPiece = PieceForSquare(boardX, boardY);
     /* Sanity check */
@@ -8515,6 +8575,11 @@ DragPieceBegin(x, y)
        /* Mark this square as needing to be redrawn. Note that
           we don't remove the piece though, since logically (ie
           as seen by opponent) the move hasn't been made yet. */
+           if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
+              boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
+           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;
     } else {
        player.dragActive = False;
@@ -8530,7 +8595,7 @@ DragPieceMove(x, y)
     /* Are we animating? */
     if (!appData.animateDragging || appData.blindfold)
       return;
-     
+
     /* Sanity check */
     if (! player.dragActive)
       return;
@@ -8548,7 +8613,7 @@ DragPieceMove(x, y)
 #endif
 }
 
-static void
+void
 DragPieceEnd(x, y)
      int x; int y;
 {
@@ -8558,7 +8623,7 @@ DragPieceEnd(x, y)
     /* Are we animating? */
     if (!appData.animateDragging || appData.blindfold)
       return;
-     
+
     /* Sanity check */
     if (! player.dragActive)
       return;
@@ -8595,3 +8660,37 @@ DrawDragPiece ()
   damage[player.startBoardY][player.startBoardX] = TRUE;
 }
 
+#include <sys/ioctl.h>
+int get_term_width()
+{
+    int fd, default_width;
+
+    fd = STDIN_FILENO;
+    default_width = 79; // this is FICS default anyway...
+
+#if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
+    struct ttysize win;
+    if (!ioctl(fd, TIOCGSIZE, &win))
+        default_width = win.ts_cols;
+#elif defined(TIOCGWINSZ)
+    struct winsize win;
+    if (!ioctl(fd, TIOCGWINSZ, &win))
+        default_width = win.ws_col;
+#endif
+    return default_width;
+}
+
+void update_ics_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;
+}
+
+void NotifyFrontendLogin()
+{
+    update_ics_width();
+}