Pop up ICS text menu with default item under mouse pointer
[xboard.git] / winboard / winboard.c
index 139a984..092574a 100644 (file)
@@ -1,9 +1,13 @@
 /*\r
  * WinBoard.c -- Windows NT front end to XBoard\r
- * $Id: winboard.c,v 2.3 2003/11/25 05:25:20 mann Exp $\r
  *\r
- * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.\r
- * Enhancements Copyright 1992-2001 Free Software Foundation, Inc.\r
+ * Copyright 1991 by Digital Equipment Corporation, Maynard,\r
+ * Massachusetts. \r
+ *\r
+ * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,\r
+ * 2007, 2008, 2009, 2010 Free Software Foundation, Inc.\r
+ *\r
+ * Enhancements Copyright 2005 Alessandro Scotti\r
  *\r
  * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,\r
  * which was written and is copyrighted by Wayne Christopher.\r
  * SOFTWARE.\r
  * ------------------------------------------------------------------------\r
  *\r
- * The following terms apply to the enhanced version of XBoard distributed\r
- * by the Free Software Foundation:\r
+ * The following terms apply to the enhanced version of XBoard\r
+ * distributed by the Free Software Foundation:\r
  * ------------------------------------------------------------------------\r
- * This program is free software; you can redistribute it and/or modify\r
+ *\r
+ * GNU XBoard is free software: you can redistribute it and/or modify\r
  * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
+ * the Free Software Foundation, either version 3 of the License, or (at\r
+ * your option) any later version.\r
  *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
+ * GNU XBoard is distributed in the hope that it will be useful, but\r
+ * WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+ * General Public License for more details.\r
  *\r
  * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
- * ------------------------------------------------------------------------\r
- */\r
+ * along with this program. If not, see http://www.gnu.org/licenses/.  *\r
+ *\r
+ *------------------------------------------------------------------------\r
+ ** See the file ChangeLog for a revision history.  */\r
 \r
 #include "config.h"\r
 \r
 #include <windows.h>\r
 #include <winuser.h>\r
 #include <winsock.h>\r
+#include <commctrl.h>\r
 \r
 #include <stdio.h>\r
 #include <stdlib.h>\r
@@ -66,6 +72,7 @@
 #include <dlgs.h>\r
 #include <richedit.h>\r
 #include <mmsystem.h>\r
+#include <ctype.h>\r
 \r
 #if __GNUC__\r
 #include <errno.h>\r
 #endif\r
 \r
 #include "common.h"\r
-#include "winboard.h"\r
 #include "frontend.h"\r
 #include "backend.h"\r
+#include "winboard.h"\r
 #include "moves.h"\r
 #include "wclipbrd.h"\r
-#include "wgamelist.h"\r
-#include "wedittags.h"\r
 #include "woptions.h"\r
 #include "wsockerr.h"\r
 #include "defaults.h"\r
-\r
+#include "help.h"\r
 #include "wsnap.h"\r
 \r
-void InitEngineUCI( const char * iniDir, ChessProgramState * cps );\r
+//void InitEngineUCI( const char * iniDir, ChessProgramState * cps );\r
 \r
   int myrandom(void);\r
   void mysrandom(unsigned int seed);\r
 \r
 extern int whiteFlag, blackFlag;\r
 Boolean flipClock = FALSE;\r
+extern HANDLE chatHandle[];\r
+extern int ics_type;\r
 \r
 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);\r
-\r
+VOID NewVariantPopup(HWND hwnd);\r
+int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,\r
+                  /*char*/int promoChar));\r
+void AnimateAtomicCapture(int fromX, int fromY, int toX, int toY, int nFrames);\r
+void DisplayMove P((int moveNumber));\r
+Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen));\r
+void ChatPopUp P((char *s));\r
 typedef struct {\r
   ChessSquare piece;  \r
   POINT pos;      /* window coordinates of current pos */\r
@@ -122,25 +135,34 @@ typedef struct {
 static HighlightInfo highlightInfo        = { {{-1, -1}, {-1, -1}} };\r
 static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };\r
 \r
+typedef struct { // [HGM] atomic\r
+  int fromX, fromY, toX, toY, radius;\r
+} ExplodeInfo;\r
+\r
+static ExplodeInfo explodeInfo;\r
+\r
 /* Window class names */\r
 char szAppName[] = "WinBoard";\r
 char szConsoleName[] = "WBConsole";\r
 \r
 /* Title bar text */\r
 char szTitle[] = "WinBoard";\r
-char szConsoleTitle[] = "ICS Interaction";\r
+char szConsoleTitle[] = "I C S Interaction";\r
 \r
 char *programName;\r
 char *settingsFileName;\r
-BOOLEAN saveSettingsOnExit;\r
+Boolean saveSettingsOnExit;\r
 char installDir[MSG_SIZ];\r
+int errorExitStatus;\r
 \r
 BoardSize boardSize;\r
-BOOLEAN chessProgram;\r
-static int boardX, boardY, consoleX, consoleY, consoleW, consoleH;\r
-static int squareSize, lineGap, minorSize;\r
-static int winWidth, winHeight;\r
-static RECT messageRect, whiteRect, blackRect;\r
+Boolean chessProgram;\r
+//static int boardX, boardY;\r
+int  minX, minY; // [HGM] placement: volatile limits on upper-left corner\r
+int squareSize, lineGap, minorSize;\r
+static int winW, winH;\r
+static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo\r
+static int logoHeight = 0;\r
 static char messageText[MESSAGE_TEXT_MAX];\r
 static int clockTimerEvent = 0;\r
 static int loadGameTimerEvent = 0;\r
@@ -153,14 +175,10 @@ char *icsNames;
 char *firstChessProgramNames;\r
 char *secondChessProgramNames;\r
 \r
-#define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */\r
-\r
 #define PALETTESIZE 256\r
 \r
 HINSTANCE hInst;          /* current instance */\r
-HWND hwndMain = NULL;        /* root window*/\r
-HWND hwndConsole = NULL;\r
-BOOLEAN alwaysOnTop = FALSE;\r
+Boolean alwaysOnTop = FALSE;\r
 RECT boardRect;\r
 COLORREF lightSquareColor, darkSquareColor, whitePieceColor, \r
   blackPieceColor, highlightSquareColor, premoveHighlightColor;\r
@@ -172,9 +190,11 @@ static HWND hwndPause;    /* pause button */
 static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */\r
 static HBRUSH lightSquareBrush, darkSquareBrush,\r
   blackSquareBrush, /* [HGM] for band between board and holdings */\r
-  whitePieceBrush, blackPieceBrush, iconBkgndBrush, outlineBrush;\r
-static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];\r
-static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];\r
+  explodeBrush,     /* [HGM] atomic */\r
+  markerBrush,      /* [HGM] markers */\r
+  whitePieceBrush, blackPieceBrush, iconBkgndBrush /*, outlineBrush*/;\r
+static POINT gridEndpoints[(BOARD_RANKS + BOARD_FILES + 2) * 2];\r
+static DWORD gridVertexCounts[BOARD_RANKS + BOARD_FILES + 2];\r
 static HPEN gridPen = NULL;\r
 static HPEN highlightPen = NULL;\r
 static HPEN premovePen = NULL;\r
@@ -184,31 +204,24 @@ static HICON iconWhite, iconBlack, iconCurrent;
 static int doingSizing = FALSE;\r
 static int lastSizing = 0;\r
 static int prevStderrPort;\r
-\r
-/* [AS] Support for background textures */\r
-#define BACK_TEXTURE_MODE_DISABLED      0\r
-#define BACK_TEXTURE_MODE_PLAIN         1\r
-#define BACK_TEXTURE_MODE_FULL_RANDOM   2\r
+static HBITMAP userLogo;\r
 \r
 static HBITMAP liteBackTexture = NULL;\r
 static HBITMAP darkBackTexture = NULL;\r
 static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;\r
 static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;\r
 static int backTextureSquareSize = 0;\r
-static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_SIZE][BOARD_SIZE];\r
+static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_RANKS][BOARD_FILES];\r
 \r
 #if __GNUC__ && !defined(_winmajor)\r
 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */\r
 #else\r
+#if defined(_winmajor)\r
 #define oldDialog (_winmajor < 4)\r
+#else\r
+#define oldDialog 0\r
+#endif\r
 #endif\r
-\r
-char *defaultTextAttribs[] = \r
-{\r
-  COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,\r
-  COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,\r
-  COLOR_NONE\r
-};\r
 \r
 typedef struct {\r
   char *name;\r
@@ -242,7 +255,7 @@ SizeInfo sizeInfo[] =
   { NULL, 0, 0, 0, 0, 0, 0 }\r
 };\r
 \r
-#define MF(x) {x, {0, }, {0, }, 0}\r
+#define MF(x) {x, {{0,}, 0. }, {0, }, 0}\r
 MyFont fontRec[NUM_SIZES][NUM_FONTS] =\r
 {\r
   { MF(CLOCK_FONT_TINY), MF(MESSAGE_FONT_TINY), MF(COORD_FONT_TINY), MF(CONSOLE_FONT_TINY), MF(COMMENT_FONT_TINY), MF(EDITTAGS_FONT_TINY), MF(MOVEHISTORY_FONT_ALL) },\r
@@ -287,7 +300,7 @@ MyButtonDesc buttonDesc[N_BUTTONS] =
 };\r
 \r
 int tinyLayout = 0, smallLayout = 0;\r
-#define MENU_BAR_ITEMS 6\r
+#define MENU_BAR_ITEMS 7\r
 char *menuBarText[2][MENU_BAR_ITEMS+1] = {\r
   { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },\r
   { "&F", "&M", "&A", "&S", "&O", "&H", NULL },\r
@@ -317,15 +330,7 @@ static char *commentTitle;
 static char *commentText;\r
 static int commentIndex;\r
 static Boolean editComment = FALSE;\r
-HWND commentDialog = NULL;\r
-BOOLEAN commentDialogUp = FALSE;\r
-static int commentX, commentY, commentH, commentW;\r
 \r
-static char *analysisTitle;\r
-static char *analysisText;\r
-HWND analysisDialog = NULL;\r
-BOOLEAN analysisDialogUp = FALSE;\r
-static int analysisX, analysisY, analysisH, analysisW;\r
 \r
 char errorTitle[MSG_SIZ];\r
 char errorMessage[2*MSG_SIZ];\r
@@ -395,35 +400,29 @@ VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
 int NewGameFRC();\r
 int GameListOptions();\r
 \r
-HWND moveHistoryDialog = NULL;\r
-BOOLEAN moveHistoryDialogUp = FALSE;\r
-\r
-WindowPlacement wpMoveHistory;\r
+int dummy; // [HGM] for obsolete args\r
 \r
+HWND hwndMain = NULL;        /* root window*/\r
+HWND hwndConsole = NULL;\r
+HWND commentDialog = NULL;\r
+HWND moveHistoryDialog = NULL;\r
 HWND evalGraphDialog = NULL;\r
-BOOLEAN evalGraphDialogUp = FALSE;\r
-\r
-WindowPlacement wpEvalGraph;\r
-\r
 HWND engineOutputDialog = NULL;\r
-BOOLEAN engineOutputDialogUp = FALSE;\r
-\r
-WindowPlacement wpEngineOutput;\r
+HWND gameListDialog = NULL;\r
+HWND editTagsDialog = NULL;\r
 \r
-VOID MoveHistoryPopUp();\r
-VOID MoveHistoryPopDown();\r
-VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );\r
-BOOL MoveHistoryIsUp();\r
+int commentUp = FALSE;\r
 \r
-VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );\r
-VOID EvalGraphPopUp();\r
-VOID EvalGraphPopDown();\r
-BOOL EvalGraphIsUp();\r
+WindowPlacement wpMain;\r
+WindowPlacement wpConsole;\r
+WindowPlacement wpComment;\r
+WindowPlacement wpMoveHistory;\r
+WindowPlacement wpEvalGraph;\r
+WindowPlacement wpEngineOutput;\r
+WindowPlacement wpGameList;\r
+WindowPlacement wpTags;\r
 \r
-VOID EngineOutputPopUp();\r
-VOID EngineOutputPopDown();\r
-BOOL EngineOutputIsUp();\r
-VOID EngineOutputUpdate( FrontEndProgramStats * stats );\r
+VOID EngineOptionsPopup(); // [HGM] settings\r
 \r
 VOID GothicPopUp(char *title, VariantClass variant);\r
 /*\r
@@ -461,6 +460,26 @@ void ThawUI()
   DrawMenuBar(hwndMain);\r
 }\r
 \r
+/*static*/ int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them\r
+\r
+/* JAWS preparation patch (WinBoard for the sight impaired). Define required insertions as empty */\r
+#ifdef JAWS\r
+#include "jaws.c"\r
+#else\r
+#define JAWS_INIT\r
+#define JAWS_ARGS\r
+#define JAWS_ALT_INTERCEPT\r
+#define JAWS_KB_NAVIGATION\r
+#define JAWS_MENU_ITEMS\r
+#define JAWS_SILENCE\r
+#define JAWS_REPLAY\r
+#define JAWS_ACCEL\r
+#define JAWS_COPYRIGHT\r
+#define JAWS_DELETE(X) X\r
+#define SAYMACHINEMOVE()\r
+#define SAY(X)\r
+#endif\r
+\r
 /*---------------------------------------------------------------------------*\\r
  *\r
  * WinMain\r
@@ -473,6 +492,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 {\r
   MSG msg;\r
   HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;\r
+//  INITCOMMONCONTROLSEX ex;\r
 \r
   debugFP = stderr;\r
 \r
@@ -486,6 +506,11 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
     return (FALSE);\r
   }\r
 \r
+  JAWS_INIT\r
+\r
+//  InitCommonControlsEx(&ex);\r
+  InitCommonControls();\r
+\r
   hAccelMain = LoadAccelerators (hInstance, szAppName);\r
   hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");\r
   hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */\r
@@ -497,6 +522,77 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    0,    /* lowest message to examine */\r
                    0))   /* highest message to examine */\r
     {\r
+\r
+      if(msg.message == WM_CHAR && msg.wParam == '\t') {\r
+       // [HGM] navigate: switch between all windows with tab\r
+       HWND e1 = NULL, e2 = NULL, mh = NULL, hInput = NULL, hText = NULL;\r
+       int i, currentElement = 0;\r
+\r
+       // first determine what element of the chain we come from (if any)\r
+       if(appData.icsActive) {\r
+           hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
+           hText  = GetDlgItem(hwndConsole, OPT_ConsoleText);\r
+       }\r
+       if(engineOutputDialog && EngineOutputIsUp()) {\r
+           e1 = GetDlgItem(engineOutputDialog, IDC_EngineMemo1);\r
+           e2 = GetDlgItem(engineOutputDialog, IDC_EngineMemo2);\r
+       }\r
+       if(moveHistoryDialog && MoveHistoryIsUp()) {\r
+           mh = GetDlgItem(moveHistoryDialog, IDC_MoveHistory);\r
+       }\r
+       if(msg.hwnd == hwndMain) currentElement = 7 ; else\r
+       if(msg.hwnd == engineOutputDialog) currentElement = 2; else\r
+       if(msg.hwnd == e1)                 currentElement = 2; else\r
+       if(msg.hwnd == e2)                 currentElement = 3; else\r
+       if(msg.hwnd == moveHistoryDialog) currentElement = 4; else\r
+       if(msg.hwnd == mh)                currentElement = 4; else\r
+       if(msg.hwnd == evalGraphDialog)    currentElement = 6; else\r
+       if(msg.hwnd == hText)  currentElement = 5; else\r
+       if(msg.hwnd == hInput) currentElement = 6; else\r
+       for (i = 0; i < N_BUTTONS; i++) {\r
+           if (buttonDesc[i].hwnd == msg.hwnd) { currentElement = 1; break; }\r
+       }\r
+\r
+       // determine where to go to\r
+       if(currentElement) { HWND h = NULL; int direction = GetKeyState(VK_SHIFT) < 0 ? -1 : 1;\r
+         do {\r
+           currentElement = (currentElement + direction) % 7;\r
+           switch(currentElement) {\r
+               case 0:\r
+                 h = hwndMain; break; // passing this case always makes the loop exit\r
+               case 1:\r
+                 h = buttonDesc[0].hwnd; break; // could be NULL\r
+               case 2:\r
+                 if(!EngineOutputIsUp()) continue; // skip closed auxiliary windows\r
+                 h = e1; break;\r
+               case 3:\r
+                 if(!EngineOutputIsUp()) continue;\r
+                 h = e2; break;\r
+               case 4:\r
+                 if(!MoveHistoryIsUp()) continue;\r
+                 h = mh; break;\r
+//             case 6: // input to eval graph does not seem to get here!\r
+//               if(!EvalGraphIsUp()) continue;\r
+//               h = evalGraphDialog; break;\r
+               case 5:\r
+                 if(!appData.icsActive) continue;\r
+                 SAY("display");\r
+                 h = hText; break;\r
+               case 6:\r
+                 if(!appData.icsActive) continue;\r
+                 SAY("input");\r
+                 h = hInput; break;\r
+           }\r
+         } while(h == 0);\r
+\r
+         if(currentElement > 4 && IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
+         if(currentElement < 5 && IsIconic(hwndMain))    ShowWindow(hwndMain, SW_RESTORE); // all open together\r
+         SetFocus(h);\r
+\r
+         continue; // this message now has been processed\r
+       }\r
+      }\r
+\r
       if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&\r
           !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&\r
           !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&\r
@@ -504,9 +600,15 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
          !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&\r
          !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&\r
          !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&\r
-         !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) &&\r
+         !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) && JAWS_ACCEL\r
           !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&\r
          !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {\r
+       int done = 0, i; // [HGM] chat: dispatch cat-box messages\r
+       for(i=0; i<MAX_CHAT; i++) \r
+           if(chatHandle[i] && IsDialogMessage(chatHandle[i], &msg)) {\r
+               done = 1; break;\r
+       }\r
+       if(done) continue; // [HGM] chat: end patch\r
        TranslateMessage(&msg); /* Translates virtual key codes */\r
        DispatchMessage(&msg);  /* Dispatches message to window */\r
       }\r
@@ -522,6 +624,21 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  *\r
 \*---------------------------------------------------------------------------*/\r
 \r
+void\r
+SetUserLogo()\r
+{   // update user logo if necessary\r
+    static char oldUserName[MSG_SIZ], *curName;\r
+\r
+    if(appData.autoLogo) {\r
+         curName = UserName();\r
+         if(strcmp(curName, oldUserName)) {\r
+               sprintf(oldUserName, "logos\\%s.bmp", curName);\r
+               userLogo = LoadImage( 0, oldUserName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );    \r
+               strcpy(oldUserName, curName);\r
+         }\r
+    }\r
+}\r
+\r
 BOOL\r
 InitApplication(HINSTANCE hInstance)\r
 {\r
@@ -564,14 +681,14 @@ InitApplication(HINSTANCE hInstance)
 int screenHeight, screenWidth;\r
 \r
 void\r
-EnsureOnScreen(int *x, int *y)\r
+EnsureOnScreen(int *x, int *y, int minX, int minY)\r
 {\r
-  int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);\r
+//  int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);\r
   /* Be sure window at (x,y) is not off screen (or even mostly off screen) */\r
   if (*x > screenWidth - 32) *x = 0;\r
   if (*y > screenHeight - 32) *y = 0;\r
-  if (*x < 10) *x = 10;\r
-  if (*y < gap) *y = gap;\r
+  if (*x < minX) *x = minX;\r
+  if (*y < minY) *y = minY;\r
 }\r
 \r
 BOOL\r
@@ -583,6 +700,7 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
   char *filepart;\r
 \r
   hInst = hInstance;   /* Store instance handle in our global variable */\r
+  programName = szAppName;\r
 \r
   if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {\r
     *filepart = NULLCHAR;\r
@@ -590,7 +708,19 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
     GetCurrentDirectory(MSG_SIZ, installDir);\r
   }\r
   gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise\r
+  screenWidth = screenHeight = 1000; // [HGM] placement: kludge to allow calling EnsureOnScreen from InitAppData\r
   InitAppData(lpCmdLine);      /* Get run-time parameters */\r
+  /* xboard, and older WinBoards, controlled the move sound with the\r
+     appData.ringBellAfterMoves option.  In the current WinBoard, we\r
+     always turn the option on (so that the backend will call us),\r
+     then let the user turn the sound off by setting it to silence if\r
+     desired.  To accommodate old winboard.ini files saved by old\r
+     versions of WinBoard, we also turn off the sound if the option\r
+     was initially set to false. [HGM] taken out of InitAppData */\r
+  if (!appData.ringBellAfterMoves) {\r
+    sounds[(int)SoundMove].name = strdup("");\r
+    appData.ringBellAfterMoves = TRUE;\r
+  }\r
   if (appData.debugMode) {\r
     debugFP = fopen(appData.nameOfDebugFile, "w");\r
     setbuf(debugFP, NULL);\r
@@ -598,8 +728,8 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
 \r
   InitBackEnd1();\r
 \r
-  InitEngineUCI( installDir, &first );\r
-  InitEngineUCI( installDir, &second );\r
+//  InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()\r
+//  InitEngineUCI( installDir, &second );\r
 \r
   /* Create a main window for this application instance. */\r
   hwnd = CreateWindow(szAppName, szTitle,\r
@@ -613,6 +743,41 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
     return (FALSE);\r
   }\r
 \r
+  /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */\r
+  if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {\r
+      first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
+\r
+      if (first.programLogo == NULL && appData.debugMode) {\r
+          fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );\r
+      }\r
+  } else if(appData.autoLogo) {\r
+      if(appData.firstDirectory && appData.firstDirectory[0]) {\r
+       char buf[MSG_SIZ];\r
+       sprintf(buf, "%s/logo.bmp", appData.firstDirectory);\r
+       first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );   \r
+      }\r
+  }\r
+\r
+  if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {\r
+      second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
+\r
+      if (second.programLogo == NULL && appData.debugMode) {\r
+          fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );\r
+      }\r
+  } else if(appData.autoLogo) {\r
+      char buf[MSG_SIZ];\r
+      if(appData.icsActive) { // [HGM] logo: in ICS mode second can be used for ICS\r
+       sprintf(buf, "logos\\%s.bmp", appData.icsHost);\r
+       second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
+      } else\r
+      if(appData.secondDirectory && appData.secondDirectory[0]) {\r
+       sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);\r
+       second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );  \r
+      }\r
+  }\r
+\r
+  SetUserLogo();\r
+\r
   iconWhite = LoadIcon(hInstance, "icon_white");\r
   iconBlack = LoadIcon(hInstance, "icon_black");\r
   iconCurrent = iconWhite;\r
@@ -622,14 +787,15 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
   for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {\r
     /* Compute window size for each board size, and use the largest\r
        size that fits on this screen as the default. */\r
-    InitDrawingSizes((BoardSize)ibs, 0);\r
+    InitDrawingSizes((BoardSize)(ibs+1000), 0);\r
     if (boardSize == (BoardSize)-1 &&\r
-        winHeight <= screenHeight\r
+        winH <= screenHeight\r
            - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10\r
-        && winWidth <= screenWidth) {\r
+        && winW <= screenWidth) {\r
       boardSize = (BoardSize)ibs;\r
     }\r
   }\r
+\r
   InitDrawingSizes(boardSize, 0);\r
   InitMenuChecks();\r
   buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);\r
@@ -657,11 +823,6 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
 \r
   mysrandom( (unsigned) time(NULL) );\r
 \r
-  /* Make a console window if needed */\r
-  if (appData.icsActive) {\r
-    ConsoleCreate();\r
-  }\r
-\r
   /* [AS] Restore layout */\r
   if( wpMoveHistory.visible ) {\r
       MoveHistoryPopUp();\r
@@ -678,26 +839,20 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
   InitBackEnd2();\r
 \r
   /* Make the window visible; update its client area; and return "success" */\r
-  EnsureOnScreen(&boardX, &boardY);\r
+  EnsureOnScreen(&wpMain.x, &wpMain.y, minX, minY);\r
   wp.length = sizeof(WINDOWPLACEMENT);\r
   wp.flags = 0;\r
   wp.showCmd = nCmdShow;\r
   wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;\r
-  wp.rcNormalPosition.left = boardX;\r
-  wp.rcNormalPosition.right = boardX + winWidth;\r
-  wp.rcNormalPosition.top = boardY;\r
-  wp.rcNormalPosition.bottom = boardY + winHeight;\r
+  wp.rcNormalPosition.left = wpMain.x;\r
+  wp.rcNormalPosition.right = wpMain.x + wpMain.width;\r
+  wp.rcNormalPosition.top = wpMain.y;\r
+  wp.rcNormalPosition.bottom = wpMain.y + wpMain.height;\r
   SetWindowPlacement(hwndMain, &wp);\r
 \r
-  SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
+  if(!appData.noGUI) SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
                0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);\r
 \r
-#if 0\r
-  /* [AS] Disable the FRC stuff if not playing the proper variant */\r
-  if( gameInfo.variant != VariantFischeRandom ) {\r
-      EnableMenuItem( GetMenu(hwndMain), IDM_NewGameFRC, MF_GRAYED );\r
-  }\r
-#endif\r
   if (hwndConsole) {\r
 #if AOT_CONSOLE\r
     SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
@@ -705,557 +860,88 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
 #endif\r
     ShowWindow(hwndConsole, nCmdShow);\r
   }\r
-  UpdateWindow(hwnd);\r
+  if(!appData.noGUI)   UpdateWindow(hwnd);  else ShowWindow(hwnd, SW_MINIMIZE);\r
+  if(gameListDialog) SetFocus(gameListDialog); // [HGM] jaws: for if we clicked multi-game game file\r
 \r
   return TRUE;\r
 \r
 }\r
 \r
+VOID\r
+InitMenuChecks()\r
+{\r
+  HMENU hmenu = GetMenu(hwndMain);\r
 \r
-typedef enum {\r
-  ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone, \r
-  ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,\r
-  ArgSettingsFilename\r
-} ArgType;\r
+  (void) EnableMenuItem(hmenu, IDM_CommPort,\r
+                       MF_BYCOMMAND|((appData.icsActive &&\r
+                                      *appData.icsCommPort != NULLCHAR) ?\r
+                                     MF_ENABLED : MF_GRAYED));\r
+  (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,\r
+                      MF_BYCOMMAND|(saveSettingsOnExit ?\r
+                                    MF_CHECKED : MF_UNCHECKED));\r
+}\r
 \r
-typedef struct {\r
-  char *argName;\r
-  ArgType argType;\r
-  /***\r
-  union {\r
-    String *pString;       // ArgString\r
-    int *pInt;             // ArgInt\r
-    float *pFloat;         // ArgFloat\r
-    Boolean *pBoolean;     // ArgBoolean\r
-    COLORREF *pColor;      // ArgColor\r
-    ColorClass cc;         // ArgAttribs\r
-    String *pFilename;     // ArgFilename\r
-    BoardSize *pBoardSize; // ArgBoardSize\r
-    int whichFont;         // ArgFont\r
-    DCB *pDCB;             // ArgCommSettings\r
-    String *pFilename;     // ArgSettingsFilename\r
-  } argLoc;\r
-  ***/\r
-  LPVOID argLoc;\r
-  BOOL save;\r
-} ArgDescriptor;\r
-\r
-int junk;\r
-ArgDescriptor argDescriptors[] = {\r
-  /* positional arguments */\r
-  { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },\r
-  { "", ArgNone, NULL },\r
-  /* keyword arguments */\r
-  { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },\r
-  { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },\r
-  { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },\r
-  { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },\r
-  { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },\r
-  { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },\r
-  { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },\r
-  { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },\r
-  { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },\r
-  { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },\r
-  { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },\r
-  { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },\r
-  { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },\r
-  { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },\r
-  { "initString", ArgString, (LPVOID) &appData.initString, FALSE },\r
-  { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },\r
-  { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },\r
-  { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,\r
-    FALSE },\r
-  { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,\r
-    FALSE },\r
-  { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,\r
-    FALSE },\r
-  { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },\r
-  { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,\r
-    FALSE },\r
-  { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },\r
-  { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },\r
-  { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },\r
-  { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },\r
-  { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },\r
-  { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },\r
-  { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },\r
-  { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },\r
-  { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },\r
-  { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },\r
-  { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },\r
-  { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },\r
-  { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },\r
-  { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },\r
-  { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },\r
-  { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },\r
-  { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },\r
-  /*!!bitmapDirectory?*/\r
-  { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },\r
-  { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },\r
-  { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },\r
-  { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },\r
-  { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },\r
-  { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },\r
-  { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },\r
-  { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },\r
-  { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },\r
-  { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },\r
-  { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },\r
-  { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },\r
-  { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },\r
-  { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },\r
-  { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },\r
-  { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },\r
-  { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },\r
-  { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },\r
-  { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },\r
-  { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },\r
-  { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },\r
-  { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },\r
-  { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },\r
-  { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },\r
-  { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },\r
-  { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },\r
-  { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },\r
-  { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },\r
-  { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },\r
-  { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },\r
-  { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },\r
-  { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },\r
-  { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },\r
-  { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },\r
-  { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },\r
-  { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },\r
-  { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },\r
-  { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },\r
-  { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },\r
-  { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },\r
-  { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },\r
-  { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },\r
-  { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },\r
-  { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },\r
-  { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },\r
-  { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },\r
-  { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },\r
-  { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },\r
-  { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },\r
-  { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },\r
-  { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },\r
-  { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },\r
-  { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },\r
-  { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },\r
-  { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },\r
-  { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },\r
-  { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },\r
-  { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },\r
-  { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },\r
-  { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },\r
-  { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },\r
-  { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },\r
-  { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },\r
-  { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },\r
-  { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },\r
-  { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },\r
-  { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },\r
-  { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },\r
-  { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },\r
-  { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },\r
-  { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },\r
-  { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },\r
-  { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },\r
-  { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },\r
-  { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },\r
-  { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },\r
-  { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },\r
-  { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },\r
-  { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },\r
-  { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },\r
-  { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },\r
-  { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },\r
-  { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },\r
-  { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },\r
-  { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },\r
-  { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },\r
-  { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },\r
-  { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },\r
-  { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },\r
-  { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },\r
-  { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },\r
-  { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },\r
-  { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },\r
-  { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, \r
-    FALSE }, /* only so that old WinBoard.ini files from betas can be read */\r
-  { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },\r
-  { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },\r
-  { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },\r
-  { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },\r
-  { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },\r
-  { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },\r
-  { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE }, /* [AS] */\r
-  { "boardSize", ArgBoardSize, (LPVOID) &boardSize,\r
-    TRUE }, /* must come after all fonts */\r
-  { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },\r
-  { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,\r
-    FALSE }, /* historical; kept only so old winboard.ini files will parse */\r
-  { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },\r
-  { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },\r
-  { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },\r
-  { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },\r
-  { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },\r
-  { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },\r
-  { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },\r
-  { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },\r
-  { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },\r
-  { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },\r
-  { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },\r
-  { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },\r
-  { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },\r
-  { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },\r
-  { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },\r
-  { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },\r
-  { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },\r
-  { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },\r
-  { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },\r
-  { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },\r
-  { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },\r
-  { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },\r
-  { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },\r
-  { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },\r
-  { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },\r
-  { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },\r
-  { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },\r
-  { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },\r
-#if 0\r
-  { "cmailGameName", ArgString, (LPVOID) &appData.cmailGameName, FALSE },\r
-  { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE },\r
-#endif\r
-  { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },\r
-  { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },\r
-  { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },\r
-  { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },\r
-  { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },\r
-  { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },\r
-  { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },\r
-  { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },\r
-  { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },\r
-  { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },\r
-  { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },\r
-  { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },\r
-  { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },\r
-  { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },\r
-  { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },\r
-  { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },\r
-  { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },\r
-  { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },\r
-  { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },\r
-  { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },\r
-  { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },\r
-  { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },\r
-  { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },\r
-  { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },\r
-  { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },\r
-  { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },\r
-  { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },\r
-  { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },\r
-  { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },\r
-  { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },\r
-  { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },\r
-  { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },\r
-  { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },\r
-  { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },\r
-  { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},\r
-  { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},\r
-  { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},\r
-  { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},\r
-  { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},\r
-  { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},\r
-  { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},\r
-  { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },\r
-  { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },\r
-  { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },\r
-  { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },\r
-  { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },\r
-  { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },\r
-  { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },\r
-  { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },\r
-  { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },\r
-  { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },\r
-  { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },\r
-  { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },\r
-  { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },\r
-  { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },\r
-  { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },\r
-  { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },\r
-  { "highlightLastMove", ArgBoolean,\r
-    (LPVOID) &appData.highlightLastMove, TRUE },\r
-  { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },\r
-  { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },\r
-  { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },\r
-  { "highlightDragging", ArgBoolean,\r
-    (LPVOID) &appData.highlightDragging, TRUE },\r
-  { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },\r
-  { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },\r
-  { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },\r
-  { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },\r
-  { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },\r
-  { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },\r
-  { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },\r
-  { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },\r
-  { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },\r
-  { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },\r
-  { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },\r
-  { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },\r
-  { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },\r
-  { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },\r
-  { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },\r
-  { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },\r
-  { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },\r
-  { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },\r
-  { "soundShout", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },\r
-  { "soundSShout", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },\r
-  { "soundChannel1", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },\r
-  { "soundChannel", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },\r
-  { "soundKibitz", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },\r
-  { "soundTell", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },\r
-  { "soundChallenge", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },\r
-  { "soundRequest", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },\r
-  { "soundSeek", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },\r
-  { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },\r
-  { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },\r
-  { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },\r
-  { "soundIcsLoss", ArgFilename, \r
-    (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },\r
-  { "soundIcsDraw", ArgFilename, \r
-    (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },\r
-  { "soundIcsUnfinished", ArgFilename, \r
-    (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},\r
-  { "soundIcsAlarm", ArgFilename, \r
-    (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },\r
-  { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },\r
-  { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },\r
-  { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },\r
-  { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },\r
-  { "reuseChessPrograms", ArgBoolean,\r
-    (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */\r
-  { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },\r
-  { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },\r
-  { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },\r
-  { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },\r
-  { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },\r
-  { "x", ArgInt, (LPVOID) &boardX, TRUE },\r
-  { "y", ArgInt, (LPVOID) &boardY, TRUE },\r
-  { "icsX", ArgInt, (LPVOID) &consoleX, TRUE },\r
-  { "icsY", ArgInt, (LPVOID) &consoleY, TRUE },\r
-  { "icsW", ArgInt, (LPVOID) &consoleW, TRUE },\r
-  { "icsH", ArgInt, (LPVOID) &consoleH, TRUE },\r
-  { "analysisX", ArgInt, (LPVOID) &analysisX, TRUE },\r
-  { "analysisY", ArgInt, (LPVOID) &analysisY, TRUE },\r
-  { "analysisW", ArgInt, (LPVOID) &analysisW, TRUE },\r
-  { "analysisH", ArgInt, (LPVOID) &analysisH, TRUE },\r
-  { "commentX", ArgInt, (LPVOID) &commentX, TRUE },\r
-  { "commentY", ArgInt, (LPVOID) &commentY, TRUE },\r
-  { "commentW", ArgInt, (LPVOID) &commentW, TRUE },\r
-  { "commentH", ArgInt, (LPVOID) &commentH, TRUE },\r
-  { "tagsX", ArgInt, (LPVOID) &editTagsX, TRUE },\r
-  { "tagsY", ArgInt, (LPVOID) &editTagsY, TRUE },\r
-  { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },\r
-  { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },\r
-  { "gameListX", ArgInt, (LPVOID) &gameListX, TRUE },\r
-  { "gameListY", ArgInt, (LPVOID) &gameListY, TRUE },\r
-  { "gameListW", ArgInt, (LPVOID) &gameListW, TRUE },\r
-  { "gameListH", ArgInt, (LPVOID) &gameListH, TRUE },\r
-  { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },\r
-  { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },\r
-  { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },\r
-  { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },\r
-  { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },\r
-  { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },\r
-  { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },\r
-  { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },\r
-  { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },\r
-  { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,\r
-    TRUE },\r
-  { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,\r
-    TRUE },\r
-  { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },\r
-  { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },\r
-  { "variant", ArgString, (LPVOID) &appData.variant, FALSE },\r
-  { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion, FALSE },\r
-  { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,FALSE },\r
-  { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },\r
-  { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },\r
-  { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },\r
-  { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },\r
-  /* [AS] New features */\r
-  { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE },\r
-  { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE },\r
-  { "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE },\r
-  { "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE },\r
-  { "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE },\r
-  { "darkBackTextureFile", ArgString, (LPVOID) &appData.darkBackTextureFile, TRUE },\r
-  { "liteBackTextureMode", ArgInt, (LPVOID) &appData.liteBackTextureMode, TRUE },\r
-  { "darkBackTextureMode", ArgInt, (LPVOID) &appData.darkBackTextureMode, TRUE },\r
-  { "renderPiecesWithFont", ArgString, (LPVOID) &appData.renderPiecesWithFont, TRUE },\r
-  { "fontPieceToCharTable", ArgString, (LPVOID) &appData.fontToPieceTable, TRUE },\r
-  { "fontPieceBackColorWhite", ArgColor, (LPVOID) &appData.fontBackColorWhite, TRUE },\r
-  { "fontPieceForeColorWhite", ArgColor, (LPVOID) &appData.fontForeColorWhite, TRUE },\r
-  { "fontPieceBackColorBlack", ArgColor, (LPVOID) &appData.fontBackColorBlack, TRUE },\r
-  { "fontPieceForeColorBlack", ArgColor, (LPVOID) &appData.fontForeColorBlack, TRUE },\r
-  { "fontPieceSize", ArgInt, (LPVOID) &appData.fontPieceSize, TRUE },\r
-  { "overrideLineGap", ArgInt, (LPVOID) &appData.overrideLineGap, TRUE },\r
-  { "adjudicateLossThreshold", ArgInt, (LPVOID) &appData.adjudicateLossThreshold, TRUE },\r
-  { "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE },\r
-  { "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE },\r
-  { "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },\r
-  { "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },\r
-  { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },\r
-  { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE },\r
-  { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE },\r
-  { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE },\r
-  { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE },\r
-  { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE },\r
-  { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE },\r
-  { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE },\r
-  { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE },\r
-  { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE },\r
-  { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE },\r
-  { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE },\r
-  { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE },\r
-  { "firstIsUCI", ArgBoolean, (LPVOID) &appData.firstIsUCI, FALSE },\r
-  { "fUCI", ArgTrue, (LPVOID) &appData.firstIsUCI, FALSE },\r
-  { "secondIsUCI", ArgBoolean, (LPVOID) &appData.secondIsUCI, FALSE },\r
-  { "sUCI", ArgTrue, (LPVOID) &appData.secondIsUCI, FALSE },\r
-  { "firstHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },\r
-  { "fNoOwnBookUCI", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },\r
-  { "secondHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },\r
-  { "sNoOwnBookUCI", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },\r
-  { "polyglotDir", ArgFilename, (LPVOID) &appData.polyglotDir, TRUE },\r
-  { "usePolyglotBook", ArgBoolean, (LPVOID) &appData.usePolyglotBook, TRUE },\r
-  { "polyglotBook", ArgFilename, (LPVOID) &appData.polyglotBook, TRUE },\r
-  { "defaultHashSize", ArgInt, (LPVOID) &appData.defaultHashSize, TRUE }, \r
-  { "defaultCacheSizeEGTB", ArgInt, (LPVOID) &appData.defaultCacheSizeEGTB, TRUE },\r
-  { "defaultPathEGTB", ArgFilename, (LPVOID) &appData.defaultPathEGTB, TRUE },\r
-\r
-  /* [AS] Layout stuff */\r
-  { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },\r
-  { "moveHistoryX", ArgInt, (LPVOID) &wpMoveHistory.x, TRUE },\r
-  { "moveHistoryY", ArgInt, (LPVOID) &wpMoveHistory.y, TRUE },\r
-  { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },\r
-  { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },\r
-\r
-  { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },\r
-  { "evalGraphX", ArgInt, (LPVOID) &wpEvalGraph.x, TRUE },\r
-  { "evalGraphY", ArgInt, (LPVOID) &wpEvalGraph.y, TRUE },\r
-  { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },\r
-  { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },\r
-\r
-  { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },\r
-  { "engineOutputX", ArgInt, (LPVOID) &wpEngineOutput.x, TRUE },\r
-  { "engineOutputY", ArgInt, (LPVOID) &wpEngineOutput.y, TRUE },\r
-  { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },\r
-  { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },\r
-\r
-  /* [HGM] board-size, adjudication and misc. options */\r
-  { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE },\r
-  { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE },\r
-  { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE },\r
-  { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE },\r
-  { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE },\r
-  { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE },\r
-  { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE },\r
-  { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE },\r
-  { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE },\r
-  { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE },\r
-  { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE },\r
-  { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE },\r
-  { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE },\r
-  { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE },\r
-  { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE },\r
-  { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE },\r
-  { "userName", ArgString, (LPVOID) &appData.userName, FALSE },\r
+//---------------------------------------------------------------------------------------------------------\r
 \r
-#ifdef ZIPPY\r
-  { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },\r
-  { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },\r
-  { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },\r
-  { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },\r
-  { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },\r
-  { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },\r
-  { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },\r
-  { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },\r
-  { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },\r
-  { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },\r
-  { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },\r
-  { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE },\r
-  { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,\r
-    FALSE },\r
-  { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE },\r
-  { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE },\r
-  { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE },\r
-  { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },\r
-  { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },\r
-  { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE },\r
-  { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,\r
-    FALSE },\r
-  { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE },\r
-  { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },\r
-  { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },\r
-  { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE },\r
-  { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE },\r
-  { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE },\r
-  { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE },\r
-  { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },\r
-  { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },\r
-  { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE },\r
-  { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE },\r
-  { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },\r
-  { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },\r
-  { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },\r
-  { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },\r
-  { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },\r
-  /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */\r
-  { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },\r
-#endif\r
-  /* [HGM] options for broadcasting and time odds */\r
-  { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },\r
-  { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },\r
-  { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },\r
-  { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },\r
-  { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },\r
-  { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },\r
-  { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },\r
-  { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },\r
-  { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },\r
-  { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },\r
-  { NULL, ArgNone, NULL, FALSE }\r
-};\r
+#define ICS_TEXT_MENU_SIZE (IDM_CommandXLast - IDM_CommandX + 1)\r
+#define XBOARD FALSE\r
 \r
+#define OPTCHAR "/"\r
+#define SEPCHAR "="\r
 \r
-/* Kludge for indirection files on command line */\r
-char* lastIndirectionFilename;\r
-ArgDescriptor argDescriptorIndirection =\r
-{ "", ArgSettingsFilename, (LPVOID) NULL, FALSE };\r
+#include "args.h"\r
 \r
+// front-end part of option handling\r
 \r
 VOID\r
-ExitArgError(char *msg, char *badArg)\r
+LFfromMFP(LOGFONT* lf, MyFontParams *mfp)\r
 {\r
-  char buf[MSG_SIZ];\r
+  HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);\r
+  lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);\r
+  DeleteDC(hdc);\r
+  lf->lfWidth = 0;\r
+  lf->lfEscapement = 0;\r
+  lf->lfOrientation = 0;\r
+  lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;\r
+  lf->lfItalic = mfp->italic;\r
+  lf->lfUnderline = mfp->underline;\r
+  lf->lfStrikeOut = mfp->strikeout;\r
+  lf->lfCharSet = mfp->charset;\r
+  lf->lfOutPrecision = OUT_DEFAULT_PRECIS;\r
+  lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;\r
+  lf->lfQuality = DEFAULT_QUALITY;\r
+  lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;\r
+  strcpy(lf->lfFaceName, mfp->faceName);\r
+}\r
 \r
-  sprintf(buf, "%s %s", msg, badArg);\r
-  DisplayFatalError(buf, 0, 2);\r
-  exit(2);\r
+void\r
+CreateFontInMF(MyFont *mf)\r
+{ \r
+  LFfromMFP(&mf->lf, &mf->mfp);\r
+  if (mf->hf) DeleteObject(mf->hf);\r
+  mf->hf = CreateFontIndirect(&mf->lf);\r
 }\r
 \r
+// [HGM] This platform-dependent table provides the location for storing the color info\r
+void *\r
+colorVariable[] = {\r
+  &whitePieceColor, \r
+  &blackPieceColor, \r
+  &lightSquareColor,\r
+  &darkSquareColor, \r
+  &highlightSquareColor,\r
+  &premoveHighlightColor,\r
+  NULL,\r
+  &consoleBackgroundColor,\r
+  &appData.fontForeColorWhite,\r
+  &appData.fontBackColorWhite,\r
+  &appData.fontForeColorBlack,\r
+  &appData.fontBackColorBlack,\r
+  &appData.evalHistColorWhite,\r
+  &appData.evalHistColorBlack,\r
+  &appData.highlightArrowColor,\r
+};\r
+\r
 /* Command line font name parser.  NULL name means do nothing.\r
    Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"\r
    For backward compatibility, syntax without the colon is also\r
@@ -1290,8 +976,42 @@ ParseFontName(char *name, MyFontParams *mfp)
   mfp->italic = (strchr(p, 'i') != NULL);\r
   mfp->underline = (strchr(p, 'u') != NULL);\r
   mfp->strikeout = (strchr(p, 's') != NULL);\r
+  mfp->charset = DEFAULT_CHARSET;\r
+  q = strchr(p, 'c');\r
+  if (q)\r
+    mfp->charset = (BYTE) atoi(q+1);\r
+}\r
+\r
+void\r
+ParseFont(char *name, int number)\r
+{ // wrapper to shield back-end from 'font'\r
+  ParseFontName(name, &font[boardSize][number]->mfp);\r
 }\r
 \r
+void\r
+SetFontDefaults()\r
+{ // in WB  we have a 2D array of fonts; this initializes their description\r
+  int i, j;\r
+  /* Point font array elements to structures and\r
+     parse default font names */\r
+  for (i=0; i<NUM_FONTS; i++) {\r
+    for (j=0; j<NUM_SIZES; j++) {\r
+      font[j][i] = &fontRec[j][i];\r
+      ParseFontName(font[j][i]->def, &font[j][i]->mfp);\r
+    }\r
+  }\r
+}\r
+\r
+void\r
+CreateFonts()\r
+{ // here we create the actual fonts from the selected descriptions\r
+  int i, j;\r
+  for (i=0; i<NUM_FONTS; i++) {\r
+    for (j=0; j<NUM_SIZES; j++) {\r
+      CreateFontInMF(font[j][i]);\r
+    }\r
+  }\r
+}\r
 /* Color name parser.\r
    X version accepts X color names, but this one\r
    handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */\r
@@ -1314,8 +1034,14 @@ ParseColorName(char *name)
   return PALETTERGB(red, green, blue);\r
 }\r
 \r
+void\r
+ParseColor(int n, char *name)\r
+{ // for WinBoard the color is an int, which needs to be derived from the string\r
+  if(colorVariable[n]) *(int*)colorVariable[n] = ParseColorName(name);\r
+}\r
 \r
-void ParseAttribs(COLORREF *color, int *effects, char* argValue)\r
+void\r
+ParseAttribs(COLORREF *color, int *effects, char* argValue)\r
 {\r
   char *e = argValue;\r
   int eff = 0;\r
@@ -1332,471 +1058,52 @@ void ParseAttribs(COLORREF *color, int *effects, char* argValue)
   *color   = ParseColorName(e);\r
 }\r
 \r
+void\r
+ParseTextAttribs(ColorClass cc, char *s)\r
+{   // [HGM] front-end wrapper that does the platform-dependent call\r
+    // for XBoard we would set (&appData.colorShout)[cc] = strdup(s);\r
+    ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, s);\r
+}\r
 \r
-BoardSize\r
-ParseBoardSize(char *name)\r
-{\r
+void\r
+ParseBoardSize(void *addr, char *name)\r
+{ // [HGM] rewritten with return-value ptr to shield back-end from BoardSize\r
   BoardSize bs = SizeTiny;\r
   while (sizeInfo[bs].name != NULL) {\r
-    if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;\r
+    if (StrCaseCmp(name, sizeInfo[bs].name) == 0) {\r
+       *(BoardSize *)addr = bs;\r
+       return;\r
+    }\r
     bs++;\r
   }\r
   ExitArgError("Unrecognized board size value", name);\r
-  return bs; /* not reached */\r
-}\r
-\r
-\r
-char\r
-StringGet(void *getClosure)\r
-{\r
-  char **p = (char **) getClosure;\r
-  return *((*p)++);\r
-}\r
-\r
-char\r
-FileGet(void *getClosure)\r
-{\r
-  int c;\r
-  FILE* f = (FILE*) getClosure;\r
-\r
-  c = getc(f);\r
-  if (c == EOF)\r
-    return NULLCHAR;\r
-  else\r
-    return (char) c;\r
-}\r
-\r
-/* Parse settings file named "name". If file found, return the\r
-   full name in fullname and return TRUE; else return FALSE */\r
-BOOLEAN\r
-ParseSettingsFile(char *name, char fullname[MSG_SIZ])\r
-{\r
-  char *dummy;\r
-  FILE *f;\r
-\r
-  if (SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy)) {\r
-    f = fopen(fullname, "r");\r
-    if (f != NULL) {\r
-      ParseArgs(FileGet, f);\r
-      fclose(f);\r
-      return TRUE;\r
-    }\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-VOID\r
-ParseArgs(GetFunc get, void *cl)\r
-{\r
-  char argName[ARG_MAX];\r
-  char argValue[ARG_MAX];\r
-  ArgDescriptor *ad;\r
-  char start;\r
-  char *q;\r
-  int i, octval;\r
-  char ch;\r
-  int posarg = 0;\r
-\r
-  ch = get(cl);\r
-  for (;;) {\r
-    while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);\r
-    if (ch == NULLCHAR) break;\r
-    if (ch == ';') {\r
-      /* Comment to end of line */\r
-      ch = get(cl);\r
-      while (ch != '\n' && ch != NULLCHAR) ch = get(cl);\r
-      continue;\r
-    } else if (ch == '/' || ch == '-') {\r
-      /* Switch */\r
-      q = argName;\r
-      while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&\r
-            ch != '\n' && ch != '\t') {\r
-       *q++ = ch;\r
-       ch = get(cl);\r
-      }\r
-      *q = NULLCHAR;\r
-\r
-      for (ad = argDescriptors; ad->argName != NULL; ad++)\r
-       if (strcmp(ad->argName, argName + 1) == 0) break;\r
-\r
-      if (ad->argName == NULL)\r
-       ExitArgError("Unrecognized argument", argName);\r
-\r
-    } else if (ch == '@') {\r
-      /* Indirection file */\r
-      ad = &argDescriptorIndirection;\r
-      ch = get(cl);\r
-    } else {\r
-      /* Positional argument */\r
-      ad = &argDescriptors[posarg++];\r
-      strcpy(argName, ad->argName);\r
-    }\r
-\r
-    if (ad->argType == ArgTrue) {\r
-      *(Boolean *) ad->argLoc = TRUE;\r
-      continue;\r
-    }\r
-    if (ad->argType == ArgFalse) {\r
-      *(Boolean *) ad->argLoc = FALSE;\r
-      continue;\r
-    }\r
-\r
-    while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);\r
-    if (ch == NULLCHAR || ch == '\n') {\r
-      ExitArgError("No value provided for argument", argName);\r
-    }\r
-    q = argValue;\r
-    if (ch == '{') {\r
-      // Quoting with { }.  No characters have to (or can) be escaped.\r
-      // Thus the string cannot contain a '}' character.\r
-      start = ch;\r
-      ch = get(cl);\r
-      while (start) {\r
-       switch (ch) {\r
-       case NULLCHAR:\r
-         start = NULLCHAR;\r
-         break;\r
-         \r
-       case '}':\r
-         ch = get(cl);\r
-         start = NULLCHAR;\r
-         break;\r
-\r
-       default:\r
-         *q++ = ch;\r
-         ch = get(cl);\r
-         break;\r
-       }\r
-      }          \r
-    } else if (ch == '\'' || ch == '"') {\r
-      // Quoting with ' ' or " ", with \ as escape character.\r
-      // Inconvenient for long strings that may contain Windows filenames.\r
-      start = ch;\r
-      ch = get(cl);\r
-      while (start) {\r
-       switch (ch) {\r
-       case NULLCHAR:\r
-         start = NULLCHAR;\r
-         break;\r
-\r
-       default:\r
-        not_special:\r
-         *q++ = ch;\r
-         ch = get(cl);\r
-         break;\r
-\r
-       case '\'':\r
-       case '\"':\r
-         if (ch == start) {\r
-           ch = get(cl);\r
-           start = NULLCHAR;\r
-           break;\r
-         } else {\r
-           goto not_special;\r
-         }\r
-\r
-       case '\\':\r
-          if (ad->argType == ArgFilename\r
-             || ad->argType == ArgSettingsFilename) {\r
-             goto not_special;\r
-         }\r
-         ch = get(cl);\r
-         switch (ch) {\r
-         case NULLCHAR:\r
-           ExitArgError("Incomplete \\ escape in value for", argName);\r
-           break;\r
-         case 'n':\r
-           *q++ = '\n';\r
-           ch = get(cl);\r
-           break;\r
-         case 'r':\r
-           *q++ = '\r';\r
-           ch = get(cl);\r
-           break;\r
-         case 't':\r
-           *q++ = '\t';\r
-           ch = get(cl);\r
-           break;\r
-         case 'b':\r
-           *q++ = '\b';\r
-           ch = get(cl);\r
-           break;\r
-         case 'f':\r
-           *q++ = '\f';\r
-           ch = get(cl);\r
-           break;\r
-         default:\r
-           octval = 0;\r
-           for (i = 0; i < 3; i++) {\r
-             if (ch >= '0' && ch <= '7') {\r
-               octval = octval*8 + (ch - '0');\r
-               ch = get(cl);\r
-             } else {\r
-               break;\r
-             }\r
-           }\r
-           if (i > 0) {\r
-             *q++ = (char) octval;\r
-           } else {\r
-             *q++ = ch;\r
-             ch = get(cl);\r
-           }\r
-           break;\r
-         }\r
-         break;\r
-       }\r
-      }\r
-    } else {\r
-      while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {\r
-       *q++ = ch;\r
-       ch = get(cl);\r
-      }\r
-    }\r
-    *q = NULLCHAR;\r
-\r
-    switch (ad->argType) {\r
-    case ArgInt:\r
-      *(int *) ad->argLoc = atoi(argValue);\r
-      break;\r
-\r
-    case ArgFloat:\r
-      *(float *) ad->argLoc = (float) atof(argValue);\r
-      break;\r
-\r
-    case ArgString:\r
-    case ArgFilename:\r
-      *(char **) ad->argLoc = strdup(argValue);\r
-      break;\r
-\r
-    case ArgSettingsFilename:\r
-      {\r
-       char fullname[MSG_SIZ];\r
-       if (ParseSettingsFile(argValue, fullname)) {\r
-         if (ad->argLoc != NULL) {\r
-           *(char **) ad->argLoc = strdup(fullname);\r
-         }\r
-       } else {\r
-         if (ad->argLoc != NULL) {\r
-         } else {\r
-           ExitArgError("Failed to open indirection file", argValue);\r
-         }\r
-       }\r
-      }\r
-      break;\r
-\r
-    case ArgBoolean:\r
-      switch (argValue[0]) {\r
-      case 't':\r
-      case 'T':\r
-       *(Boolean *) ad->argLoc = TRUE;\r
-       break;\r
-      case 'f':\r
-      case 'F':\r
-       *(Boolean *) ad->argLoc = FALSE;\r
-       break;\r
-      default:\r
-       ExitArgError("Unrecognized boolean argument value", argValue);\r
-       break;\r
-      }\r
-      break;\r
-\r
-    case ArgColor:\r
-      *(COLORREF *)ad->argLoc = ParseColorName(argValue);\r
-      break;\r
-\r
-    case ArgAttribs: {\r
-      ColorClass cc = (ColorClass)ad->argLoc;\r
-      ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);\r
-      }\r
-      break;\r
-      \r
-    case ArgBoardSize:\r
-      *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);\r
-      break;\r
-\r
-    case ArgFont:\r
-      ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);\r
-      break;\r
-\r
-    case ArgCommSettings:\r
-      ParseCommSettings(argValue, &dcb);\r
-      break;\r
-\r
-    case ArgNone:\r
-      ExitArgError("Unrecognized argument", argValue);\r
-      break;\r
-    }\r
-  }\r
 }\r
 \r
-VOID\r
-LFfromMFP(LOGFONT* lf, MyFontParams *mfp)\r
-{\r
-  HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);\r
-  lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);\r
-  DeleteDC(hdc);\r
-  lf->lfWidth = 0;\r
-  lf->lfEscapement = 0;\r
-  lf->lfOrientation = 0;\r
-  lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;\r
-  lf->lfItalic = mfp->italic;\r
-  lf->lfUnderline = mfp->underline;\r
-  lf->lfStrikeOut = mfp->strikeout;\r
-  lf->lfCharSet = DEFAULT_CHARSET;\r
-  lf->lfOutPrecision = OUT_DEFAULT_PRECIS;\r
-  lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;\r
-  lf->lfQuality = DEFAULT_QUALITY;\r
-  lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;\r
-  strcpy(lf->lfFaceName, mfp->faceName);\r
-}\r
-\r
-VOID\r
-CreateFontInMF(MyFont *mf)\r
-{\r
-  LFfromMFP(&mf->lf, &mf->mfp);\r
-  if (mf->hf) DeleteObject(mf->hf);\r
-  mf->hf = CreateFontIndirect(&mf->lf);\r
-}\r
-\r
-VOID\r
-SetDefaultTextAttribs()\r
-{\r
-  ColorClass cc;\r
-  for (cc = (ColorClass)0; cc < NColorClasses; cc++) {\r
-    ParseAttribs(&textAttribs[cc].color, \r
-                &textAttribs[cc].effects, \r
-                defaultTextAttribs[cc]);\r
-  }\r
-}\r
-\r
-VOID\r
-SetDefaultSounds()\r
-{\r
+void\r
+LoadAllSounds()\r
+{ // [HGM] import name from appData first\r
   ColorClass cc;\r
   SoundClass sc;\r
-  for (cc = (ColorClass)0; cc < NColorClasses; cc++) {\r
+  for (cc = (ColorClass)0; cc < ColorNormal; cc++) {\r
+    textAttribs[cc].sound.name = strdup((&appData.soundShout)[cc]);\r
+    textAttribs[cc].sound.data = NULL;\r
+    MyLoadSound(&textAttribs[cc].sound);\r
+  }\r
+  for (cc = ColorNormal; cc < NColorClasses; cc++) {\r
     textAttribs[cc].sound.name = strdup("");\r
     textAttribs[cc].sound.data = NULL;\r
   }\r
   for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {\r
-    sounds[sc].name = strdup("");\r
+    sounds[sc].name = strdup((&appData.soundMove)[sc]);\r
     sounds[sc].data = NULL;\r
-  }\r
-  sounds[(int)SoundBell].name = strdup(SOUND_BELL);\r
-}\r
-\r
-VOID\r
-LoadAllSounds()\r
-{\r
-  ColorClass cc;\r
-  SoundClass sc;\r
-  for (cc = (ColorClass)0; cc < NColorClasses; cc++) {\r
-    MyLoadSound(&textAttribs[cc].sound);\r
-  }\r
-  for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {\r
     MyLoadSound(&sounds[sc]);\r
   }\r
 }\r
 \r
-VOID\r
-InitAppData(LPSTR lpCmdLine)\r
+void\r
+SetCommPortDefaults()\r
 {\r
-  int i, j;\r
-  char buf[ARG_MAX], currDir[MSG_SIZ];\r
-  char *dummy, *p;\r
-\r
-  programName = szAppName;\r
-\r
-  /* Initialize to defaults */\r
-  lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);\r
-  darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);\r
-  whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);\r
-  blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);\r
-  highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);\r
-  premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);\r
-  consoleBackgroundColor = ParseColorName(COLOR_BKGD);\r
-  SetDefaultTextAttribs();\r
-  SetDefaultSounds();\r
-  appData.movesPerSession = MOVES_PER_SESSION;\r
-  appData.initString = INIT_STRING;\r
-  appData.secondInitString = INIT_STRING;\r
-  appData.firstComputerString = COMPUTER_STRING;\r
-  appData.secondComputerString = COMPUTER_STRING;\r
-  appData.firstChessProgram = FIRST_CHESS_PROGRAM;\r
-  appData.secondChessProgram = SECOND_CHESS_PROGRAM;\r
-  appData.firstPlaysBlack = FALSE;\r
-  appData.noChessProgram = FALSE;\r
-  chessProgram = FALSE;\r
-  appData.firstHost = FIRST_HOST;\r
-  appData.secondHost = SECOND_HOST;\r
-  appData.firstDirectory = FIRST_DIRECTORY;\r
-  appData.secondDirectory = SECOND_DIRECTORY;\r
-  appData.bitmapDirectory = "";\r
-  appData.remoteShell = REMOTE_SHELL;\r
-  appData.remoteUser = "";\r
-  appData.timeDelay = TIME_DELAY;\r
-  appData.timeControl = TIME_CONTROL;\r
-  appData.timeIncrement = TIME_INCREMENT;\r
-  appData.icsActive = FALSE;\r
-  appData.icsHost = "";\r
-  appData.icsPort = ICS_PORT;\r
-  appData.icsCommPort = ICS_COMM_PORT;\r
-  appData.icsLogon = ICS_LOGON;\r
-  appData.icsHelper = "";\r
-  appData.useTelnet = FALSE;\r
-  appData.telnetProgram = TELNET_PROGRAM;\r
-  appData.gateway = "";\r
-  appData.loadGameFile = "";\r
-  appData.loadGameIndex = 0;\r
-  appData.saveGameFile = "";\r
-  appData.autoSaveGames = FALSE;\r
-  appData.loadPositionFile = "";\r
-  appData.loadPositionIndex = 1;\r
-  appData.savePositionFile = "";\r
-  appData.matchMode = FALSE;\r
-  appData.matchGames = 0;\r
-  appData.monoMode = FALSE;\r
-  appData.debugMode = FALSE;\r
-  appData.clockMode = TRUE;\r
-  boardSize = (BoardSize) -1; /* determine by screen size */\r
-  appData.Iconic = FALSE; /*unused*/\r
-  appData.searchTime = "";\r
-  appData.searchDepth = 0;\r
-  appData.showCoords = FALSE;\r
-  appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/\r
-  appData.autoCallFlag = FALSE;\r
-  appData.flipView = FALSE;\r
-  appData.autoFlipView = TRUE;\r
-  appData.cmailGameName = "";\r
-  appData.alwaysPromoteToQueen = FALSE;\r
-  appData.oldSaveStyle = FALSE;\r
-  appData.quietPlay = FALSE;\r
-  appData.showThinking = FALSE;\r
-  appData.ponderNextMove = TRUE;\r
-  appData.periodicUpdates = TRUE;\r
-  appData.popupExitMessage = TRUE;\r
-  appData.popupMoveErrors = FALSE;\r
-  appData.autoObserve = FALSE;\r
-  appData.autoComment = FALSE;\r
-  appData.animate = TRUE;\r
-  appData.animSpeed = 10;\r
-  appData.animateDragging = TRUE;\r
-  appData.highlightLastMove = TRUE;\r
-  appData.getMoveList = TRUE;\r
-  appData.testLegality = TRUE;\r
-  appData.premove = TRUE;\r
-  appData.premoveWhite = FALSE;\r
-  appData.premoveWhiteText = "";\r
-  appData.premoveBlack = FALSE;\r
-  appData.premoveBlackText = "";\r
-  appData.icsAlarm = TRUE;\r
-  appData.icsAlarmTime = 5000;\r
-  appData.autoRaiseBoard = TRUE;\r
-  appData.localLineEditing = TRUE;\r
-  appData.colorize = TRUE;\r
-  appData.reuseFirst = TRUE;\r
-  appData.reuseSecond = TRUE;\r
-  appData.blindfold = FALSE;\r
+   memset(&dcb, 0, sizeof(DCB)); // required by VS 2002 +\r
   dcb.DCBlength = sizeof(DCB);\r
   dcb.BaudRate = 9600;\r
   dcb.fBinary = TRUE;\r
@@ -1811,473 +1118,124 @@ InitAppData(LPSTR lpCmdLine)
   dcb.fNull = FALSE;\r
   dcb.fRtsControl = RTS_CONTROL_ENABLE;\r
   dcb.fAbortOnError = FALSE;\r
-  dcb.wReserved = 0;\r
   dcb.ByteSize = 7;\r
   dcb.Parity = SPACEPARITY;\r
   dcb.StopBits = ONESTOPBIT;\r
-  settingsFileName = SETTINGS_FILE;\r
-  saveSettingsOnExit = TRUE;\r
-  boardX = CW_USEDEFAULT;\r
-  boardY = CW_USEDEFAULT;\r
-  consoleX = CW_USEDEFAULT; \r
-  consoleY = CW_USEDEFAULT; \r
-  consoleW = CW_USEDEFAULT;\r
-  consoleH = CW_USEDEFAULT;\r
-  analysisX = CW_USEDEFAULT; \r
-  analysisY = CW_USEDEFAULT; \r
-  analysisW = CW_USEDEFAULT;\r
-  analysisH = CW_USEDEFAULT;\r
-  commentX = CW_USEDEFAULT; \r
-  commentY = CW_USEDEFAULT; \r
-  commentW = CW_USEDEFAULT;\r
-  commentH = CW_USEDEFAULT;\r
-  editTagsX = CW_USEDEFAULT; \r
-  editTagsY = CW_USEDEFAULT; \r
-  editTagsW = CW_USEDEFAULT;\r
-  editTagsH = CW_USEDEFAULT;\r
-  gameListX = CW_USEDEFAULT; \r
-  gameListY = CW_USEDEFAULT; \r
-  gameListW = CW_USEDEFAULT;\r
-  gameListH = CW_USEDEFAULT;\r
-  icsTextMenuString = ICS_TEXT_MENU_DEFAULT;\r
-  icsNames = ICS_NAMES;\r
-  firstChessProgramNames = FCP_NAMES;\r
-  secondChessProgramNames = SCP_NAMES;\r
-  appData.initialMode = "";\r
-  appData.variant = "normal";\r
-  appData.firstProtocolVersion = PROTOVER;\r
-  appData.secondProtocolVersion = PROTOVER;\r
-  appData.showButtonBar = TRUE;\r
-\r
-   /* [AS] New properties (see comments in header file) */\r
-  appData.firstScoreIsAbsolute = FALSE;\r
-  appData.secondScoreIsAbsolute = FALSE;\r
-  appData.saveExtendedInfoInPGN = FALSE;\r
-  appData.hideThinkingFromHuman = FALSE;\r
-  appData.liteBackTextureFile = "";\r
-  appData.liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;\r
-  appData.darkBackTextureFile = "";\r
-  appData.darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;\r
-  appData.renderPiecesWithFont = "";\r
-  appData.fontToPieceTable = "";\r
-  appData.fontBackColorWhite = 0;\r
-  appData.fontForeColorWhite = 0;\r
-  appData.fontBackColorBlack = 0;\r
-  appData.fontForeColorBlack = 0;\r
-  appData.fontPieceSize = 80;\r
-  appData.overrideLineGap = 1;\r
-  appData.adjudicateLossThreshold = 0;\r
-  appData.delayBeforeQuit = 0;\r
-  appData.delayAfterQuit = 0;\r
-  appData.nameOfDebugFile = "winboard.debug";\r
-  appData.pgnEventHeader = "Computer Chess Game";\r
-  appData.defaultFrcPosition = -1;\r
-  appData.gameListTags = GLT_DEFAULT_TAGS;\r
-  appData.saveOutOfBookInfo = TRUE;\r
-  appData.showEvalInMoveHistory = TRUE;\r
-  appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );\r
-  appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );\r
-  appData.highlightMoveWithArrow = FALSE;\r
-  appData.highlightArrowColor = ParseColorName( "#FFFF80" );\r
-  appData.useStickyWindows = TRUE;\r
-  appData.adjudicateDrawMoves = 0;\r
-  appData.autoDisplayComment = TRUE;\r
-  appData.autoDisplayTags = TRUE;\r
-  appData.firstIsUCI = FALSE;\r
-  appData.secondIsUCI = FALSE;\r
-  appData.firstHasOwnBookUCI = TRUE;\r
-  appData.secondHasOwnBookUCI = TRUE;\r
-  appData.polyglotDir = "";\r
-  appData.usePolyglotBook = FALSE;\r
-  appData.polyglotBook = "";\r
-  appData.defaultHashSize = 64;\r
-  appData.defaultCacheSizeEGTB = 4;\r
-  appData.defaultPathEGTB = "c:\\egtb";\r
-\r
-  InitWindowPlacement( &wpMoveHistory );\r
-  InitWindowPlacement( &wpEvalGraph );\r
-  InitWindowPlacement( &wpEngineOutput );\r
-\r
-  /* [HGM] User-selectable board size, adjudication control, miscellaneous */\r
-  appData.NrFiles      = -1;\r
-  appData.NrRanks      = -1;\r
-  appData.holdingsSize = -1;\r
-  appData.testClaims   = FALSE;\r
-  appData.checkMates   = FALSE;\r
-  appData.materialDraws= FALSE;\r
-  appData.trivialDraws = FALSE;\r
-  appData.ruleMoves    = 51;\r
-  appData.drawRepeats  = 6;\r
-  appData.matchPause   = 10000;\r
-  appData.alphaRank    = FALSE;\r
-  appData.allWhite     = FALSE;\r
-  appData.upsideDown   = FALSE;\r
-  appData.serverPause  = 15;\r
-  appData.serverMovesName   = NULL;\r
-  appData.suppressLoadMoves = FALSE;\r
-  appData.firstTimeOdds  = 1;\r
-  appData.secondTimeOdds = 1;\r
-  appData.firstAccumulateTC  = 1; // combine previous and current sessions\r
-  appData.secondAccumulateTC = 1;\r
-  appData.firstNPS  = -1; // [HGM] nps: use wall-clock time\r
-  appData.secondNPS = -1;\r
-  appData.engineComments = 1;\r
-\r
-\r
-#ifdef ZIPPY\r
-  appData.zippyTalk = ZIPPY_TALK;\r
-  appData.zippyPlay = ZIPPY_PLAY;\r
-  appData.zippyLines = ZIPPY_LINES;\r
-  appData.zippyPinhead = ZIPPY_PINHEAD;\r
-  appData.zippyPassword = ZIPPY_PASSWORD;\r
-  appData.zippyPassword2 = ZIPPY_PASSWORD2;\r
-  appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;\r
-  appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;\r
-  appData.zippyUseI = ZIPPY_USE_I;\r
-  appData.zippyBughouse = ZIPPY_BUGHOUSE;\r
-  appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;\r
-  appData.zippyGameEnd = ZIPPY_GAME_END;\r
-  appData.zippyGameStart = ZIPPY_GAME_START;\r
-  appData.zippyAdjourn = ZIPPY_ADJOURN;\r
-  appData.zippyAbort = ZIPPY_ABORT;\r
-  appData.zippyVariants = ZIPPY_VARIANTS;\r
-  appData.zippyMaxGames = ZIPPY_MAX_GAMES;\r
-  appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;\r
-#endif\r
-\r
-  /* Point font array elements to structures and\r
-     parse default font names */\r
-  for (i=0; i<NUM_FONTS; i++) {\r
-    for (j=0; j<NUM_SIZES; j++) {\r
-      font[j][i] = &fontRec[j][i];\r
-      ParseFontName(font[j][i]->def, &font[j][i]->mfp);\r
-    }\r
-  }\r
-  \r
-  /* Parse default settings file if any */\r
-  if (ParseSettingsFile(settingsFileName, buf)) {\r
-    settingsFileName = strdup(buf);\r
-  }\r
-\r
-  /* Parse command line */\r
-  ParseArgs(StringGet, &lpCmdLine);\r
-\r
-  /* [HGM] make sure board size is acceptable */\r
-  if(appData.NrFiles > BOARD_SIZE ||\r
-     appData.NrRanks > BOARD_SIZE   )\r
-      DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);\r
+}\r
 \r
-  /* [HGM] After parsing the options from the .ini file, and overruling them\r
-   * with options from the command line, we now make an even higher priority\r
-   * overrule by WB options attached to the engine command line. This so that\r
-   * tournament managers can use WB options (such as /timeOdds) that follow\r
-   * the engines.\r
-   */\r
-  if(appData.firstChessProgram != NULL) {\r
-      char *p = StrStr(appData.firstChessProgram, "WBopt");\r
-      static char *f = "first";\r
-      char buf[MSG_SIZ], *q = buf;\r
-      if(p != NULL) { // engine command line contains WinBoard options\r
-          sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"\r
-          ParseArgs(StringGet, &q);\r
-          p[-1] = 0; // cut them offengine command line\r
-      }\r
-  }\r
-  // now do same for second chess program\r
-  if(appData.secondChessProgram != NULL) {\r
-      char *p = StrStr(appData.secondChessProgram, "WBopt");\r
-      static char *s = "second";\r
-      char buf[MSG_SIZ], *q = buf;\r
-      if(p != NULL) { // engine command line contains WinBoard options\r
-          sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"\r
-          ParseArgs(StringGet, &q);\r
-          p[-1] = 0; // cut them offengine command line\r
+// [HGM] args: these three cases taken out to stay in front-end\r
+void\r
+SaveFontArg(FILE *f, ArgDescriptor *ad)\r
+{      // in WinBoard every board size has its own font, and the "argLoc" identifies the table,\r
+       // while the curent board size determines the element. This system should be ported to XBoard.\r
+       // What the table contains pointers to, and how to print the font description, remains platform-dependent\r
+        int bs;\r
+       for (bs=0; bs<NUM_SIZES; bs++) {\r
+         MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;\r
+          fprintf(f, "/size=%s ", sizeInfo[bs].name);\r
+         fprintf(f, "/%s=\"%s:%g%s%s%s%s%sc%d\"\n",\r
+           ad->argName, mfp->faceName, mfp->pointSize,\r
+            mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",\r
+           mfp->bold ? "b" : "",\r
+           mfp->italic ? "i" : "",\r
+           mfp->underline ? "u" : "",\r
+           mfp->strikeout ? "s" : "",\r
+            (int)mfp->charset);\r
+       }\r
       }\r
-  }\r
 \r
+void\r
+ExportSounds()\r
+{ // [HGM] copy the names from the internal WB variables to appData\r
+  ColorClass cc;\r
+  SoundClass sc;\r
+  for (cc = (ColorClass)0; cc < ColorNormal; cc++)\r
+    (&appData.soundShout)[cc] = textAttribs[cc].sound.name;\r
+  for (sc = (SoundClass)0; sc < NSoundClasses; sc++)\r
+    (&appData.soundMove)[sc] = sounds[sc].name;\r
+}\r
 \r
-  /* Propagate options that affect others */\r
-  if (appData.matchMode || appData.matchGames) chessProgram = TRUE;\r
-  if (appData.icsActive || appData.noChessProgram) {\r
-     chessProgram = FALSE;  /* not local chess program mode */\r
-  }\r
+void\r
+SaveAttribsArg(FILE *f, ArgDescriptor *ad)\r
+{      // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though\r
+       MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];\r
+       fprintf(f, "/%s=\"%s%s%s%s%s#%02lx%02lx%02lx\"\n", ad->argName,\r
+          (ta->effects & CFE_BOLD) ? "b" : "",\r
+          (ta->effects & CFE_ITALIC) ? "i" : "",\r
+          (ta->effects & CFE_UNDERLINE) ? "u" : "",\r
+          (ta->effects & CFE_STRIKEOUT) ? "s" : "",\r
+          (ta->effects) ? " " : "",\r
+         ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);\r
+      }\r
 \r
-  /* Open startup dialog if needed */\r
-  if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||\r
-      (appData.icsActive && *appData.icsHost == NULLCHAR) ||\r
-      (chessProgram && (*appData.firstChessProgram == NULLCHAR ||\r
-                        *appData.secondChessProgram == NULLCHAR))) {\r
-    FARPROC lpProc;\r
-    \r
-    lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);\r
-    DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);\r
-    FreeProcInstance(lpProc);\r
-  }\r
+void\r
+SaveColor(FILE *f, ArgDescriptor *ad)\r
+{      // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?\r
+       COLORREF color = *(COLORREF *)colorVariable[(int)ad->argLoc];\r
+       fprintf(f, "/%s=#%02lx%02lx%02lx\n", ad->argName, \r
+         color&0xff, (color>>8)&0xff, (color>>16)&0xff);\r
+}\r
 \r
-  /* Make sure save files land in the right (?) directory */\r
-  if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {\r
-    appData.saveGameFile = strdup(buf);\r
-  }\r
-  if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {\r
-    appData.savePositionFile = strdup(buf);\r
-  }\r
+void\r
+SaveBoardSize(FILE *f, char *name, void *addr)\r
+{ // wrapper to shield back-end from BoardSize & sizeInfo\r
+  fprintf(f, "/%s=%s\n", name, sizeInfo[*(BoardSize *)addr].name);\r
+}\r
 \r
-  /* Finish initialization for fonts and sounds */\r
-  for (i=0; i<NUM_FONTS; i++) {\r
-    for (j=0; j<NUM_SIZES; j++) {\r
-      CreateFontInMF(font[j][i]);\r
-    }\r
-  }\r
-  /* xboard, and older WinBoards, controlled the move sound with the\r
-     appData.ringBellAfterMoves option.  In the current WinBoard, we\r
-     always turn the option on (so that the backend will call us),\r
-     then let the user turn the sound off by setting it to silence if\r
-     desired.  To accommodate old winboard.ini files saved by old\r
-     versions of WinBoard, we also turn off the sound if the option\r
-     was initially set to false. */\r
-  if (!appData.ringBellAfterMoves) {\r
-    sounds[(int)SoundMove].name = strdup("");\r
-    appData.ringBellAfterMoves = TRUE;\r
-  }\r
-  GetCurrentDirectory(MSG_SIZ, currDir);\r
-  SetCurrentDirectory(installDir);\r
-  LoadAllSounds();\r
-  SetCurrentDirectory(currDir);\r
+void\r
+ParseCommPortSettings(char *s)\r
+{ // wrapper to keep dcb from back-end\r
+  ParseCommSettings(s, &dcb);\r
+}\r
 \r
-  p = icsTextMenuString;\r
-  if (p[0] == '@') {\r
-    FILE* f = fopen(p + 1, "r");\r
-    if (f == NULL) {\r
-      DisplayFatalError(p + 1, errno, 2);\r
-      return;\r
-    }\r
-    i = fread(buf, 1, sizeof(buf)-1, f);\r
-    fclose(f);\r
-    buf[i] = NULLCHAR;\r
-    p = buf;\r
-  }\r
-  ParseIcsTextMenu(strdup(p));\r
+void\r
+GetWindowCoords()\r
+{ // wrapper to shield use of window handles from back-end (make addressible by number?)\r
+  GetActualPlacement(hwndMain, &wpMain);\r
+  GetActualPlacement(hwndConsole, &wpConsole);\r
+  GetActualPlacement(commentDialog, &wpComment);\r
+  GetActualPlacement(editTagsDialog, &wpTags);\r
+  GetActualPlacement(gameListDialog, &wpGameList);\r
+  GetActualPlacement(moveHistoryDialog, &wpMoveHistory);\r
+  GetActualPlacement(evalGraphDialog, &wpEvalGraph);\r
+  GetActualPlacement(engineOutputDialog, &wpEngineOutput);\r
 }\r
 \r
+void\r
+PrintCommPortSettings(FILE *f, char *name)\r
+{ // wrapper to shield back-end from DCB\r
+      PrintCommSettings(f, name, &dcb);\r
+}\r
 \r
-VOID\r
-InitMenuChecks()\r
+int\r
+MySearchPath(char *installDir, char *name, char *fullname)\r
 {\r
-  HMENU hmenu = GetMenu(hwndMain);\r
-\r
-  (void) EnableMenuItem(hmenu, IDM_CommPort,\r
-                       MF_BYCOMMAND|((appData.icsActive &&\r
-                                      *appData.icsCommPort != NULLCHAR) ?\r
-                                     MF_ENABLED : MF_GRAYED));\r
-  (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,\r
-                      MF_BYCOMMAND|(saveSettingsOnExit ?\r
-                                    MF_CHECKED : MF_UNCHECKED));\r
+  char *dummy;\r
+  return (int) SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy);\r
 }\r
 \r
-\r
-VOID\r
-SaveSettings(char* name)\r
+int\r
+MyGetFullPathName(char *name, char *fullname)\r
 {\r
-  FILE *f;\r
-  ArgDescriptor *ad;\r
-  WINDOWPLACEMENT wp;\r
-  char dir[MSG_SIZ];\r
-\r
-  if (!hwndMain) return;\r
-\r
-  GetCurrentDirectory(MSG_SIZ, dir);\r
-  SetCurrentDirectory(installDir);\r
-  f = fopen(name, "w");\r
-  SetCurrentDirectory(dir);\r
-  if (f == NULL) {\r
-    DisplayError(name, errno);\r
-    return;\r
-  }\r
-  fprintf(f, ";\n");\r
-  fprintf(f, "; %s %s.%s Save Settings file\n", PRODUCT, VERSION, PATCHLEVEL);\r
-  fprintf(f, ";\n");\r
-  fprintf(f, "; You can edit the values of options that are already set in this file,\n");\r
-  fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");\r
-  fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");\r
-  fprintf(f, ";\n");\r
-\r
-  wp.length = sizeof(WINDOWPLACEMENT);\r
-  GetWindowPlacement(hwndMain, &wp);\r
-  boardX = wp.rcNormalPosition.left;\r
-  boardY = wp.rcNormalPosition.top;\r
-\r
-  if (hwndConsole) {\r
-    GetWindowPlacement(hwndConsole, &wp);\r
-    consoleX = wp.rcNormalPosition.left;\r
-    consoleY = wp.rcNormalPosition.top;\r
-    consoleW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
-    consoleH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
-  }\r
-\r
-  if (analysisDialog) {\r
-    GetWindowPlacement(analysisDialog, &wp);\r
-    analysisX = wp.rcNormalPosition.left;\r
-    analysisY = wp.rcNormalPosition.top;\r
-    analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
-    analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
-  }\r
-\r
-  if (commentDialog) {\r
-    GetWindowPlacement(commentDialog, &wp);\r
-    commentX = wp.rcNormalPosition.left;\r
-    commentY = wp.rcNormalPosition.top;\r
-    commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
-    commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
-  }\r
-\r
-  if (editTagsDialog) {\r
-    GetWindowPlacement(editTagsDialog, &wp);\r
-    editTagsX = wp.rcNormalPosition.left;\r
-    editTagsY = wp.rcNormalPosition.top;\r
-    editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
-    editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
-  }\r
-\r
-  if (gameListDialog) {\r
-    GetWindowPlacement(gameListDialog, &wp);\r
-    gameListX = wp.rcNormalPosition.left;\r
-    gameListY = wp.rcNormalPosition.top;\r
-    gameListW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
-    gameListH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
-  }\r
-\r
-  /* [AS] Move history */\r
-  wpMoveHistory.visible = MoveHistoryIsUp();\r
-  \r
-  if( moveHistoryDialog ) {\r
-    GetWindowPlacement(moveHistoryDialog, &wp);\r
-    wpMoveHistory.x = wp.rcNormalPosition.left;\r
-    wpMoveHistory.y = wp.rcNormalPosition.top;\r
-    wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
-    wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
-  }\r
-\r
-  /* [AS] Eval graph */\r
-  wpEvalGraph.visible = EvalGraphIsUp();\r
-\r
-  if( evalGraphDialog ) {\r
-    GetWindowPlacement(evalGraphDialog, &wp);\r
-    wpEvalGraph.x = wp.rcNormalPosition.left;\r
-    wpEvalGraph.y = wp.rcNormalPosition.top;\r
-    wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
-    wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
-  }\r
-\r
-  /* [AS] Engine output */\r
-  wpEngineOutput.visible = EngineOutputIsUp();\r
-\r
-  if( engineOutputDialog ) {\r
-    GetWindowPlacement(engineOutputDialog, &wp);\r
-    wpEngineOutput.x = wp.rcNormalPosition.left;\r
-    wpEngineOutput.y = wp.rcNormalPosition.top;\r
-    wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
-    wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
-  }\r
-\r
-  for (ad = argDescriptors; ad->argName != NULL; ad++) {\r
-    if (!ad->save) continue;\r
-    switch (ad->argType) {\r
-    case ArgString:\r
-      {\r
-       char *p = *(char **)ad->argLoc;\r
-       if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {\r
-         /* Quote multiline values or \-containing values\r
-            with { } if possible */\r
-         fprintf(f, "/%s={%s}\n", ad->argName, p);\r
-       } else {\r
-         /* Else quote with " " */\r
-         fprintf(f, "/%s=\"", ad->argName);\r
-         while (*p) {\r
-           if (*p == '\n') fprintf(f, "\n");\r
-           else if (*p == '\r') fprintf(f, "\\r");\r
-           else if (*p == '\t') fprintf(f, "\\t");\r
-           else if (*p == '\b') fprintf(f, "\\b");\r
-           else if (*p == '\f') fprintf(f, "\\f");\r
-           else if (*p < ' ') fprintf(f, "\\%03o", *p);\r
-           else if (*p == '\"') fprintf(f, "\\\"");\r
-           else if (*p == '\\') fprintf(f, "\\\\");\r
-           else putc(*p, f);\r
-           p++;\r
-         }\r
-         fprintf(f, "\"\n");\r
-       }\r
-      }\r
-      break;\r
-    case ArgInt:\r
-      fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);\r
-      break;\r
-    case ArgFloat:\r
-      fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);\r
-      break;\r
-    case ArgBoolean:\r
-      fprintf(f, "/%s=%s\n", ad->argName, \r
-       (*(Boolean *)ad->argLoc) ? "true" : "false");\r
-      break;\r
-    case ArgTrue:\r
-      if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);\r
-      break;\r
-    case ArgFalse:\r
-      if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);\r
-      break;\r
-    case ArgColor:\r
-      {\r
-       COLORREF color = *(COLORREF *)ad->argLoc;\r
-       fprintf(f, "/%s=#%02x%02x%02x\n", ad->argName, \r
-         color&0xff, (color>>8)&0xff, (color>>16)&0xff);\r
-      }\r
-      break;\r
-    case ArgAttribs:\r
-      {\r
-       MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];\r
-       fprintf(f, "/%s=\"%s%s%s%s%s#%02x%02x%02x\"\n", ad->argName,\r
-          (ta->effects & CFE_BOLD) ? "b" : "",\r
-          (ta->effects & CFE_ITALIC) ? "i" : "",\r
-          (ta->effects & CFE_UNDERLINE) ? "u" : "",\r
-          (ta->effects & CFE_STRIKEOUT) ? "s" : "",\r
-          (ta->effects) ? " " : "",\r
-         ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);\r
-      }\r
-      break;\r
-    case ArgFilename:\r
-      if (strchr(*(char **)ad->argLoc, '\"')) {\r
-       fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);\r
-      } else {\r
-       fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);\r
-      }\r
-      break;\r
-    case ArgBoardSize:\r
-      fprintf(f, "/%s=%s\n", ad->argName,\r
-             sizeInfo[*(BoardSize *)ad->argLoc].name);\r
-      break;\r
-    case ArgFont:\r
-      {\r
-        int bs;\r
-       for (bs=0; bs<NUM_SIZES; bs++) {\r
-         MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;\r
-          fprintf(f, "/size=%s ", sizeInfo[bs].name);\r
-         fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n",\r
-           ad->argName, mfp->faceName, mfp->pointSize,\r
-            mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",\r
-           mfp->bold ? "b" : "",\r
-           mfp->italic ? "i" : "",\r
-           mfp->underline ? "u" : "",\r
-           mfp->strikeout ? "s" : "");\r
-       }\r
-      }\r
-      break;\r
-    case ArgCommSettings:\r
-      PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);\r
-    }\r
-  }\r
-  fclose(f);\r
+  char *dummy;\r
+  return (int) GetFullPathName(name, MSG_SIZ, fullname, &dummy);\r
 }\r
 \r
+int\r
+MainWindowUp()\r
+{ // [HGM] args: allows testing if main window is realized from back-end\r
+  return hwndMain != NULL;\r
+}\r
 \r
+void\r
+PopUpStartupDialog()\r
+{\r
+    FARPROC lpProc;\r
+    \r
+    lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);\r
+    DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);\r
+    FreeProcInstance(lpProc);\r
+}\r
 \r
 /*---------------------------------------------------------------------------*\\r
  *\r
@@ -2365,6 +1323,12 @@ enum {
     PM_WH = (int) WhiteNightrider, \r
     PM_WA = (int) WhiteAngel, \r
     PM_WC = (int) WhiteMarshall, \r
+    PM_WAB = (int) WhiteCardinal, \r
+    PM_WD = (int) WhiteDragon, \r
+    PM_WL = (int) WhiteLance, \r
+    PM_WS = (int) WhiteCobra, \r
+    PM_WV = (int) WhiteFalcon, \r
+    PM_WSG = (int) WhiteSilver, \r
     PM_WG = (int) WhiteGrasshopper, \r
     PM_WK = (int) WhiteKing,\r
     PM_BP = (int) BlackPawn, \r
@@ -2382,6 +1346,12 @@ enum {
     PM_BA = (int) BlackAngel, \r
     PM_BC = (int) BlackMarshall, \r
     PM_BG = (int) BlackGrasshopper, \r
+    PM_BAB = (int) BlackCardinal,\r
+    PM_BD = (int) BlackDragon,\r
+    PM_BL = (int) BlackLance,\r
+    PM_BS = (int) BlackCobra,\r
+    PM_BV = (int) BlackFalcon,\r
+    PM_BSG = (int) BlackSilver,\r
     PM_BK = (int) BlackKing\r
 };\r
 \r
@@ -2480,13 +1450,12 @@ static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
     POINT pt;\r
     int backColor = whitePieceColor; \r
     int foreColor = blackPieceColor;\r
-    int shapeIndex = index < 6 ? index+6 : index;\r
     \r
-    if( index < 6 && appData.fontBackColorWhite != appData.fontForeColorWhite ) {\r
+    if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {\r
         backColor = appData.fontBackColorWhite;\r
         foreColor = appData.fontForeColorWhite;\r
     }\r
-    else if( index >= 6 && appData.fontBackColorBlack != appData.fontForeColorBlack ) {\r
+    else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {\r
         backColor = appData.fontBackColorBlack;\r
         foreColor = appData.fontForeColorBlack;\r
     }\r
@@ -2512,11 +1481,15 @@ static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
     SetBkMode( hdc, TRANSPARENT );\r
     SetTextColor( hdc, chroma );\r
     /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */\r
-    TextOut( hdc, pt.x, pt.y, &pieceToFontChar[index], 1 );\r
+    TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );\r
 \r
     SelectObject( hdc, GetStockObject(WHITE_BRUSH) );\r
     /* Step 3: the area outside the piece is filled with white */\r
-    FloodFill( hdc, 0, 0, chroma );\r
+//    FloodFill( hdc, 0, 0, chroma );\r
+    ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );\r
+    ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big\r
+    ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );\r
+    ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );\r
     SelectObject( hdc, GetStockObject(BLACK_BRUSH) );\r
     /* \r
         Step 4: this is the tricky part, the area inside the piece is filled with black,\r
@@ -2524,14 +1497,30 @@ static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
         There should be a better way to do this... if we could create a region or path\r
         from the fill operation we would be fine for example.\r
     */\r
-    FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );\r
+//    FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );\r
+    ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );\r
+\r
+    {   /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */\r
+        HDC dc2 = CreateCompatibleDC( hdc_window );\r
+        HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );\r
+\r
+        SelectObject( dc2, bm2 );\r
+        BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy\r
+        BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );\r
+        BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );\r
+        BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );\r
+        BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );\r
+\r
+        DeleteDC( dc2 );\r
+        DeleteObject( bm2 );\r
+    }\r
 \r
     SetTextColor( hdc, 0 );\r
     /* \r
         Step 5: some fonts have "disconnected" areas that are skipped by the fill:\r
         draw the piece again in black for safety.\r
     */\r
-    TextOut( hdc, pt.x, pt.y, &pieceToFontChar[index], 1 );\r
+    TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );\r
 \r
     SelectObject( hdc, hbm_old );\r
 \r
@@ -2572,7 +1561,7 @@ static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
     }\r
 \r
     SetTextColor( hdc, foreColor );\r
-    TextOut( hdc, pt.x, pt.y, &pieceToFontChar[index], 1 );\r
+    TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );\r
 \r
     SelectObject( hdc, hbm_old );\r
 \r
@@ -2610,6 +1599,7 @@ static int TranslatePieceToFontPiece( int piece )
         return PM_WQ;\r
     case WhiteKing:\r
         return PM_WK;\r
+\r
     case BlackAngel:\r
         return PM_BA;\r
     case BlackMarshall:\r
@@ -2630,6 +1620,19 @@ static int TranslatePieceToFontPiece( int piece )
         return PM_BG;\r
     case BlackMan:\r
         return PM_BM;\r
+    case BlackSilver:\r
+        return PM_BSG;\r
+    case BlackLance:\r
+        return PM_BL;\r
+    case BlackFalcon:\r
+        return PM_BV;\r
+    case BlackCobra:\r
+        return PM_BS;\r
+    case BlackCardinal:\r
+        return PM_BAB;\r
+    case BlackDragon:\r
+        return PM_BD;\r
+\r
     case WhiteAngel:\r
         return PM_WA;\r
     case WhiteMarshall:\r
@@ -2650,6 +1653,18 @@ static int TranslatePieceToFontPiece( int piece )
         return PM_WG;\r
     case WhiteMan:\r
         return PM_WM;\r
+    case WhiteSilver:\r
+        return PM_WSG;\r
+    case WhiteLance:\r
+        return PM_WL;\r
+    case WhiteFalcon:\r
+        return PM_WV;\r
+    case WhiteCobra:\r
+        return PM_WS;\r
+    case WhiteCardinal:\r
+        return PM_WAB;\r
+    case WhiteDragon:\r
+        return PM_WD;\r
     }\r
 \r
     return 0;\r
@@ -2682,7 +1697,7 @@ void CreatePiecesFromFont()
             DeleteObject( hPieceFont );\r
         }\r
         else {\r
-            for( i=0; i<12; i++ ) {\r
+            for( i=0; i<=(int)BlackKing; i++ ) {\r
                 hPieceMask[i] = NULL;\r
                 hPieceFace[i] = NULL;\r
             }\r
@@ -2735,7 +1750,7 @@ void CreatePiecesFromFont()
                 }\r
                 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {\r
                     /* Good Companion (Some characters get warped as literal :-( */\r
-                    char s[] = "1cmWG0ñueOS¯®oYI23wgQU";\r
+                    char s[] = "1cmWG0??S??oYI23wgQU";\r
                     s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;\r
                     SetCharTable(pieceToFontChar, s);\r
                 }\r
@@ -2747,41 +1762,9 @@ void CreatePiecesFromFont()
 \r
             /* Create bitmaps */\r
             hfont_old = SelectObject( hdc, hPieceFont );\r
-\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_WP );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_WN );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_WB );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_WR );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_WQ );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_WK );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_BP );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_BN );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_BB );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_BR );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_BQ );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_BK );\r
-#ifdef FAIRY\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_WA );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_WC );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_WF );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_WH );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_WE );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_WW );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_WU );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_WO );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_WG );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_WM );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_BA );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_BC );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_BF );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_BH );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_BE );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_BW );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_BU );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_BO );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_BG );\r
-            CreatePieceMaskFromFont( hdc_window, hdc, PM_BM );\r
-#endif\r
+           for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */\r
+               if(PieceToChar((ChessSquare)i) != '.')     /* skip unused pieces         */\r
+                   CreatePieceMaskFromFont( hdc_window, hdc, i );\r
 \r
             SelectObject( hdc, hfont_old );\r
 \r
@@ -2870,7 +1853,8 @@ InitDrawingColors()
   whitePieceBrush = CreateSolidBrush(whitePieceColor);\r
   blackPieceBrush = CreateSolidBrush(blackPieceColor);\r
   iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));\r
-\r
+  explodeBrush = CreateSolidBrush(highlightSquareColor); // [HGM] atomic\r
+  markerBrush = CreateSolidBrush(premoveHighlightColor); // [HGM] markers\r
   /* [AS] Force rendering of the font-based pieces */\r
   if( fontBitmapSquareSize > 0 ) {\r
     fontBitmapSquareSize = 0;\r
@@ -2900,9 +1884,10 @@ ResizeBoard(int newSizeX, int newSizeY, int flags)
   if (IsIconic(hwndMain)) return;\r
   if (recurse > 0) return;\r
   recurse++;\r
-  while (newSize > 0 &&\r
-        (newSizeX < sizeInfo[newSize].cliWidth ||\r
-         newSizeY < sizeInfo[newSize].cliHeight)) {\r
+  while (newSize > 0) {\r
+       InitDrawingSizes(newSize+1000, 0); // [HGM] kludge to update sizeInfo without visible effects\r
+       if(newSizeX >= sizeInfo[newSize].cliWidth &&\r
+          newSizeY >= sizeInfo[newSize].cliHeight) break;\r
     newSize--;\r
   } \r
   boardSize = newSize;\r
@@ -2924,13 +1909,21 @@ InitDrawingSizes(BoardSize boardSize, int flags)
   char buf[MSG_SIZ];\r
   char *str;\r
   HMENU hmenu = GetMenu(hwndMain);\r
-  RECT crect, wrect;\r
+  RECT crect, wrect, oldRect;\r
   int offby;\r
   LOGBRUSH logbrush;\r
 \r
-  /* [HGM] call with -1 uses old size (for if nr of files, ranks changes) */\r
+  int suppressVisibleEffects = 0; // [HGM] kludge to request updating sizeInfo only\r
+  if((int)boardSize >= 1000 ) { boardSize -= 1000; suppressVisibleEffects = 1; }\r
+\r
+  /* [HGM] call with -2 uses old size (for if nr of files, ranks changes) */\r
   if(boardSize == (BoardSize)(-2) ) boardSize = oldBoardSize;\r
 \r
+  oldRect.left = wpMain.x; //[HGM] placement: remember previous window params\r
+  oldRect.top = wpMain.y;\r
+  oldRect.right = wpMain.x + wpMain.width;\r
+  oldRect.bottom = wpMain.y + wpMain.height;\r
+\r
   tinyLayout = sizeInfo[boardSize].tinyLayout;\r
   smallLayout = sizeInfo[boardSize].smallLayout;\r
   squareSize = sizeInfo[boardSize].squareSize;\r
@@ -2979,69 +1972,109 @@ InitDrawingSizes(BoardSize boardSize, int flags)
   ReleaseDC(hwndMain, hdc);\r
 \r
   /* Compute where everything goes */\r
-  whiteRect.left = OUTER_MARGIN;\r
-  whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2;\r
-  whiteRect.top = OUTER_MARGIN;\r
-  whiteRect.bottom = whiteRect.top + clockSize.cy;\r
+  if((first.programLogo || second.programLogo) && !tinyLayout) {\r
+        /* [HGM] logo: if either logo is on, reserve space for it */\r
+       logoHeight =  2*clockSize.cy;\r
+       leftLogoRect.left   = OUTER_MARGIN;\r
+       leftLogoRect.right  = leftLogoRect.left + 4*clockSize.cy;\r
+       leftLogoRect.top    = OUTER_MARGIN;\r
+       leftLogoRect.bottom = OUTER_MARGIN + logoHeight;\r
+\r
+       rightLogoRect.right  = OUTER_MARGIN + boardWidth;\r
+       rightLogoRect.left   = rightLogoRect.right - 4*clockSize.cy;\r
+       rightLogoRect.top    = OUTER_MARGIN;\r
+       rightLogoRect.bottom = OUTER_MARGIN + logoHeight;\r
+\r
+\r
+    whiteRect.left = leftLogoRect.right;\r
+    whiteRect.right = OUTER_MARGIN + boardWidth/2 - INNER_MARGIN/2;\r
+    whiteRect.top = OUTER_MARGIN;\r
+    whiteRect.bottom = whiteRect.top + logoHeight;\r
+\r
+    blackRect.right = rightLogoRect.left;\r
+    blackRect.left = whiteRect.right + INNER_MARGIN;\r
+    blackRect.top = whiteRect.top;\r
+    blackRect.bottom = whiteRect.bottom;\r
+  } else {\r
+    whiteRect.left = OUTER_MARGIN;\r
+    whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2;\r
+    whiteRect.top = OUTER_MARGIN;\r
+    whiteRect.bottom = whiteRect.top + clockSize.cy;\r
 \r
-  blackRect.left = whiteRect.right + INNER_MARGIN;\r
-  blackRect.right = blackRect.left + boardWidth/2 - 1;\r
-  blackRect.top = whiteRect.top;\r
-  blackRect.bottom = whiteRect.bottom;\r
+    blackRect.left = whiteRect.right + INNER_MARGIN;\r
+    blackRect.right = blackRect.left + boardWidth/2 - 1;\r
+    blackRect.top = whiteRect.top;\r
+    blackRect.bottom = whiteRect.bottom;\r
+\r
+    logoHeight = 0; // [HGM] logo: suppress logo after change to tiny layout!\r
+  }\r
 \r
-  messageRect.left = whiteRect.left + MESSAGE_LINE_LEFTMARGIN;\r
+  messageRect.left = OUTER_MARGIN + MESSAGE_LINE_LEFTMARGIN;\r
   if (appData.showButtonBar) {\r
-    messageRect.right = blackRect.right\r
+    messageRect.right = OUTER_MARGIN + boardWidth         // [HGM] logo: expressed independent of clock placement\r
       - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN;\r
   } else {\r
-    messageRect.right = blackRect.right;\r
+    messageRect.right = OUTER_MARGIN + boardWidth;\r
   }\r
   messageRect.top = whiteRect.bottom + INNER_MARGIN;\r
   messageRect.bottom = messageRect.top + messageSize.cy;\r
 \r
-  boardRect.left = whiteRect.left;\r
+  boardRect.left = OUTER_MARGIN;\r
   boardRect.right = boardRect.left + boardWidth;\r
   boardRect.top = messageRect.bottom + INNER_MARGIN;\r
   boardRect.bottom = boardRect.top + boardHeight;\r
 \r
   sizeInfo[boardSize].cliWidth = boardRect.right + OUTER_MARGIN;\r
   sizeInfo[boardSize].cliHeight = boardRect.bottom + OUTER_MARGIN;\r
-  winWidth = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN;\r
-  winHeight = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) +\r
+  oldBoardSize = boardSize;\r
+  oldTinyLayout = tinyLayout;\r
+  winW = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN;\r
+  winH = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) +\r
     GetSystemMetrics(SM_CYCAPTION) + boardRect.bottom + OUTER_MARGIN;\r
+  if(suppressVisibleEffects) return; // [HGM] when called for filling sizeInfo only\r
+  wpMain.width = winW;  // [HGM] placement: set through temporary which can used by initial sizing choice\r
+  wpMain.height = winH; //       without disturbing window attachments\r
   GetWindowRect(hwndMain, &wrect);\r
-  SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,\r
+  SetWindowPos(hwndMain, NULL, 0, 0, wpMain.width, wpMain.height,\r
               SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);\r
+\r
+  // [HGM] placement: let attached windows follow size change.\r
+  ReattachAfterSize( &oldRect, wpMain.width, wpMain.height, moveHistoryDialog, &wpMoveHistory );\r
+  ReattachAfterSize( &oldRect, wpMain.width, wpMain.height, evalGraphDialog, &wpEvalGraph );\r
+  ReattachAfterSize( &oldRect, wpMain.width, wpMain.height, engineOutputDialog, &wpEngineOutput );\r
+  ReattachAfterSize( &oldRect, wpMain.width, wpMain.height, gameListDialog, &wpGameList );\r
+  ReattachAfterSize( &oldRect, wpMain.width, wpMain.height, hwndConsole, &wpConsole );\r
+\r
   /* compensate if menu bar wrapped */\r
   GetClientRect(hwndMain, &crect);\r
   offby = boardRect.bottom + OUTER_MARGIN - crect.bottom;\r
-  winHeight += offby;\r
+  wpMain.height += offby;\r
   switch (flags) {\r
   case WMSZ_TOPLEFT:\r
     SetWindowPos(hwndMain, NULL, \r
-                 wrect.right - winWidth, wrect.bottom - winHeight, \r
-                 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);\r
+                 wrect.right - wpMain.width, wrect.bottom - wpMain.height, \r
+                 wpMain.width, wpMain.height, SWP_NOCOPYBITS|SWP_NOZORDER);\r
     break;\r
 \r
   case WMSZ_TOPRIGHT:\r
   case WMSZ_TOP:\r
     SetWindowPos(hwndMain, NULL, \r
-                 wrect.left, wrect.bottom - winHeight, \r
-                 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);\r
+                 wrect.left, wrect.bottom - wpMain.height, \r
+                 wpMain.width, wpMain.height, SWP_NOCOPYBITS|SWP_NOZORDER);\r
     break;\r
 \r
   case WMSZ_BOTTOMLEFT:\r
   case WMSZ_LEFT:\r
     SetWindowPos(hwndMain, NULL, \r
-                 wrect.right - winWidth, wrect.top, \r
-                 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);\r
+                 wrect.right - wpMain.width, wrect.top, \r
+                 wpMain.width, wpMain.height, SWP_NOCOPYBITS|SWP_NOZORDER);\r
     break;\r
 \r
   case WMSZ_BOTTOMRIGHT:\r
   case WMSZ_BOTTOM:\r
   case WMSZ_RIGHT:\r
   default:\r
-    SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,\r
+    SetWindowPos(hwndMain, NULL, 0, 0, wpMain.width, wpMain.height,\r
                SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);\r
     break;\r
   }\r
@@ -3097,7 +2130,6 @@ InitDrawingSizes(BoardSize boardSize, int flags)
        boardRect.top + lineGap / 2 + (i * (squareSize + lineGap));\r
       gridEndpoints[i*2 + 1].x = boardRect.left + lineGap / 2 +\r
         BOARD_WIDTH * (squareSize + lineGap);\r
-       lineGap / 2 + (i * (squareSize + lineGap));\r
       gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;\r
     }\r
     for (i = 0; i < BOARD_WIDTH + 1; i++) {\r
@@ -3122,8 +2154,6 @@ InitDrawingSizes(BoardSize boardSize, int flags)
 \r
 \r
 /*  if (boardSize == oldBoardSize) return; [HGM] variant might have changed */\r
-  oldBoardSize = boardSize;\r
-  oldTinyLayout = tinyLayout;\r
 \r
   /* Load piece bitmaps for this board size */\r
   for (i=0; i<=2; i++) {\r
@@ -3135,6 +2165,7 @@ InitDrawingSizes(BoardSize boardSize, int flags)
     }\r
   }\r
 \r
+  fontBitmapSquareSize = 0; /* [HGM] render: make sure pieces will be recreated, as we might need others now */\r
   // Orthodox Chess pieces\r
   pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s");\r
   pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s");\r
@@ -3484,7 +2515,7 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y,
     CreatePiecesFromFont();\r
 \r
     if( fontBitmapSquareSize == squareSize ) {\r
-        int index = TranslatePieceToFontPiece( piece );\r
+        int index = TranslatePieceToFontPiece(piece);\r
 \r
         SelectObject( tmphdc, hPieceMask[ index ] );\r
 \r
@@ -3516,8 +2547,8 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y,
   } else {\r
     tmpSize = squareSize;\r
     if(minorSize &&\r
-        (piece >= (int)WhiteNightrider && piece <= WhiteGrasshopper ||\r
-         piece >= (int)BlackNightrider && piece <= BlackGrasshopper)  ) {\r
+        ((piece >= (int)WhiteNightrider && piece <= WhiteGrasshopper) ||\r
+         (piece >= (int)BlackNightrider && piece <= BlackGrasshopper))  ) {\r
       /* [HGM] no bitmap available for promoted pieces in Crazyhouse        */\r
       /* Bitmaps of smaller size are substituted, but we have to align them */\r
       x += (squareSize - minorSize)>>1;\r
@@ -3533,35 +2564,13 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y,
         StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, 0x00B8074A);\r
       else\r
         BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);\r
-#if 0\r
-      /* Use black piece color for outline of white pieces */\r
-      /* Not sure this looks really good (though xboard does it).\r
-        Maybe better to have another selectable color, default black */\r
-      SelectObject(hdc, blackPieceBrush); /* could have own brush */\r
-      SelectObject(tmphdc, PieceBitmap(piece, OUTLINE_PIECE));\r
-      BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);\r
-#else\r
       /* Use black for outline of white pieces */\r
       SelectObject(tmphdc, PieceBitmap(piece, OUTLINE_PIECE));\r
       if(appData.upsideDown && color==flipView)\r
         StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, SRCAND);\r
       else\r
         BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, SRCAND);\r
-#endif\r
     } else {\r
-#if 0\r
-      /* Use white piece color for details of black pieces */\r
-      /* Requires filled-in solid bitmaps (BLACK_PIECE class); the\r
-        WHITE_PIECE ones aren't always the right shape. */\r
-      /* Not sure this looks really good (though xboard does it).\r
-        Maybe better to have another selectable color, default medium gray? */\r
-      oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, BLACK_PIECE));\r
-      oldBrush = SelectObject(hdc, whitePieceBrush); /* could have own brush */\r
-      BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);\r
-      SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE));\r
-      SelectObject(hdc, blackPieceBrush);\r
-      BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);\r
-#else\r
       /* Use square color for details of black pieces */\r
       oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE));\r
       oldBrush = SelectObject(hdc, blackPieceBrush);\r
@@ -3569,7 +2578,6 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y,
         StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, 0x00B8074A);\r
       else\r
         BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);\r
-#endif\r
     }\r
     SelectObject(hdc, oldBrush);\r
     SelectObject(tmphdc, oldBitmap);\r
@@ -3629,16 +2637,16 @@ VOID RebuildTextureSquareInfo()
             if( (col + row) & 1 ) {\r
                 /* Lite square */\r
                 if( lite_w >= squareSize && lite_h >= squareSize ) {\r
-                    backTextureSquareInfo[row][col].x = col * (lite_w - squareSize) / BOARD_WIDTH;\r
-                    backTextureSquareInfo[row][col].y = row * (lite_h - squareSize) / BOARD_HEIGHT;\r
+                    backTextureSquareInfo[row][col].x = col * (lite_w - squareSize) / (BOARD_WIDTH-1);  /* [HGM] divide by size-1 in stead of size! */\r
+                    backTextureSquareInfo[row][col].y = (BOARD_HEIGHT-1-row) * (lite_h - squareSize) / (BOARD_HEIGHT-1);\r
                     backTextureSquareInfo[row][col].mode = GetBackTextureMode(liteBackTextureMode);\r
                 }\r
             }\r
             else {\r
                 /* Dark square */\r
                 if( dark_w >= squareSize && dark_h >= squareSize ) {\r
-                    backTextureSquareInfo[row][col].x = col * (dark_w - squareSize) / BOARD_WIDTH;\r
-                    backTextureSquareInfo[row][col].y = row * (dark_h - squareSize) / BOARD_HEIGHT;\r
+                    backTextureSquareInfo[row][col].x = col * (dark_w - squareSize) / (BOARD_WIDTH-1);\r
+                    backTextureSquareInfo[row][col].y = (BOARD_HEIGHT-1-row) * (dark_h - squareSize) / (BOARD_HEIGHT-1);\r
                     backTextureSquareInfo[row][col].mode = GetBackTextureMode(darkBackTextureMode);\r
                 }\r
             }\r
@@ -3927,7 +2935,7 @@ BOOL DrawPositionNeedsFullRepaint()
         but animation is fast enough that it's difficult to notice.\r
     */\r
     if( animInfo.piece == EmptySquare ) {\r
-        if( (appData.highlightLastMove || appData.highlightDragging) && IsDrawArrowEnabled() && HasHighlightInfo() ) {\r
+        if( (appData.highlightLastMove || appData.highlightDragging) && IsDrawArrowEnabled() /*&& HasHighlightInfo()*/ ) {\r
             result = TRUE;\r
         }\r
     }\r
@@ -3945,7 +2953,10 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc)
 \r
   /* [AS] Initialize background textures if needed */\r
   if( liteBackTexture != NULL || darkBackTexture != NULL ) {\r
-      if( backTextureSquareSize != squareSize ) {\r
+      static int backTextureBoardSize; /* [HGM] boardsize: also new texture if board format changed */\r
+      if( backTextureSquareSize != squareSize \r
+       || backTextureBoardSize != BOARD_WIDTH+BOARD_FILES*BOARD_HEIGHT) {\r
+         backTextureBoardSize = BOARD_WIDTH+BOARD_FILES*BOARD_HEIGHT;\r
           backTextureSquareSize = squareSize;\r
           RebuildTextureSquareInfo();\r
       }\r
@@ -3961,7 +2972,7 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc)
       piece = board[row][column];\r
 \r
       square_color = ((column + row) % 2) == 1;\r
-      if(!strcmp(appData.variant, "xiangqi") ) {\r
+      if( gameInfo.variant == VariantXiangqi ) {\r
           square_color = !InPalace(row, column);\r
           if(BOARD_HEIGHT&1) { if(row==BOARD_HEIGHT/2) square_color ^= 1; }\r
           else if(row < BOARD_HEIGHT/2) square_color ^= 1;\r
@@ -3987,9 +2998,9 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc)
             }\r
       }\r
       if(column == BOARD_LEFT-1 ) /* left align */\r
-            DisplayHoldingsCount(hdc, x, y, 0, (int) board[row][column]);\r
+            DisplayHoldingsCount(hdc, x, y, flipView, (int) board[row][column]);\r
       else if( column == BOARD_RGHT) /* right align */\r
-            DisplayHoldingsCount(hdc, x, y, 1, (int) board[row][column]);\r
+            DisplayHoldingsCount(hdc, x, y, !flipView, (int) board[row][column]);\r
       else\r
       if (appData.monoMode) {\r
         if (piece == EmptySquare) {\r
@@ -4002,14 +3013,16 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc)
       else if( backTextureSquareInfo[row][column].mode > 0 ) {\r
           /* [AS] Draw the square using a texture bitmap */\r
           HBITMAP hbm = SelectObject( texture_hdc, square_color ? liteBackTexture : darkBackTexture );\r
+         int r = row, c = column; // [HGM] do not flip board in flipView\r
+         if(flipView) { r = BOARD_HEIGHT-1 - r; c = BOARD_WIDTH-1 - c; }\r
 \r
           DrawTile( x, y, \r
               squareSize, squareSize, \r
               hdc, \r
               texture_hdc,\r
-              backTextureSquareInfo[row][column].mode,\r
-              backTextureSquareInfo[row][column].x,\r
-              backTextureSquareInfo[row][column].y );\r
+              backTextureSquareInfo[r][c].mode,\r
+              backTextureSquareInfo[r][c].x,\r
+              backTextureSquareInfo[r][c].y );\r
 \r
           SelectObject( texture_hdc, hbm );\r
 \r
@@ -4046,6 +3059,88 @@ void fputDW(FILE *f, int x)
 #define MAX_CLIPS 200   /* more than enough */\r
 \r
 VOID\r
+DrawLogoOnDC(HDC hdc, RECT logoRect, HBITMAP logo)\r
+{\r
+//  HBITMAP bufferBitmap;\r
+  BITMAP bi;\r
+//  RECT Rect;\r
+  HDC tmphdc;\r
+  HBITMAP hbm;\r
+  int w = 100, h = 50;\r
+\r
+  if(logo == NULL) return;\r
+//  GetClientRect(hwndMain, &Rect);\r
+//  bufferBitmap = CreateCompatibleBitmap(hdc, Rect.right-Rect.left+1,\r
+//                                     Rect.bottom-Rect.top+1);\r
+  tmphdc = CreateCompatibleDC(hdc);\r
+  hbm = SelectObject(tmphdc, logo);\r
+  if( GetObject( logo, sizeof(bi), &bi ) > 0 ) {\r
+            w = bi.bmWidth;\r
+            h = bi.bmHeight;\r
+  }\r
+  StretchBlt(hdc, logoRect.left, logoRect.top, logoRect.right - logoRect.left, \r
+                  logoRect.bottom - logoRect.top, tmphdc, 0, 0, w, h, SRCCOPY);\r
+  SelectObject(tmphdc, hbm);\r
+  DeleteDC(tmphdc);\r
+}\r
+\r
+static HDC hdcSeek;\r
+\r
+// [HGM] seekgraph\r
+void DrawSeekAxis( int x, int y, int xTo, int yTo )\r
+{\r
+    POINT stPt;\r
+    HPEN hp = SelectObject( hdcSeek, gridPen );\r
+    MoveToEx( hdcSeek, boardRect.left+x, boardRect.top+y, &stPt );\r
+    LineTo( hdcSeek, boardRect.left+xTo, boardRect.top+yTo );\r
+    SelectObject( hdcSeek, hp );\r
+}\r
+\r
+// front-end wrapper for drawing functions to do rectangles\r
+void DrawSeekBackground( int left, int top, int right, int bottom )\r
+{\r
+    HPEN hp;\r
+    RECT rc;\r
+\r
+    if (hdcSeek == NULL) {\r
+    hdcSeek = GetDC(hwndMain);\r
+      if (!appData.monoMode) {\r
+        SelectPalette(hdcSeek, hPal, FALSE);\r
+        RealizePalette(hdcSeek);\r
+      }\r
+    }\r
+    hp = SelectObject( hdcSeek, gridPen );\r
+    rc.top = boardRect.top+top; rc.left = boardRect.left+left; \r
+    rc.bottom = boardRect.top+bottom; rc.right = boardRect.left+right;\r
+    FillRect( hdcSeek, &rc, lightSquareBrush );\r
+    SelectObject( hdcSeek, hp );\r
+}\r
+\r
+// front-end wrapper for putting text in graph\r
+void DrawSeekText(char *buf, int x, int y)\r
+{\r
+        SIZE stSize;\r
+       SetBkMode( hdcSeek, TRANSPARENT );\r
+        GetTextExtentPoint32( hdcSeek, buf, strlen(buf), &stSize );\r
+        TextOut( hdcSeek, boardRect.left+x-3, boardRect.top+y-stSize.cy/2, buf, strlen(buf) );\r
+}\r
+\r
+void DrawSeekDot(int x, int y, int color)\r
+{\r
+       int square = color & 0x80;\r
+       color &= 0x7F;\r
+           HBRUSH oldBrush = SelectObject(hdcSeek, \r
+                       color == 0 ? markerBrush : color == 1 ? darkSquareBrush : explodeBrush);\r
+       if(square)\r
+           Rectangle(hdcSeek, boardRect.left+x - squareSize/9, boardRect.top+y - squareSize/9,\r
+                              boardRect.left+x + squareSize/9, boardRect.top+y + squareSize/9);\r
+       else\r
+           Ellipse(hdcSeek, boardRect.left+x - squareSize/8, boardRect.top+y - squareSize/8,\r
+                            boardRect.left+x + squareSize/8, boardRect.top+y + squareSize/8);\r
+           SelectObject(hdcSeek, oldBrush);\r
+}\r
+\r
+VOID\r
 HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)\r
 {\r
   static Board lastReq, lastDrawn;\r
@@ -4071,21 +3166,12 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
    */\r
   Boolean fullrepaint = repaint;\r
 \r
+  if(DrawSeekGraph()) return; // [HG} seekgraph: suppress printing board if seek graph up\r
+\r
   if( DrawPositionNeedsFullRepaint() ) {\r
       fullrepaint = TRUE;\r
   }\r
 \r
-#if 0\r
-  if( fullrepaint ) {\r
-      static int repaint_count = 0;\r
-      char buf[128];\r
-\r
-      repaint_count++;\r
-      sprintf( buf, "FULL repaint: %d\n", repaint_count );\r
-      OutputDebugString( buf );\r
-  }\r
-#endif\r
-\r
   if (board == NULL) {\r
     if (!lastReqValid) {\r
       return;\r
@@ -4115,35 +3201,6 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
     releaseDC = FALSE;\r
   }\r
 \r
-#if 0\r
-  fprintf(debugFP, "*******************************\n"\r
-                   "repaint = %s\n"\r
-                   "dragInfo.from (%d,%d)\n"\r
-                   "dragInfo.start (%d,%d)\n"\r
-                   "dragInfo.pos (%d,%d)\n"\r
-                   "dragInfo.lastpos (%d,%d)\n", \r
-                    repaint ? "TRUE" : "FALSE",\r
-                    dragInfo.from.x, dragInfo.from.y, \r
-                    dragInfo.start.x, dragInfo.start.y,\r
-                    dragInfo.pos.x, dragInfo.pos.y,\r
-                    dragInfo.lastpos.x, dragInfo.lastpos.y);\r
-  fprintf(debugFP, "prev:  ");\r
-  for (row = 0; row < BOARD_HEIGHT; row++) {\r
-    for (column = 0; column < BOARD_WIDTH; column++) {\r
-      fprintf(debugFP, "%d ", lastDrawn[row][column]);\r
-    }\r
-  }\r
-  fprintf(debugFP, "\n");\r
-  fprintf(debugFP, "board: ");\r
-  for (row = 0; row < BOARD_HEIGHT; row++) {\r
-    for (column = 0; column < BOARD_WIDTH; column++) {\r
-      fprintf(debugFP, "%d ", board[row][column]);\r
-    }\r
-  }\r
-  fprintf(debugFP, "\n");\r
-  fflush(debugFP);\r
-#endif\r
-\r
   /* Create some work-DCs */\r
   hdcmem = CreateCompatibleDC(hdc);\r
   tmphdc = CreateCompatibleDC(hdc);\r
@@ -4276,7 +3333,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
         atomic, where the piece moves to an empty square and then\r
         explodes.  The old and new positions both had an empty square\r
         at the destination, but animation has drawn a piece there and\r
-        we have to remember to erase it. */\r
+        we have to remember to erase it. [HGM] moved until after setting lastDrawn */\r
       lastDrawn[animInfo.to.y][animInfo.to.x] = animInfo.piece;\r
     }\r
   }\r
@@ -4295,9 +3352,75 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
   }\r
 \r
   /* Do all the drawing to the memory DC */\r
-  DrawGridOnDC(hdcmem);\r
-  DrawHighlightsOnDC(hdcmem);\r
-  DrawBoardOnDC(hdcmem, board, tmphdc);\r
+  if(explodeInfo.radius) { // [HGM] atomic\r
+       HBRUSH oldBrush;\r
+       int x, y, r=(explodeInfo.radius * squareSize)/100;\r
+        board[explodeInfo.fromY][explodeInfo.fromX] = EmptySquare; // suppress display of capturer\r
+       SquareToPos(explodeInfo.toY, explodeInfo.toX, &x, &y);\r
+       x += squareSize/2;\r
+       y += squareSize/2;\r
+        if(!fullrepaint) {\r
+         clips[num_clips] = CreateRectRgn(x-r, y-r, x+r, y+r);\r
+         ExtSelectClipRgn(hdcmem, clips[num_clips++], RGN_OR);\r
+       }\r
+       DrawGridOnDC(hdcmem);\r
+       DrawHighlightsOnDC(hdcmem);\r
+       DrawBoardOnDC(hdcmem, board, tmphdc);\r
+       oldBrush = SelectObject(hdcmem, explodeBrush);\r
+       Ellipse(hdcmem, x-r, y-r, x+r, y+r);\r
+       SelectObject(hdcmem, oldBrush);\r
+  } else {\r
+    DrawGridOnDC(hdcmem);\r
+    DrawHighlightsOnDC(hdcmem);\r
+    DrawBoardOnDC(hdcmem, board, tmphdc);\r
+  }\r
+  for (row = 0; row < BOARD_HEIGHT; row++) {\r
+    for (column = 0; column < BOARD_WIDTH; column++) {\r
+       if (marker[row][column]) { // marker changes only occur with full repaint!\r
+           HBRUSH oldBrush = SelectObject(hdcmem, \r
+                       marker[row][column] == 2 ? markerBrush : explodeBrush);\r
+           SquareToPos(row, column, &x, &y);\r
+           Ellipse(hdcmem, x + squareSize/4, y + squareSize/4,\r
+                         x + 3*squareSize/4, y + 3*squareSize/4);\r
+           SelectObject(hdcmem, oldBrush);\r
+       }\r
+    }\r
+  }\r
+  if(logoHeight) {\r
+       HBITMAP whiteLogo = (HBITMAP) first.programLogo, blackLogo = (HBITMAP) second.programLogo;\r
+       if(appData.autoLogo) {\r
+         \r
+         switch(gameMode) { // pick logos based on game mode\r
+           case IcsObserving:\r
+               whiteLogo = second.programLogo; // ICS logo\r
+               blackLogo = second.programLogo;\r
+           default:\r
+               break;\r
+           case IcsPlayingWhite:\r
+               if(!appData.zippyPlay) whiteLogo = userLogo;\r
+               blackLogo = second.programLogo; // ICS logo\r
+               break;\r
+           case IcsPlayingBlack:\r
+               whiteLogo = second.programLogo; // ICS logo\r
+               blackLogo = appData.zippyPlay ? first.programLogo : userLogo;\r
+               break;\r
+           case TwoMachinesPlay:\r
+               if(first.twoMachinesColor[0] == 'b') {\r
+                   whiteLogo = second.programLogo;\r
+                   blackLogo = first.programLogo;\r
+               }\r
+               break;\r
+           case MachinePlaysWhite:\r
+               blackLogo = userLogo;\r
+               break;\r
+           case MachinePlaysBlack:\r
+               whiteLogo = userLogo;\r
+               blackLogo = first.programLogo;\r
+         }\r
+       }\r
+       DrawLogoOnDC(hdc, leftLogoRect, flipClock ? blackLogo : whiteLogo);\r
+       DrawLogoOnDC(hdc, rightLogoRect, flipClock ? whiteLogo : blackLogo);\r
+  }\r
 \r
   if( appData.highlightMoveWithArrow ) {\r
     DrawArrowHighlight(hdcmem);\r
@@ -4357,9 +3480,8 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
         boardRect.right - boardRect.left,\r
         boardRect.bottom - boardRect.top,\r
         tmphdc, boardRect.left, boardRect.top, SRCCOPY);\r
-\r
   if(saveDiagFlag) { \r
-    BITMAP b; int i, j, m, w, wb, fac=0; char pData[1000000]; \r
+    BITMAP b; int i, j=0, m, w, wb, fac=0; char pData[1000000]; \r
     BITMAPINFOHEADER bih; int color[16], nrColors=0;\r
 \r
     GetObject(bufferBitmap, sizeof(b), &b);\r
@@ -4380,7 +3502,6 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
        GetDIBits(tmphdc,bufferBitmap,0,b.bmHeight,pData,(BITMAPINFO*)&bih,DIB_RGB_COLORS);\r
 //     fprintf(diagFile, "%8x\n", (int) pData);\r
 \r
-#if 1\r
        wb = b.bmWidthBytes;\r
        // count colors\r
        for(i=0; i<wb*(b.bmHeight - boardRect.top + OUTER_MARGIN)>>2; i++) {\r
@@ -4403,7 +3524,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
                    while(p&3) pData[p++] = 0;\r
                }\r
                fac = 3;\r
-               wb = (wb+31>>5)<<2;\r
+               wb = ((wb+31)>>5)<<2;\r
        }\r
        // write BITMAPFILEHEADER\r
        fprintf(diagFile, "BM");\r
@@ -4428,7 +3549,6 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
        // write bitmap data\r
        for(i=0; i<wb*(b.bmHeight - boardRect.top + OUTER_MARGIN); i++) \r
                fputc(pData[i], diagFile);\r
-#endif\r
      }\r
   }\r
 \r
@@ -4463,9 +3583,6 @@ int
 SaveDiagram(f)\r
      FILE *f;\r
 {\r
-    time_t tm;\r
-    char *fen;\r
-\r
     saveDiagFlag = 1; diagFile = f;\r
     HDCDrawPosition(NULL, TRUE, NULL);\r
 \r
@@ -4490,7 +3607,7 @@ PaintProc(HWND hwnd)
   PAINTSTRUCT ps;\r
   HFONT       oldFont;\r
 \r
-  if(hdc = BeginPaint(hwnd, &ps)) {\r
+  if((hdc = BeginPaint(hwnd, &ps))) {\r
     if (IsIconic(hwnd)) {\r
       DrawIcon(hdc, 2, 2, iconCurrent);\r
     } else {\r
@@ -4520,8 +3637,8 @@ PaintProc(HWND hwnd)
  * The offset boardRect.left or boardRect.top must already have been\r
  *   subtracted from x.\r
  */\r
-int\r
-EventToSquare(int x)\r
+int EventToSquare(x, limit)\r
+     int x, limit;\r
 {\r
   if (x <= 0)\r
     return -2;\r
@@ -4531,7 +3648,7 @@ EventToSquare(int x)
   if ((x % (squareSize + lineGap)) >= squareSize)\r
     return -1;\r
   x /= (squareSize + lineGap);\r
-  if (x >= BOARD_SIZE)\r
+    if (x >= limit)\r
     return -2;\r
   return x;\r
 }\r
@@ -4573,21 +3690,33 @@ SetupDropMenu(HMENU hmenu)
   }\r
 }\r
 \r
-static int fromX = -1, fromY = -1, toX, toY;\r
+void DragPieceBegin(int x, int y)\r
+{\r
+      dragInfo.lastpos.x = boardRect.left + x;\r
+      dragInfo.lastpos.y = boardRect.top + y;\r
+      dragInfo.from.x = fromX;\r
+      dragInfo.from.y = fromY;\r
+      dragInfo.start = dragInfo.from;\r
+      SetCapture(hwndMain);\r
+}\r
+\r
+void DragPieceEnd(int x, int y)\r
+{\r
+    ReleaseCapture();\r
+    dragInfo.start.x = dragInfo.start.y = -1;\r
+    dragInfo.from = dragInfo.start;\r
+    dragInfo.pos = dragInfo.lastpos = dragInfo.start;\r
+}\r
 \r
 /* Event handler for mouse messages */\r
 VOID\r
 MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
 {\r
-  int x, y;\r
+  int x, y, menuNr;\r
   POINT pt;\r
   static int recursive = 0;\r
   HMENU hmenu;\r
-  BOOLEAN needsRedraw = FALSE;\r
-  BOOLEAN saveAnimate;\r
   BOOLEAN forceFullRepaint = IsFullRepaintPreferrable(); /* [AS] */\r
-  static BOOLEAN sameAgain = FALSE;\r
-  ChessMove moveType;\r
 \r
   if (recursive) {\r
     if (message == WM_MBUTTONUP) {\r
@@ -4603,8 +3732,8 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
   \r
   pt.x = LOWORD(lParam);\r
   pt.y = HIWORD(lParam);\r
-  x = EventToSquare(pt.x - boardRect.left);\r
-  y = EventToSquare(pt.y - boardRect.top);\r
+  x = EventToSquare(pt.x - boardRect.left, BOARD_WIDTH);\r
+  y = EventToSquare(pt.y - boardRect.top, BOARD_HEIGHT);\r
   if (!flipView && y >= 0) {\r
     y = BOARD_HEIGHT - 1 - y;\r
   }\r
@@ -4614,10 +3743,6 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 \r
   switch (message) {\r
   case WM_LBUTTONDOWN:\r
-    ErrorPopDown();\r
-    sameAgain = FALSE;\r
-    if (y == -2) {\r
-      /* Downclick vertically off board; check if on clock */\r
       if (PtInRect((LPRECT) &whiteRect, pt)) {\r
         if (gameMode == EditPosition) {\r
          SetWhiteToPlayEvent();\r
@@ -4637,163 +3762,31 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
           AdjustClock(!flipClock, -1);\r
        }\r
       }\r
-      if (!appData.highlightLastMove) {\r
-        ClearHighlights();\r
-       DrawPosition(forceFullRepaint || FALSE, NULL);\r
-      }\r
-      fromX = fromY = -1;\r
-      dragInfo.start.x = dragInfo.start.y = -1;\r
-      dragInfo.from = dragInfo.start;\r
-      break;\r
-    } else if (x < 0 || y < 0\r
-      /* [HGM] block clicks between board and holdings */\r
-              || x == BOARD_LEFT-1 || x == BOARD_RGHT\r
-              || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize\r
-              || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize\r
-       /* EditPosition, empty square, or different color piece;\r
-          click-click move is possible */\r
-                               ) {\r
-      break;\r
-    } else if (fromX == x && fromY == y) {\r
-      /* Downclick on same square again */\r
-      ClearHighlights();\r
-      DrawPosition(forceFullRepaint || FALSE, NULL);\r
-      sameAgain = TRUE;  \r
-    } else if (fromX != -1 &&\r
-               x != BOARD_LEFT-2 && x != BOARD_RGHT+1 \r
-                                                                        ) {\r
-      /* Downclick on different square. */\r
-      /* [HGM] if on holdings file, should count as new first click ! */\r
-      { /* [HGM] <sameColor> now always do UserMoveTest(), and check colors there */\r
-       toX = x;\r
-       toY = y;\r
-        /* [HGM] <popupFix> UserMoveEvent requires two calls now,\r
-           to make sure move is legal before showing promotion popup */\r
-        moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR);\r
-        if(moveType != ImpossibleMove) {\r
-          /* [HGM] We use PromotionToKnight in Shogi to indicate frorced promotion */\r
-          if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||\r
-             (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&\r
-              appData.alwaysPromoteToQueen) {\r
-                  FinishMove(moveType, fromX, fromY, toX, toY, 'q');\r
-                  if (!appData.highlightLastMove) {\r
-                      ClearHighlights();\r
-                      DrawPosition(forceFullRepaint || FALSE, NULL);\r
-                  }\r
-          } else\r
-          if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {\r
-                  SetHighlights(fromX, fromY, toX, toY);\r
-                  DrawPosition(forceFullRepaint || FALSE, NULL);\r
-                  /* [HGM] <popupFix> Popup calls FinishMove now.\r
-                     If promotion to Q is legal, all are legal! */\r
-                  PromotionPopup(hwnd);\r
-          } else {       /* not a promotion */\r
-             if (appData.animate || appData.highlightLastMove) {\r
-                 SetHighlights(fromX, fromY, toX, toY);\r
-             } else {\r
-                 ClearHighlights();\r
-             }\r
-             FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);\r
-             if (appData.animate && !appData.highlightLastMove) {\r
-                  ClearHighlights();\r
-                  DrawPosition(forceFullRepaint || FALSE, NULL);\r
-             }\r
-          }\r
-          break;\r
-        }\r
-        if (gotPremove) {\r
-            /* [HGM] it seemed that braces were missing here */\r
-            SetPremoveHighlights(fromX, fromY, toX, toY);\r
-            fromX = fromY = -1;\r
-            break;\r
-        }\r
-      }\r
-      ClearHighlights();\r
-      DrawPosition(forceFullRepaint || FALSE, NULL);\r
-    }\r
-    /* First downclick, or restart on a square with same color piece */\r
-    if (!frozen && OKToStartUserMove(x, y)) {\r
-      fromX = x;\r
-      fromY = y;\r
-      dragInfo.lastpos = pt;\r
-      dragInfo.from.x = fromX;\r
-      dragInfo.from.y = fromY;\r
-      dragInfo.start = dragInfo.from;\r
-      SetCapture(hwndMain);\r
-    } else {\r
-      fromX = fromY = -1;\r
       dragInfo.start.x = dragInfo.start.y = -1;\r
       dragInfo.from = dragInfo.start;\r
+    if(fromX == -1 && frozen) { // not sure where this is for\r
+               fromX = fromY = -1; \r
       DrawPosition(forceFullRepaint || FALSE, NULL); /* [AS] */\r
+      break;\r
     }\r
+      LeftClick(Press, pt.x - boardRect.left, pt.y - boardRect.top);\r
+      DrawPosition(TRUE, NULL);\r
     break;\r
 \r
   case WM_LBUTTONUP:\r
-    ReleaseCapture();\r
-    if (fromX == -1) break;\r
-    if (x == fromX && y == fromY) {\r
-      dragInfo.from.x = dragInfo.from.y = -1;\r
-      /* Upclick on same square */\r
-      if (sameAgain) {\r
-       /* Clicked same square twice: abort click-click move */\r
-       fromX = fromY = -1;\r
-       gotPremove = 0;\r
-       ClearPremoveHighlights();\r
-      } else {\r
-       /* First square clicked: start click-click move */\r
-       SetHighlights(fromX, fromY, -1, -1);\r
-      }\r
-      DrawPosition(forceFullRepaint || FALSE, NULL);\r
-    } else if (dragInfo.from.x < 0 || dragInfo.from.y < 0) {\r
-      /* Errant click; ignore */\r
-      break;\r
-    } else {\r
-      /* Finish drag move. */\r
-    if (appData.debugMode) {\r
-        fprintf(debugFP, "release\n");\r
-    }\r
-      dragInfo.from.x = dragInfo.from.y = -1;\r
-      toX = x;\r
-      toY = y;\r
-      saveAnimate = appData.animate; /* sorry, Hawk :) */\r
-      appData.animate = appData.animate && !appData.animateDragging;\r
-      moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR);\r
-      if(moveType != ImpossibleMove) {\r
-          /* [HGM] use move type to determine if move is promotion.\r
-             Knight is Shogi kludge for mandatory promotion, Queen means choice */\r
-          if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||\r
-             (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&\r
-              appData.alwaysPromoteToQueen) \r
-               FinishMove(moveType, fromX, fromY, toX, toY, 'q');\r
-          else \r
-          if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {\r
-               DrawPosition(forceFullRepaint || FALSE, NULL);\r
-               PromotionPopup(hwnd); /* [HGM] Popup now calls FinishMove */\r
-        } else FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);\r
-      }\r
-      if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);\r
-      appData.animate = saveAnimate;\r
-      fromX = fromY = -1;\r
-      if (appData.highlightDragging && !appData.highlightLastMove) {\r
-       ClearHighlights();\r
-      }\r
-      if (appData.animate || appData.animateDragging ||\r
-         appData.highlightDragging || gotPremove) {\r
-       DrawPosition(forceFullRepaint || FALSE, NULL);\r
-      }\r
-    }\r
-    dragInfo.start.x = dragInfo.start.y = -1; \r
-    dragInfo.pos = dragInfo.lastpos = dragInfo.start;\r
+      LeftClick(Release, pt.x - boardRect.left, pt.y - boardRect.top);\r
+      DrawPosition(TRUE, NULL);\r
     break;\r
 \r
   case WM_MOUSEMOVE:\r
+    if(SeekGraphClick(Press, pt.x - boardRect.left, pt.y - boardRect.top, 1)) break;\r
+    MovePV(pt.x - boardRect.left, pt.y - boardRect.top, boardRect.bottom - boardRect.top);\r
     if ((appData.animateDragging || appData.highlightDragging)\r
        && (wParam & MK_LBUTTON)\r
        && dragInfo.from.x >= 0) \r
     {\r
       BOOL full_repaint = FALSE;\r
 \r
-      sameAgain = FALSE; /* [HGM] if we drag something around, do keep square selected */\r
       if (appData.animateDragging) {\r
        dragInfo.pos = pt;\r
       }\r
@@ -4810,6 +3803,27 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     }\r
     break;\r
 \r
+  case WM_MOUSEWHEEL: // [DM]\r
+    {  static int lastDir = 0; // [HGM] build in some hysteresis to avoid spurious events\r
+       /* Mouse Wheel is being rolled forward\r
+        * Play moves forward\r
+        */\r
+       if((short)HIWORD(wParam) > 0 && currentMove < forwardMostMove) \r
+               { if(lastDir == 1) ForwardEvent(); else lastDir = 1; } // [HGM] suppress first event in direction\r
+       /* Mouse Wheel is being rolled backward\r
+        * Play moves backward\r
+        */\r
+       if((short)HIWORD(wParam) < 0 && currentMove > backwardMostMove) \r
+               { if(lastDir == -1) BackwardEvent(); else lastDir = -1; }\r
+    }\r
+    break;\r
+\r
+  case WM_MBUTTONUP:\r
+  case WM_RBUTTONUP:\r
+    ReleaseCapture();\r
+    RightClick(Release, pt.x - boardRect.left, pt.y - boardRect.top, &fromX, &fromY);\r
+    break;\r
\r
   case WM_MBUTTONDOWN:\r
   case WM_RBUTTONDOWN:\r
     ErrorPopDown();\r
@@ -4832,12 +3846,9 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     }\r
     DrawPosition(TRUE, NULL);\r
 \r
-    switch (gameMode) {\r
-    case EditPosition:\r
-    case IcsExamining:\r
-      if (x < 0 || y < 0) break;\r
-      fromX = x;\r
-      fromY = y;\r
+    menuNr = RightClick(Press, pt.x - boardRect.left, pt.y - boardRect.top, &fromX, &fromY);\r
+    switch (menuNr) {\r
+    case 0:\r
       if (message == WM_MBUTTONDOWN) {\r
        buttonCount = 3;  /* even if system didn't think so */\r
        if (wParam & MK_SHIFT) \r
@@ -4845,16 +3856,6 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        else\r
          MenuPopup(hwnd, pt, LoadMenu(hInst, "WhitePieceMenu"), -1);\r
       } else { /* message == WM_RBUTTONDOWN */\r
-#if 0\r
-       if (buttonCount == 3) {\r
-         if (wParam & MK_SHIFT) \r
-           MenuPopup(hwnd, pt, LoadMenu(hInst, "WhitePieceMenu"), -1);\r
-         else\r
-           MenuPopup(hwnd, pt, LoadMenu(hInst, "BlackPieceMenu"), -1);\r
-       } else {\r
-         MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1);\r
-       }\r
-#else\r
        /* Just have one menu, on the right button.  Windows users don't\r
           think to try the middle one, and sometimes other software steals\r
           it, or it doesn't really exist. */\r
@@ -4862,24 +3863,15 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
             MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1);\r
         else\r
             MenuPopup(hwnd, pt, LoadMenu(hInst, "ShogiPieceMenu"), -1);\r
-#endif\r
       }\r
       break;\r
-    case IcsPlayingWhite:\r
-    case IcsPlayingBlack:\r
-    case EditGame:\r
-    case MachinePlaysWhite:\r
-    case MachinePlaysBlack:\r
-      if (appData.testLegality &&\r
-         gameInfo.variant != VariantBughouse &&\r
-         gameInfo.variant != VariantCrazyhouse) break;\r
-      if (x < 0 || y < 0) break;\r
-      fromX = x;\r
-      fromY = y;\r
+    case 2:\r
+      SetCapture(hwndMain);
+      break;\r
+    case 1:\r
       hmenu = LoadMenu(hInst, "DropPieceMenu");\r
       SetupDropMenu(hmenu);\r
       MenuPopup(hwnd, pt, hmenu, -1);\r
-      break;\r
     default:\r
       break;\r
     }\r
@@ -4915,24 +3907,9 @@ ButtonProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     case '\r':\r
       SendMessage(hwndMain, WM_COMMAND, MAKEWPARAM(buttonDesc[i].id, 0), 0);\r
       return TRUE;\r
-    case '\t':\r
-      if (appData.icsActive) {\r
-       if (GetKeyState(VK_SHIFT) < 0) {\r
-         /* shifted */\r
-         HWND h = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
-         if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
-         SetFocus(h);\r
-       } else {\r
-         /* unshifted */\r
-         HWND h = GetDlgItem(hwndConsole, OPT_ConsoleText);\r
-         if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
-         SetFocus(h);\r
-       }\r
-       return TRUE;\r
-      }\r
-      break;\r
     default:\r
-      if (appData.icsActive) {\r
+      if (appData.icsActive && (isalpha((char)wParam) || wParam == '0')) {\r
+       // [HGM] movenum: only letters or leading zero should go to ICS input\r
         HWND h = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
        if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
        SetFocus(h);\r
@@ -4960,20 +3937,20 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
     CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER));\r
     ShowWindow(GetDlgItem(hDlg, PB_King), \r
       (!appData.testLegality || gameInfo.variant == VariantSuicide ||\r
-       gameInfo.variant == VariantGiveaway) ?\r
+       gameInfo.variant == VariantGiveaway || gameInfo.variant == VariantSuper ) ?\r
               SW_SHOW : SW_HIDE);\r
     /* [HGM] Only allow C & A promotions if these pieces are defined */\r
     ShowWindow(GetDlgItem(hDlg, PB_Archbishop),\r
-       (PieceToChar(WhiteAngel) >= 'A' &&\r
-        PieceToChar(WhiteAngel) != '~' ||\r
-        PieceToChar(BlackAngel) >= 'A' &&\r
-        PieceToChar(BlackAngel) != '~'   ) ?\r
+       ((PieceToChar(WhiteAngel) >= 'A' &&\r
+         PieceToChar(WhiteAngel) != '~') ||\r
+        (PieceToChar(BlackAngel) >= 'A' &&\r
+         PieceToChar(BlackAngel) != '~')   ) ?\r
               SW_SHOW : SW_HIDE);\r
     ShowWindow(GetDlgItem(hDlg, PB_Chancellor), \r
-       (PieceToChar(WhiteMarshall) >= 'A' &&\r
-        PieceToChar(WhiteMarshall) != '~' ||\r
-        PieceToChar(BlackMarshall) >= 'A' &&\r
-        PieceToChar(BlackMarshall) != '~'   ) ?\r
+       ((PieceToChar(WhiteMarshall) >= 'A' &&\r
+         PieceToChar(WhiteMarshall) != '~') ||\r
+        (PieceToChar(BlackMarshall) >= 'A' &&\r
+         PieceToChar(BlackMarshall) != '~')   ) ?\r
               SW_SHOW : SW_HIDE);\r
     /* [HGM] Hide B & R button in Shogi, use Q as promote, N as defer */\r
     ShowWindow(GetDlgItem(hDlg, PB_Rook),\r
@@ -4988,6 +3965,9 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
     ShowWindow(GetDlgItem(hDlg, IDC_No), \r
        gameInfo.variant == VariantShogi ?\r
               SW_SHOW : SW_HIDE);\r
+    ShowWindow(GetDlgItem(hDlg, IDC_Centaur), \r
+       gameInfo.variant == VariantSuper ?\r
+              SW_SHOW : SW_HIDE);\r
     return TRUE;\r
 \r
   case WM_COMMAND: /* message: received a command */\r
@@ -4998,7 +3978,7 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
       DrawPosition(FALSE, NULL);\r
       return TRUE;\r
     case PB_King:\r
-      promoChar = PieceToChar(BlackKing);\r
+      promoChar = gameInfo.variant == VariantSuper ? PieceToChar(BlackSilver) : PieceToChar(BlackKing);\r
       break;\r
     case PB_Queen:\r
       promoChar = gameInfo.variant == VariantShogi ? '+' : PieceToChar(BlackQueen);\r
@@ -5026,7 +4006,8 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
        only show the popup when we are already sure the move is valid or\r
        legal. We pass a faulty move type, but the kludge is that FinishMove\r
        will figure out it is a promotion from the promoChar. */\r
-    FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);\r
+    UserMoveEvent(fromX, fromY, toX, toY, promoChar);\r
+    fromX = fromY = -1;\r
     if (!appData.highlightLastMove) {\r
       ClearHighlights();\r
       DrawPosition(FALSE, NULL);\r
@@ -5048,11 +4029,19 @@ PromotionPopup(HWND hwnd)
   FreeProcInstance(lpProc);\r
 }\r
 \r
+void\r
+PromotionPopUp()\r
+{\r
+  DrawPosition(TRUE, NULL);\r
+  PromotionPopup(hwndMain);\r
+}\r
+\r
 /* Toggle ShowThinking */\r
 VOID\r
 ToggleShowThinking()\r
 {\r
-  ShowThinkingEvent(!appData.showThinking);\r
+  appData.showThinking = !appData.showThinking;\r
+  ShowThinkingEvent();\r
 }\r
 \r
 VOID\r
@@ -5083,6 +4072,57 @@ LoadGameDialog(HWND hwnd, char* title)
   }\r
 }\r
 \r
+int get_term_width()\r
+{\r
+    HDC hdc;\r
+    TEXTMETRIC tm;\r
+    RECT rc;\r
+    HFONT hfont, hold_font;\r
+    LOGFONT lf;\r
+    HWND hText;\r
+\r
+    if (hwndConsole)\r
+        hText = GetDlgItem(hwndConsole, OPT_ConsoleText);\r
+    else\r
+        return 79;\r
+\r
+    // get the text metrics\r
+    hdc = GetDC(hText);\r
+    lf = font[boardSize][CONSOLE_FONT]->lf;\r
+    if (consoleCF.dwEffects & CFE_BOLD)\r
+        lf.lfWeight = FW_BOLD;\r
+    if (consoleCF.dwEffects & CFE_ITALIC)\r
+        lf.lfItalic = TRUE;\r
+    if (consoleCF.dwEffects & CFE_STRIKEOUT)\r
+        lf.lfStrikeOut = TRUE;\r
+    if (consoleCF.dwEffects & CFE_UNDERLINE)\r
+        lf.lfUnderline = TRUE;\r
+    hfont = CreateFontIndirect(&lf);\r
+    hold_font = SelectObject(hdc, hfont);\r
+    GetTextMetrics(hdc, &tm);\r
+    SelectObject(hdc, hold_font);\r
+    DeleteObject(hfont);\r
+    ReleaseDC(hText, hdc);\r
+\r
+    // get the rectangle\r
+    SendMessage(hText, EM_GETRECT, 0, (LPARAM)&rc);\r
+\r
+    return (rc.right-rc.left) / tm.tmAveCharWidth;\r
+}\r
+\r
+void UpdateICSWidth(HWND hText)\r
+{\r
+    LONG old_width, new_width;\r
+\r
+    new_width = get_term_width(hText, FALSE);\r
+    old_width = GetWindowLong(hText, GWL_USERDATA);\r
+    if (new_width != old_width)\r
+    {\r
+        ics_update_width(new_width);\r
+        SetWindowLong(hText, GWL_USERDATA, new_width);\r
+    }\r
+}\r
+\r
 VOID\r
 ChangedConsoleFont()\r
 {\r
@@ -5122,6 +4162,7 @@ ChangedConsoleFont()
   paraf.dxOffset = WRAP_INDENT;\r
   SendMessage(hText, EM_SETPARAFORMAT, 0, (LPARAM) &paraf);\r
   SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&sel);\r
+  UpdateICSWidth(hText);\r
 }\r
 \r
 /*---------------------------------------------------------------------------*\\r
@@ -5140,6 +4181,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
   FILE *f;\r
   UINT number;\r
   char fileTitle[MSG_SIZ];\r
+  char buf[MSG_SIZ];\r
   static SnapData sd;\r
 \r
   switch (message) {\r
@@ -5164,33 +4206,29 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
   case WM_MBUTTONUP:\r
   case WM_RBUTTONUP:\r
   case WM_MOUSEMOVE:\r
+  case WM_MOUSEWHEEL:\r
     MouseEvent(hwnd, message, wParam, lParam);\r
     break;\r
 \r
+  JAWS_KB_NAVIGATION\r
+\r
   case WM_CHAR:\r
     \r
-    if (appData.icsActive) {\r
-      if (wParam == '\t') {\r
-       if (GetKeyState(VK_SHIFT) < 0) {\r
-         /* shifted */\r
-         HWND h = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
-         if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
-         SetFocus(h);\r
-       } else {\r
-         /* unshifted */\r
-         HWND h = GetDlgItem(hwndConsole, OPT_ConsoleText);\r
-         if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
-         SetFocus(h);\r
-       }\r
-      } else {\r
+    JAWS_ALT_INTERCEPT\r
+\r
+    if (appData.icsActive && ((char)wParam == '\r' || (char)wParam > ' ' && !((char)wParam >= '1' && (char)wParam <= '9'))) { \r
+       // [HGM] movenum: for non-zero digits we always do type-in dialog\r
        HWND h = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
        if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
        SetFocus(h);\r
        SendMessage(h, message, wParam, lParam);\r
-      }\r
-    } else if (isalpha((char)wParam) || isdigit((char)wParam)) {\r
-      PopUpMoveDialog((char)wParam);\r
+    } else if(lParam != KF_REPEAT) {\r
+       if (isalpha((char)wParam) || isdigit((char)wParam)) {\r
+               PopUpMoveDialog((char)wParam);\r
+       } else if((char)wParam == 003) CopyGameToClipboard();\r
+        else if((char)wParam == 026) PasteGameOrFENFromClipboard();\r
     }\r
+\r
     break;\r
 \r
   case WM_PALETTECHANGED:\r
@@ -5201,11 +4239,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       nnew = RealizePalette(hdc);\r
       if (nnew > 0) {\r
        paletteChanged = TRUE;\r
-#if 0\r
-        UpdateColors(hdc);\r
-#else\r
-        InvalidateRect(hwnd, &boardRect, FALSE);/*faster!*/\r
-#endif\r
+        InvalidateRect(hwnd, &boardRect, FALSE);\r
       }\r
       ReleaseDC(hwnd, hdc);\r
     }\r
@@ -5233,13 +4267,12 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     switch (wmId) {\r
     case IDM_NewGame:\r
       ResetGameEvent();\r
-      AnalysisPopDown();\r
+      SAY("new game enter a move to play against the computer with white");\r
       break;\r
 \r
     case IDM_NewGameFRC:\r
       if( NewGameFRC() == 0 ) {\r
         ResetGameEvent();\r
-        AnalysisPopDown();\r
       }\r
       break;\r
 \r
@@ -5356,6 +4389,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
         }\r
         else {\r
             EvalGraphPopUp();\r
+           SetFocus(hwndMain);\r
         }\r
         break;\r
 \r
@@ -5387,6 +4421,10 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       GameListOptions();\r
       break;\r
 \r
+    case IDM_NewChat:\r
+      ChatPopUp(NULL);\r
+      break;\r
+\r
     case IDM_CopyPosition:\r
       CopyFENToClipboard();\r
       break;\r
@@ -5423,6 +4461,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
          TagsPopUp(tags, CmailMsg());\r
          free(tags);\r
       }\r
+      SAY("computer starts playing white");\r
       break;\r
 \r
     case IDM_MachineBlack:\r
@@ -5436,6 +4475,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
          TagsPopUp(tags, CmailMsg());\r
          free(tags);\r
       }\r
+      SAY("computer starts playing black");\r
       break;\r
 \r
     case IDM_TwoMachines:\r
@@ -5449,14 +4489,40 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
          TagsPopUp(tags, CmailMsg());\r
          free(tags);\r
       }\r
+      SAY("programs start playing each other");\r
       break;\r
 \r
     case IDM_AnalysisMode:\r
       if (!first.analysisSupport) {\r
-        char buf[MSG_SIZ];\r
         sprintf(buf, "%s does not support analysis", first.tidy);\r
         DisplayError(buf, 0);\r
       } else {\r
+       SAY("analyzing current position");\r
+        /* [DM] icsEngineAnlyze [HGM] Why is this front-end??? */\r
+        if (appData.icsActive) {\r
+               if (gameMode != IcsObserving) {\r
+                       sprintf(buf, "You are not observing a game");\r
+                       DisplayError(buf, 0);\r
+                       /* secure check */\r
+                       if (appData.icsEngineAnalyze) {\r
+                               if (appData.debugMode) \r
+                                       fprintf(debugFP, "Found unexpected active ICS engine analyze \n");\r
+                               ExitAnalyzeMode();\r
+                               ModeHighlight();\r
+                               break;\r
+                       }\r
+                       break;\r
+               } else {\r
+                       /* if enable, user want disable icsEngineAnalyze */\r
+                       if (appData.icsEngineAnalyze) {\r
+                               ExitAnalyzeMode();\r
+                               ModeHighlight();\r
+                               break;\r
+                       }\r
+                       appData.icsEngineAnalyze = TRUE;\r
+                       if (appData.debugMode) fprintf(debugFP, "ICS engine analyze starting...\n");\r
+               }\r
+        } \r
        if (!appData.showThinking) ToggleShowThinking();\r
        AnalyzeModeEvent();\r
       }\r
@@ -5481,10 +4547,12 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 \r
     case IDM_EditGame:\r
       EditGameEvent();\r
+      SAY("edit game");\r
       break;\r
 \r
     case IDM_EditPosition:\r
       EditPositionEvent();\r
+      SAY("to set up a position type a FEN");\r
       break;\r
 \r
     case IDM_Training:\r
@@ -5500,7 +4568,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       break;\r
 \r
     case IDM_EditComment:\r
-      if (commentDialogUp && editComment) {\r
+      if (commentUp && editComment) {\r
        CommentPopDown();\r
       } else {\r
        EditCommentEvent();\r
@@ -5564,6 +4632,8 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       SetFocus(hwndMain);\r
       break;\r
 \r
+    JAWS_MENU_ITEMS\r
+\r
     case IDM_Forward:\r
       ForwardEvent();\r
       SetFocus(hwndMain);\r
@@ -5603,6 +4673,13 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     case IDM_FlipClock:\r
       flipClock = !flipClock;\r
       DisplayBothClocks();\r
+      DrawPosition(FALSE, NULL);\r
+      break;\r
+\r
+    case IDM_MuteSounds:\r
+      mute = !mute; // [HGM] mute: keep track of global muting variable\r
+      CheckMenuItem(GetMenu(hwndMain),IDM_MuteSounds, \r
+                               MF_BYCOMMAND|(mute?MF_CHECKED:MF_UNCHECKED));\r
       break;\r
 \r
     case IDM_GeneralOptions:\r
@@ -5618,6 +4695,14 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       EnginePlayOptionsPopup(hwnd);\r
       break;\r
 \r
+    case IDM_Engine1Options:\r
+      EngineOptionsPopup(hwnd, &first);\r
+      break;\r
+\r
+    case IDM_Engine2Options:\r
+      EngineOptionsPopup(hwnd, &second);\r
+      break;\r
+\r
     case IDM_OptionsUCI:\r
       UciOptionsPopup(hwnd);\r
       break;\r
@@ -5689,15 +4774,17 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       break;\r
 \r
     case IDM_HELPCONTENTS:\r
-      if (!WinHelp (hwnd, "winboard.hlp", HELP_KEY,(DWORD)(LPSTR)"CONTENTS")) {\r
-       MessageBox (GetFocus(),\r
+      if (!MyHelp (hwnd, "winboard.hlp", HELP_KEY,(DWORD)(LPSTR)"CONTENTS") &&\r
+         !HtmlHelp(hwnd, "winboard.chm", 0, 0) ) {\r
+         MessageBox (GetFocus(),\r
                    "Unable to activate help",\r
                    szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND);\r
       }\r
       break;\r
 \r
     case IDM_HELPSEARCH:\r
-      if (!WinHelp(hwnd, "winboard.hlp", HELP_PARTIALKEY, (DWORD)(LPSTR)"")) {\r
+        if (!MyHelp (hwnd, "winboard.hlp", HELP_PARTIALKEY, (DWORD)(LPSTR)"") &&\r
+           !HtmlHelp(hwnd, "winboard.chm", 0, 0)       ) {\r
        MessageBox (GetFocus(),\r
                    "Unable to activate help",\r
                    szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND);\r
@@ -5922,8 +5009,8 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       AutoPlayGameLoop(); /* call into back end */\r
       break;\r
     case ANALYSIS_TIMER_ID:\r
-      if ((gameMode == AnalyzeMode || gameMode == AnalyzeFile) && \r
-         appData.periodicUpdates) {\r
+      if ((gameMode == AnalyzeMode || gameMode == AnalyzeFile\r
+                 || appData.icsEngineAnalyze) && appData.periodicUpdates) {\r
        AnalysisPeriodicEvent(0);\r
       } else {\r
        KillTimer(hwnd, analysisTimerEvent);\r
@@ -5944,6 +5031,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 \r
   /* [AS] Also move "attached" child windows */\r
   case WM_WINDOWPOSCHANGING:\r
+\r
     if( hwnd == hwndMain && appData.useStickyWindows ) {\r
         LPWINDOWPOS lpwp = (LPWINDOWPOS) lParam;\r
 \r
@@ -5951,17 +5039,26 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
             /* Window is moving */\r
             RECT rcMain;\r
 \r
-            GetWindowRect( hwnd, &rcMain );\r
+//            GetWindowRect( hwnd, &rcMain ); //[HGM] sticky: in XP this returned new position, not old\r
+           rcMain.left   = wpMain.x;           //              replace by these 4 lines to reconstruct old rect\r
+           rcMain.right  = wpMain.x + wpMain.width;\r
+           rcMain.top    = wpMain.y;\r
+           rcMain.bottom = wpMain.y + wpMain.height;\r
             \r
             ReattachAfterMove( &rcMain, lpwp->x, lpwp->y, moveHistoryDialog, &wpMoveHistory );\r
             ReattachAfterMove( &rcMain, lpwp->x, lpwp->y, evalGraphDialog, &wpEvalGraph );\r
             ReattachAfterMove( &rcMain, lpwp->x, lpwp->y, engineOutputDialog, &wpEngineOutput );\r
+            ReattachAfterMove( &rcMain, lpwp->x, lpwp->y, gameListDialog, &wpGameList );\r
+            ReattachAfterMove( &rcMain, lpwp->x, lpwp->y, hwndConsole, &wpConsole );\r
+           wpMain.x = lpwp->x;\r
+            wpMain.y = lpwp->y;\r
         }\r
     }\r
     break;\r
 \r
   /* [AS] Snapping */\r
   case WM_ENTERSIZEMOVE:\r
+    if(appData.debugMode) { fprintf(debugFP, "size-move\n"); }\r
     if (hwnd == hwndMain) {\r
       doingSizing = TRUE;\r
       lastSizing = 0;\r
@@ -5970,15 +5067,18 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     break;\r
 \r
   case WM_SIZING:\r
+    if(appData.debugMode) { fprintf(debugFP, "sizing\n"); }\r
     if (hwnd == hwndMain) {\r
       lastSizing = wParam;\r
     }\r
     break;\r
 \r
   case WM_MOVING:\r
+    if(appData.debugMode) { fprintf(debugFP, "moving\n"); }\r
       return OnMoving( &sd, hwnd, wParam, lParam );\r
 \r
   case WM_EXITSIZEMOVE:\r
+    if(appData.debugMode) { fprintf(debugFP, "exit size-move, size = %d\n", squareSize); }\r
     if (hwnd == hwndMain) {\r
       RECT client;\r
       doingSizing = FALSE;\r
@@ -5986,6 +5086,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       GetClientRect(hwnd, &client);\r
       ResizeBoard(client.right, client.bottom, lastSizing);\r
       lastSizing = 0;\r
+      if(appData.debugMode) { fprintf(debugFP, "square size = %d\n", squareSize); }\r
     }\r
     return OnExitSizeMove( &sd, hwnd, wParam, lParam );\r
     break;\r
@@ -6139,8 +5240,11 @@ BOOLEAN
 MyPlaySound(MySound *ms)\r
 {\r
   BOOLEAN ok = FALSE;\r
+\r
+  if(mute) return TRUE; // [HGM] mute: suppress all sound play when muted\r
   switch (ms->name[0]) {\r
   case NULLCHAR:\r
+       if(appData.debugMode) fprintf(debugFP, "silence\n");\r
     /* Silence */\r
     ok = TRUE;\r
     break;\r
@@ -6170,13 +5274,6 @@ MyPlaySound(MySound *ms)
   /* Don't print an error: this can happen innocently if the sound driver\r
      is busy; for instance, if another instance of WinBoard is playing\r
      a sound at about the same time. */\r
-#if 0\r
-  if (!ok) {\r
-    char buf[MSG_SIZ];\r
-    sprintf(buf, "Error playing sound %s", ms->name);\r
-    DisplayError(buf, GetLastError());\r
-  }\r
-#endif\r
   return ok;\r
 }\r
 \r
@@ -6455,7 +5552,7 @@ InitComboStrings(HANDLE hwndCombo, char **cd)
 void\r
 InitComboStringsFromOption(HANDLE hwndCombo, char *str)\r
 {\r
-  char buf1[ARG_MAX];\r
+  char buf1[MAX_ARG_LEN];\r
   int len;\r
 \r
   if (str[0] == '@') {\r
@@ -6488,7 +5585,7 @@ SetStartupDialogEnables(HWND hDlg)
 {\r
   EnableWindow(GetDlgItem(hDlg, OPT_ChessEngineName),\r
     IsDlgButtonChecked(hDlg, OPT_ChessEngine) ||\r
-    appData.zippyPlay && IsDlgButtonChecked(hDlg, OPT_ChessServer));\r
+    (appData.zippyPlay && IsDlgButtonChecked(hDlg, OPT_ChessServer)));\r
   EnableWindow(GetDlgItem(hDlg, OPT_SecondChessEngineName),\r
     IsDlgButtonChecked(hDlg, OPT_ChessEngine));\r
   EnableWindow(GetDlgItem(hDlg, OPT_ChessServerName),\r
@@ -6662,6 +5759,7 @@ About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
     /* Center the dialog over the application window */\r
     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
     SetDlgItemText(hDlg, ABOUTBOX_Version, programVersion);\r
+    JAWS_COPYRIGHT\r
     return (TRUE);\r
 \r
   case WM_COMMAND: /* message: received a command */\r
@@ -6716,18 +5814,18 @@ CommentDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
       GetClientRect(hDlg, &rect);\r
       sizeX = rect.right;\r
       sizeY = rect.bottom;\r
-      if (commentX != CW_USEDEFAULT && commentY != CW_USEDEFAULT &&\r
-         commentW != CW_USEDEFAULT && commentH != CW_USEDEFAULT) {\r
+      if (wpComment.x != CW_USEDEFAULT && wpComment.y != CW_USEDEFAULT &&\r
+         wpComment.width != CW_USEDEFAULT && wpComment.height != CW_USEDEFAULT) {\r
        WINDOWPLACEMENT wp;\r
-       EnsureOnScreen(&commentX, &commentY);\r
+       EnsureOnScreen(&wpComment.x, &wpComment.y, 0, 0);\r
        wp.length = sizeof(WINDOWPLACEMENT);\r
        wp.flags = 0;\r
        wp.showCmd = SW_SHOW;\r
        wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;\r
-       wp.rcNormalPosition.left = commentX;\r
-       wp.rcNormalPosition.right = commentX + commentW;\r
-       wp.rcNormalPosition.top = commentY;\r
-       wp.rcNormalPosition.bottom = commentY + commentH;\r
+       wp.rcNormalPosition.left = wpComment.x;\r
+       wp.rcNormalPosition.right = wpComment.x + wpComment.width;\r
+       wp.rcNormalPosition.top = wpComment.y;\r
+       wp.rcNormalPosition.bottom = wpComment.y + wpComment.height;\r
        SetWindowPlacement(hDlg, &wp);\r
 \r
        GetClientRect(hDlg, &rect);\r
@@ -6826,14 +5924,14 @@ EitherCommentPopUp(int index, char *title, char *str, BOOLEAN edit)
 \r
   if (commentDialog) {\r
     SendMessage(commentDialog, WM_INITDIALOG, 0, 0);\r
-    if (!commentDialogUp) ShowWindow(commentDialog, SW_SHOW);\r
+    if (!commentUp) ShowWindow(commentDialog, SW_SHOW);\r
   } else {\r
     lpProc = MakeProcInstance((FARPROC)CommentDialog, hInst);\r
     CreateDialog(hInst, MAKEINTRESOURCE(DLG_EditComment),\r
                 hwndMain, (DLGPROC)lpProc);\r
     FreeProcInstance(lpProc);\r
   }\r
-  commentDialogUp = TRUE;\r
+  commentUp = TRUE;\r
 }\r
 \r
 \r
@@ -6866,12 +5964,30 @@ TypeInMoveDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
   case WM_COMMAND:\r
     switch (LOWORD(wParam)) {\r
     case IDOK:\r
+      GetDlgItemText(hDlg, OPT_Move, move, sizeof(move));\r
+      { int n; Board board;\r
+       // [HGM] FENedit\r
+       if(gameMode == EditPosition && ParseFEN(board, &n, move) ) {\r
+               EditPositionPasteFEN(move);\r
+               EndDialog(hDlg, TRUE);\r
+               return TRUE;\r
+       }\r
+       // [HGM] movenum: allow move number to be typed in any mode\r
+       if(sscanf(move, "%d", &n) == 1 && n != 0 ) {\r
+         ToNrEvent(2*n-1);\r
+         EndDialog(hDlg, TRUE);\r
+         return TRUE;\r
+       }\r
+      }\r
       if (gameMode != EditGame && currentMove != forwardMostMove && \r
        gameMode != Training) {\r
        DisplayMoveError("Displayed move is not current");\r
       } else {\r
-       GetDlgItemText(hDlg, OPT_Move, move, sizeof(move));\r
-       if (ParseOneMove(move, gameMode == EditPosition ? blackPlaysFirst : currentMove, \r
+//     GetDlgItemText(hDlg, OPT_Move, move, sizeof(move)); // moved upstream\r
+       int ok = ParseOneMove(move, gameMode == EditPosition ? blackPlaysFirst : currentMove, \r
+         &moveType, &fromX, &fromY, &toX, &toY, &promoChar);\r
+       if(!ok && move[0] >= 'a') { move[0] += 'A' - 'a'; ok = 2; } // [HGM] try also capitalized\r
+       if (ok==1 || ok && ParseOneMove(move, gameMode == EditPosition ? blackPlaysFirst : currentMove, \r
          &moveType, &fromX, &fromY, &toX, &toY, &promoChar)) {\r
          if (gameMode != Training)\r
              forwardMostMove = currentMove;\r
@@ -6903,6 +6019,9 @@ PopUpMoveDialog(char firstchar)
        gameMode == AnalyzeMode || gameMode == EditGame || \r
        gameMode == EditPosition || gameMode == IcsExamining ||\r
        gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack ||\r
+       isdigit(firstchar) && // [HGM] movenum: allow typing in of move nr in 'passive' modes\r
+               ( gameMode == AnalyzeFile || gameMode == PlayFromGameFile ||\r
+                 gameMode == IcsObserving || gameMode == TwoMachinesPlay    ) ||\r
        gameMode == Training) {\r
       lpProc = MakeProcInstance((FARPROC)TypeInMoveDialog, hInst);\r
       DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_TypeInMove),\r
@@ -6939,6 +6058,7 @@ TypeInNameDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
     case IDOK:\r
       GetDlgItemText(hDlg, OPT_Name, move, sizeof(move));\r
       appData.userName = strdup(move);\r
+      SetUserLogo();\r
 \r
       EndDialog(hDlg, TRUE);\r
       return TRUE;\r
@@ -7017,6 +6137,7 @@ ErrorPopDown()
   if (errorDialog == NULL) return;\r
   DestroyWindow(errorDialog);\r
   errorDialog = NULL;\r
+  if(errorExitStatus) ExitEvent(errorExitStatus);\r
 }\r
 \r
 LRESULT CALLBACK\r
@@ -7079,7 +6200,7 @@ GothicDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
   case WM_INITDIALOG:\r
     GetWindowRect(hDlg, &rChild);\r
 \r
-    SetWindowPos(hDlg, NULL, boardX, boardY-height, winWidth, height,\r
+    SetWindowPos(hDlg, NULL, wpMain.x, wpMain.y-height, wpMain.width, height,\r
                                                              SWP_NOZORDER);\r
 \r
     /* \r
@@ -7114,8 +6235,6 @@ VOID
 GothicPopUp(char *title, VariantClass variant)\r
 {\r
   FARPROC lpProc;\r
-  char *p, *q;\r
-  BOOLEAN modal = hwndMain == NULL;\r
   static char *lastTitle;\r
 \r
   strncpy(errorTitle, title, sizeof(errorTitle));\r
@@ -7181,76 +6300,7 @@ NextInHistory()
 {\r
   if (histP == histIn) return NULL;\r
   histP = (histP + 1) % HISTORY_SIZE;\r
-  return history[histP];\r
-}\r
-\r
-typedef struct {\r
-  char *item;\r
-  char *command;\r
-  BOOLEAN getname;\r
-  BOOLEAN immediate;\r
-} IcsTextMenuEntry;\r
-#define ICS_TEXT_MENU_SIZE (IDM_CommandXLast - IDM_CommandX + 1)\r
-IcsTextMenuEntry icsTextMenuEntry[ICS_TEXT_MENU_SIZE];\r
-\r
-void\r
-ParseIcsTextMenu(char *icsTextMenuString)\r
-{\r
-  int flags = 0;\r
-  IcsTextMenuEntry *e = icsTextMenuEntry;\r
-  char *p = icsTextMenuString;\r
-  while (e->item != NULL && e < icsTextMenuEntry + ICS_TEXT_MENU_SIZE) {\r
-    free(e->item);\r
-    e->item = NULL;\r
-    if (e->command != NULL) {\r
-      free(e->command);\r
-      e->command = NULL;\r
-    }\r
-    e++;\r
-  }\r
-  e = icsTextMenuEntry;\r
-  while (*p && e < icsTextMenuEntry + ICS_TEXT_MENU_SIZE) {\r
-    if (*p == ';' || *p == '\n') {\r
-      e->item = strdup("-");\r
-      e->command = NULL;\r
-      p++;\r
-    } else if (*p == '-') {\r
-      e->item = strdup("-");\r
-      e->command = NULL;\r
-      p++;\r
-      if (*p) p++;\r
-    } else {\r
-      char *q, *r, *s, *t;\r
-      char c;\r
-      q = strchr(p, ',');\r
-      if (q == NULL) break;\r
-      *q = NULLCHAR;\r
-      r = strchr(q + 1, ',');\r
-      if (r == NULL) break;\r
-      *r = NULLCHAR;\r
-      s = strchr(r + 1, ',');\r
-      if (s == NULL) break;\r
-      *s = NULLCHAR;\r
-      c = ';';\r
-      t = strchr(s + 1, c);\r
-      if (t == NULL) {\r
-       c = '\n';\r
-       t = strchr(s + 1, c);\r
-      }\r
-      if (t != NULL) *t = NULLCHAR;\r
-      e->item = strdup(p);\r
-      e->command = strdup(q + 1);\r
-      e->getname = *(r + 1) != '0';\r
-      e->immediate = *(s + 1) != '0';\r
-      *q = ',';\r
-      *r = ',';\r
-      *s = ',';\r
-      if (t == NULL) break;\r
-      *t = c;\r
-      p = t + 1;\r
-    }\r
-    e++;\r
-  } \r
+  return history[histP];   \r
 }\r
 \r
 HMENU\r
@@ -7263,13 +6313,14 @@ LoadIcsTextMenu(IcsTextMenuEntry *e)
   while (e->item) {\r
     if (strcmp(e->item, "-") == 0) {\r
       AppendMenu(h, MF_SEPARATOR, 0, 0);\r
-    } else {\r
+    } else { // [HGM] re-written a bit to use only one AppendMenu call for both cases (| or no |)\r
+      int flags = MF_STRING, j = 0;\r
       if (e->item[0] == '|') {\r
-       AppendMenu(h, MF_STRING|MF_MENUBARBREAK,\r
-                  IDM_CommandX + i, &e->item[1]);\r
-      } else {\r
-       AppendMenu(h, MF_STRING, IDM_CommandX + i, e->item);\r
+       flags |= MF_MENUBARBREAK;\r
+        j++;\r
       }\r
+      if(!strcmp(e->command, "none")) flags |= MF_GRAYED; // [HGM] chatclick: provide inactive dummy\r
+      AppendMenu(h, flags, IDM_CommandX + i, e->item + j);\r
     }\r
     e++;\r
     i++;\r
@@ -7338,6 +6389,7 @@ CommandX(HWND hwnd, char *command, BOOLEAN getname, BOOLEAN immediate)
     SetWindowText(hInput, buf);\r
     SendMessage(hInput, WM_CHAR, '\r', 0);\r
   } else {\r
+    if(!strcmp(command, "chat")) { ChatPopUp(name); return; }\r
     sprintf(buf, "%s %s ", command, name); /* trailing space */\r
     SetWindowText(hInput, buf);\r
     sel.cpMin = 999999;\r
@@ -7369,6 +6421,7 @@ ConsoleTextSubclass(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     }\r
     break;\r
   case WM_CHAR:\r
+   if(wParam != '\022') {\r
     if (wParam == '\t') {\r
       if (GetKeyState(VK_SHIFT) < 0) {\r
        /* shifted */\r
@@ -7384,16 +6437,11 @@ ConsoleTextSubclass(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       }\r
     } else {\r
       hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
-      SetFocus(hInput);\r
+      JAWS_DELETE( SetFocus(hInput); )\r
       SendMessage(hInput, message, wParam, lParam);\r
     }\r
     return 0;\r
-  case WM_PASTE:\r
-    hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
-    SetFocus(hInput);\r
-    return SendMessage(hInput, message, wParam, lParam);\r
-  case WM_MBUTTONDOWN:\r
-    return SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0);\r
+   } // [HGM] navigate: for Ctrl+R, flow into nex case (moved up here) to summon up menu\r
   case WM_RBUTTONDOWN:\r
     if (!(GetKeyState(VK_SHIFT) & ~1)) {\r
       /* Move selection here if it was empty */\r
@@ -7407,13 +6455,7 @@ ConsoleTextSubclass(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel);\r
       }\r
       SendMessage(hwnd, EM_HIDESELECTION, FALSE, FALSE);\r
-    }\r
-    return 0;\r
-  case WM_RBUTTONUP:\r
-    if (GetKeyState(VK_SHIFT) & ~1) {\r
-      SendDlgItemMessage(hwndConsole, OPT_ConsoleText, \r
-        WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0);\r
-    } else {\r
+{ // [HGM] chatclick: code moved here from WM_RBUTTONUP case, to have menu appear on down-click\r
       POINT pt;\r
       HMENU hmenu = LoadIcsTextMenu(icsTextMenuEntry);\r
       SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel);\r
@@ -7424,11 +6466,25 @@ ConsoleTextSubclass(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       if (!IsClipboardFormatAvailable(CF_TEXT)) {\r
         EnableMenuItem(hmenu, IDM_Paste, MF_BYCOMMAND|MF_GRAYED);\r
       }\r
-      pt.x = LOWORD(lParam);\r
-      pt.y = HIWORD(lParam);\r
+      pt.x = LOWORD(lParam)-30; // [HGM] chatclick: make menu pop up with pointer above upper-right item\r
+      pt.y = HIWORD(lParam)-10; //       make it appear as if mouse moved there, so it will be selected on up-click\r
+      PostMessage(hwnd, WM_MOUSEMOVE, wParam, lParam+5);\r
       MenuPopup(hwnd, pt, hmenu, -1);\r
+}\r
+    }\r
+    return 0;\r
+  case WM_RBUTTONUP:\r
+    if (GetKeyState(VK_SHIFT) & ~1) {\r
+      SendDlgItemMessage(hwndConsole, OPT_ConsoleText, \r
+        WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0);\r
     }\r
     return 0;\r
+  case WM_PASTE:\r
+    hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
+    SetFocus(hInput);\r
+    return SendMessage(hInput, message, wParam, lParam);\r
+  case WM_MBUTTONDOWN:\r
+    return SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0);\r
   case WM_COMMAND:\r
     switch (LOWORD(wParam)) {\r
     case IDM_QuickPaste:\r
@@ -7545,6 +6601,7 @@ ConsoleInputSubclass(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     case '\021': /* Ctrl+Q */\r
       quoteNextChar = TRUE;\r
       return 0;\r
+    JAWS_REPLAY\r
     default:\r
       break;\r
     }\r
@@ -7639,18 +6696,35 @@ LRESULT CALLBACK
 ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
 {\r
   static SnapData sd;\r
-  static HWND hText, hInput, hFocus;\r
-  InputSource *is = consoleInputSource;\r
+  HWND hText, hInput;\r
   RECT rect;\r
   static int sizeX, sizeY;\r
   int newSizeX, newSizeY;\r
   MINMAXINFO *mmi;\r
+  WORD wMask;\r
+\r
+  hText = GetDlgItem(hDlg, OPT_ConsoleText);\r
+  hInput = GetDlgItem(hDlg, OPT_ConsoleInput);\r
 \r
   switch (message) {\r
+  case WM_NOTIFY:\r
+    if (((NMHDR*)lParam)->code == EN_LINK)\r
+    {\r
+      ENLINK *pLink = (ENLINK*)lParam;\r
+      if (pLink->msg == WM_LBUTTONUP)\r
+      {\r
+        TEXTRANGE tr;\r
+\r
+        tr.chrg = pLink->chrg;\r
+        tr.lpstrText = malloc(1+tr.chrg.cpMax-tr.chrg.cpMin);\r
+        SendMessage(hText, EM_GETTEXTRANGE, 0, (LPARAM)&tr);\r
+        ShellExecute(NULL, "open", tr.lpstrText, NULL, NULL, SW_SHOW);\r
+        free(tr.lpstrText);\r
+      }\r
+    }\r
+    break;\r
   case WM_INITDIALOG: /* message: initialize dialog box */\r
     hwndConsole = hDlg;\r
-    hText = GetDlgItem(hDlg, OPT_ConsoleText);\r
-    hInput = GetDlgItem(hDlg, OPT_ConsoleInput);\r
     SetFocus(hInput);\r
     consoleTextWindowProc = (WNDPROC)\r
       SetWindowLong(hText, GWL_WNDPROC, (LONG) ConsoleTextSubclass);\r
@@ -7664,20 +6738,46 @@ ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
     GetClientRect(hDlg, &rect);\r
     sizeX = rect.right;\r
     sizeY = rect.bottom;\r
-    if (consoleX != CW_USEDEFAULT && consoleY != CW_USEDEFAULT &&\r
-       consoleW != CW_USEDEFAULT && consoleH != CW_USEDEFAULT) {\r
+    if (wpConsole.x != CW_USEDEFAULT && wpConsole.y != CW_USEDEFAULT &&\r
+       wpConsole.width != CW_USEDEFAULT && wpConsole.height != CW_USEDEFAULT) {\r
       WINDOWPLACEMENT wp;\r
-      EnsureOnScreen(&consoleX, &consoleY);\r
+      EnsureOnScreen(&wpConsole.x, &wpConsole.y, 0, 0);\r
       wp.length = sizeof(WINDOWPLACEMENT);\r
       wp.flags = 0;\r
       wp.showCmd = SW_SHOW;\r
       wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;\r
-      wp.rcNormalPosition.left = consoleX;\r
-      wp.rcNormalPosition.right = consoleX + consoleW;\r
-      wp.rcNormalPosition.top = consoleY;\r
-      wp.rcNormalPosition.bottom = consoleY + consoleH;\r
+      wp.rcNormalPosition.left = wpConsole.x;\r
+      wp.rcNormalPosition.right = wpConsole.x + wpConsole.width;\r
+      wp.rcNormalPosition.top = wpConsole.y;\r
+      wp.rcNormalPosition.bottom = wpConsole.y + wpConsole.height;\r
       SetWindowPlacement(hDlg, &wp);\r
     }\r
+\r
+   // [HGM] Chessknight's change 2004-07-13\r
+   else { /* Determine Defaults */\r
+       WINDOWPLACEMENT wp;\r
+       wpConsole.x = wpMain.width + 1;\r
+       wpConsole.y = wpMain.y;\r
+       wpConsole.width = screenWidth -  wpMain.width;\r
+       wpConsole.height = wpMain.height;\r
+       EnsureOnScreen(&wpConsole.x, &wpConsole.y, 0, 0);\r
+       wp.length = sizeof(WINDOWPLACEMENT);\r
+       wp.flags = 0;\r
+       wp.showCmd = SW_SHOW;\r
+       wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;\r
+       wp.rcNormalPosition.left = wpConsole.x;\r
+       wp.rcNormalPosition.right = wpConsole.x + wpConsole.width;\r
+       wp.rcNormalPosition.top = wpConsole.y;\r
+       wp.rcNormalPosition.bottom = wpConsole.y + wpConsole.height;\r
+       SetWindowPlacement(hDlg, &wp);\r
+    }\r
+\r
+   // Allow hText to highlight URLs and send notifications on them\r
+   wMask = (WORD) SendMessage(hText, EM_GETEVENTMASK, 0, 0L);\r
+   SendMessage(hText, EM_SETEVENTMASK, 0, wMask | ENM_LINK);\r
+   SendMessage(hText, EM_AUTOURLDETECT, TRUE, 0L);\r
+   SetWindowLong(hText, GWL_USERDATA, 79); // initialize the text window's width\r
+\r
     return FALSE;\r
 \r
   case WM_SETFOCUS:\r
@@ -7737,6 +6837,7 @@ ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
     return OnMoving( &sd, hDlg, wParam, lParam );\r
 \r
   case WM_EXITSIZEMOVE:\r
+       UpdateICSWidth(hText);\r
     return OnExitSizeMove( &sd, hDlg, wParam, lParam );\r
   }\r
 \r
@@ -7890,7 +6991,7 @@ DisplayAClock(HDC hdc, int timeRemaining, int highlight,
     if (tinyLayout)\r
       sprintf(buf, "%c %s %s", color[0], TimeString(timeRemaining), flagFell);\r
     else\r
-      sprintf(buf, "%s: %s %s", color, TimeString(timeRemaining), flagFell);\r
+      sprintf(buf, "%s:%c%s %s", color, (logoHeight>0 ? 0 : ' '), TimeString(timeRemaining), flagFell);\r
     str = buf;\r
   } else {\r
     str = color;\r
@@ -7905,10 +7006,22 @@ DisplayAClock(HDC hdc, int timeRemaining, int highlight,
   }\r
   oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);\r
 \r
+  JAWS_SILENCE\r
+\r
   ExtTextOut(hdc, rect->left + MESSAGE_LINE_LEFTMARGIN,\r
             rect->top, ETO_CLIPPED|ETO_OPAQUE,\r
             rect, str, strlen(str), NULL);\r
-\r
+  if(logoHeight > 0 && appData.clockMode) {\r
+      RECT r;\r
+      sprintf(buf, "%s %s", buf+7, flagFell);\r
+      r.top = rect->top + logoHeight/2;\r
+      r.left = rect->left;\r
+      r.right = rect->right;\r
+      r.bottom = rect->bottom;\r
+      ExtTextOut(hdc, rect->left + MESSAGE_LINE_LEFTMARGIN,\r
+                r.top, ETO_CLIPPED|ETO_OPAQUE,\r
+                &r, str, strlen(str), NULL);\r
+  }\r
   (void) SetTextColor(hdc, oldFg);\r
   (void) SetBkColor(hdc, oldBg);\r
   (void) SelectObject(hdc, oldFont);\r
@@ -7985,7 +7098,7 @@ void CheckForInputBufferFull( InputSource * is )
 \r
         if( p >= is->next ) {\r
             if (appData.debugMode) {\r
-                fprintf( debugFP, "Input line exceeded buffer size (source id=%u)\n", is->id );\r
+                fprintf( debugFP, "Input line exceeded buffer size (source id=%lu)\n", is->id );\r
             }\r
 \r
             is->error = ERROR_BROKEN_PIPE; /* [AS] Just any non-successful code! */\r
@@ -8034,7 +7147,7 @@ InputThread(LPVOID arg)
   CloseHandle(is->hFile);\r
 \r
   if (appData.debugMode) {\r
-    fprintf( debugFP, "Input thread terminated (id=%u, error=%d, count=%d)\n", is->id, is->error, is->count );\r
+    fprintf( debugFP, "Input thread terminated (id=%lu, error=%d, count=%ld)\n", is->id, is->error, is->count );\r
   }\r
 \r
   return 0;\r
@@ -8175,6 +7288,13 @@ typedef struct {
 } Enables;\r
 \r
 VOID\r
+GreyRevert(Boolean grey)\r
+{ // [HGM] vari: for retracting variations in local mode\r
+  HMENU hmenu = GetMenu(hwndMain);\r
+  EnableMenuItem(hmenu, IDM_Revert, MF_BYCOMMAND|(grey ? MF_GRAYED : MF_ENABLED));\r
+}\r
+\r
+VOID\r
 SetMenuEnables(HMENU hmenu, Enables *enab)\r
 {\r
   while (enab->item > 0) {\r
@@ -8194,6 +7314,7 @@ Enables gnuEnables[] = {
   { IDM_StopExamining, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_StopObserving, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_Revert, MF_BYCOMMAND|MF_GRAYED },\r
+  { IDM_NewChat, MF_BYCOMMAND|MF_GRAYED },\r
   { -1, -1 }\r
 };\r
 \r
@@ -8203,13 +7324,16 @@ Enables icsEnables[] = {
   { IDM_MachineWhite, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_MachineBlack, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_TwoMachines, MF_BYCOMMAND|MF_GRAYED },\r
-  { IDM_AnalysisMode, MF_BYCOMMAND|MF_GRAYED },\r
+  { IDM_MachineBoth, MF_BYCOMMAND|MF_GRAYED },\r
+  { IDM_AnalysisMode, MF_BYCOMMAND|MF_ENABLED },\r
   { IDM_AnalyzeFile, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_TimeControl, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_MoveNow, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_Hint, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_Book, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_IcsOptions, MF_BYCOMMAND|MF_ENABLED },\r
+  { IDM_Engine1Options, MF_BYCOMMAND|MF_GRAYED },\r
+  { IDM_Engine2Options, MF_BYCOMMAND|MF_GRAYED },\r
   { -1, -1 }\r
 };\r
 \r
@@ -8218,6 +7342,7 @@ Enables zippyEnables[] = {
   { IDM_MoveNow, MF_BYCOMMAND|MF_ENABLED },\r
   { IDM_Hint, MF_BYCOMMAND|MF_ENABLED },\r
   { IDM_Book, MF_BYCOMMAND|MF_ENABLED },\r
+  { IDM_Engine1Options, MF_BYCOMMAND|MF_ENABLED },\r
   { -1, -1 }\r
 };\r
 #endif\r
@@ -8238,6 +7363,10 @@ Enables ncpEnables[] = {
   { IDM_TimeControl, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_Hint, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_Book, MF_BYCOMMAND|MF_GRAYED },\r
+  { IDM_MachineBoth, MF_BYCOMMAND|MF_GRAYED },\r
+  { IDM_NewChat, MF_BYCOMMAND|MF_GRAYED },\r
+  { IDM_Engine1Options, MF_BYCOMMAND|MF_GRAYED },\r
+  { IDM_Engine2Options, MF_BYCOMMAND|MF_GRAYED },\r
   { -1, -1 }\r
 };\r
 \r
@@ -8398,6 +7527,17 @@ ModeHighlight()
   }\r
 \r
   prevChecked = nowChecked;\r
+\r
+  /* [DM] icsEngineAnalyze - Do a sceure check too */\r
+  if (appData.icsActive) {\r
+       if (appData.icsEngineAnalyze) {\r
+               (void) CheckMenuItem(GetMenu(hwndMain), IDM_AnalysisMode,\r
+                       MF_BYCOMMAND|MF_CHECKED);\r
+       } else {\r
+               (void) CheckMenuItem(GetMenu(hwndMain), IDM_AnalysisMode,\r
+                       MF_BYCOMMAND|MF_UNCHECKED);\r
+       }\r
+  }\r
 }\r
 \r
 VOID\r
@@ -8410,6 +7550,9 @@ SetICSMode()
 #ifdef ZIPPY\r
   if (appData.zippyPlay) {\r
     SetMenuEnables(hmenu, zippyEnables);\r
+    if (!appData.noChessProgram)     /* [DM] icsEngineAnalyze */\r
+         (void) EnableMenuItem(GetMenu(hwndMain), IDM_AnalysisMode,\r
+          MF_BYCOMMAND|MF_ENABLED);\r
   }\r
 #endif\r
 }\r
@@ -8534,7 +7677,10 @@ DisplayMessage(char *str1, char *str2)
   }\r
   messageText[MESSAGE_TEXT_MAX - 1] = NULLCHAR;\r
 \r
-  if (IsIconic(hwndMain)) return;\r
+  if (hwndMain == NULL || IsIconic(hwndMain)) return;\r
+\r
+  SAYMACHINEMOVE();\r
+\r
   hdc = GetDC(hwndMain);\r
   oldFont = SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);\r
   ExtTextOut(hdc, messageRect.left, messageRect.top, ETO_CLIPPED|ETO_OPAQUE,\r
@@ -8760,103 +7906,42 @@ int NewGameFRC()
     return result;\r
 }\r
 \r
-/* [AS] Game list options */\r
-typedef struct {\r
-    char id;\r
-    char * name;\r
-} GLT_Item;\r
-\r
-static GLT_Item GLT_ItemInfo[] = {\r
-    { GLT_EVENT,      "Event" },\r
-    { GLT_SITE,       "Site" },\r
-    { GLT_DATE,       "Date" },\r
-    { GLT_ROUND,      "Round" },\r
-    { GLT_PLAYERS,    "Players" },\r
-    { GLT_RESULT,     "Result" },\r
-    { GLT_WHITE_ELO,  "White Rating" },\r
-    { GLT_BLACK_ELO,  "Black Rating" },\r
-    { GLT_TIME_CONTROL,"Time Control" },\r
-    { GLT_VARIANT,    "Variant" },\r
-    { GLT_OUT_OF_BOOK,PGN_OUT_OF_BOOK },\r
-    { 0, 0 }\r
-};\r
-\r
-const char * GLT_FindItem( char id )\r
-{\r
-    const char * result = 0;\r
-\r
-    GLT_Item * list = GLT_ItemInfo;\r
-\r
-    while( list->id != 0 ) {\r
-        if( list->id == id ) {\r
-            result = list->name;\r
-            break;\r
-        }\r
+/* [AS] Game list options. Refactored by HGM */\r
 \r
-        list++;\r
-    }\r
+HWND gameListOptionsDialog;\r
 \r
-    return result;\r
+// low-level front-end: clear text edit / list widget\r
+void\r
+GLT_ClearList()\r
+{\r
+    SendDlgItemMessage( gameListOptionsDialog, IDC_GameListTags, LB_RESETCONTENT, 0, 0 );\r
 }\r
 \r
-void GLT_AddToList( HWND hDlg, int iDlgItem, char id, int index )\r
+// low-level front-end: clear text edit / list widget\r
+void\r
+GLT_DeSelectList()\r
 {\r
-    const char * name = GLT_FindItem( id );\r
-\r
-    if( name != 0 ) {\r
-        if( index >= 0 ) {\r
-            SendDlgItemMessage( hDlg, iDlgItem, LB_INSERTSTRING, index, (LPARAM) name );\r
-        }\r
-        else {\r
-            SendDlgItemMessage( hDlg, iDlgItem, LB_ADDSTRING, 0, (LPARAM) name );\r
-        }\r
-    }\r
+    SendDlgItemMessage( gameListOptionsDialog, IDC_GameListTags, LB_SETCURSEL, 0, 0 );\r
 }\r
 \r
-void GLT_TagsToList( HWND hDlg, char * tags )\r
+// low-level front-end: append line to text edit / list widget\r
+void\r
+GLT_AddToList( char *name )\r
 {\r
-    char * pc = tags;\r
-\r
-    SendDlgItemMessage( hDlg, IDC_GameListTags, LB_RESETCONTENT, 0, 0 );\r
-\r
-    while( *pc ) {\r
-        GLT_AddToList( hDlg, IDC_GameListTags, *pc, -1 );\r
-        pc++;\r
-    }\r
-\r
-    SendDlgItemMessage( hDlg, IDC_GameListTags, LB_ADDSTRING, 0, (LPARAM) "\t --- Hidden tags ---" );\r
-\r
-    pc = GLT_ALL_TAGS;\r
-\r
-    while( *pc ) {\r
-        if( strchr( tags, *pc ) == 0 ) {\r
-            GLT_AddToList( hDlg, IDC_GameListTags, *pc, -1 );\r
-        }\r
-        pc++;\r
+    if( name != 0 ) {\r
+            SendDlgItemMessage( gameListOptionsDialog, IDC_GameListTags, LB_ADDSTRING, 0, (LPARAM) name );\r
     }\r
-\r
-    SendDlgItemMessage( hDlg, IDC_GameListTags, LB_SETCURSEL, 0, 0 );\r
 }\r
 \r
-char GLT_ListItemToTag( HWND hDlg, int index )\r
+// low-level front-end: get line from text edit / list widget\r
+Boolean\r
+GLT_GetFromList( int index, char *name )\r
 {\r
-    char result = '\0';\r
-    char name[128];\r
-\r
-    GLT_Item * list = GLT_ItemInfo;\r
-\r
-    if( SendDlgItemMessage( hDlg, IDC_GameListTags, LB_GETTEXT, index, (LPARAM) name ) != LB_ERR ) {\r
-        while( list->id != 0 ) {\r
-            if( strcmp( list->name, name ) == 0 ) {\r
-                result = list->id;\r
-                break;\r
-            }\r
-\r
-            list++;\r
-        }\r
+    if( name != 0 ) {\r
+           if( SendDlgItemMessage( gameListOptionsDialog, IDC_GameListTags, LB_GETTEXT, index, (LPARAM) name ) != LB_ERR )\r
+               return TRUE;\r
     }\r
-\r
-    return result;\r
+    return FALSE;\r
 }\r
 \r
 void GLT_MoveSelection( HWND hDlg, int delta )\r
@@ -8877,20 +7962,15 @@ void GLT_MoveSelection( HWND hDlg, int delta )
 \r
 LRESULT CALLBACK GameListOptions_Proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
 {\r
-    static char glt[64];\r
-    static char * lpUserGLT;\r
-\r
     switch( message )\r
     {\r
     case WM_INITDIALOG:\r
-        lpUserGLT = (char *) lParam;\r
+       gameListOptionsDialog = hDlg; // [HGM] pass through global to keep out off back-end\r
         \r
-        strcpy( glt, lpUserGLT );\r
-\r
         CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER));\r
 \r
         /* Initialize list */\r
-        GLT_TagsToList( hDlg, glt );\r
+        GLT_TagsToList( lpUserGLT );\r
 \r
         SetFocus( GetDlgItem(hDlg, IDC_GameListTags) );\r
 \r
@@ -8899,19 +7979,7 @@ LRESULT CALLBACK GameListOptions_Proc(HWND hDlg, UINT message, WPARAM wParam, LP
     case WM_COMMAND:\r
         switch( LOWORD(wParam) ) {\r
         case IDOK:\r
-            {\r
-                char * pc = lpUserGLT;\r
-                int idx = 0;\r
-                int cnt = (int) SendDlgItemMessage( hDlg, IDC_GameListTags, LB_GETCOUNT, 0, 0 );\r
-                char id;\r
-\r
-                do {\r
-                    id = GLT_ListItemToTag( hDlg, idx );\r
-\r
-                    *pc++ = id;\r
-                    idx++;\r
-                } while( id != '\0' );\r
-            }\r
+           GLT_ParseList();\r
             EndDialog( hDlg, 0 );\r
             return TRUE;\r
         case IDCANCEL:\r
@@ -8919,13 +7987,11 @@ LRESULT CALLBACK GameListOptions_Proc(HWND hDlg, UINT message, WPARAM wParam, LP
             return TRUE;\r
 \r
         case IDC_GLT_Default:\r
-            strcpy( glt, GLT_DEFAULT_TAGS );\r
-            GLT_TagsToList( hDlg, glt );\r
+            GLT_TagsToList( GLT_DEFAULT_TAGS );\r
             return TRUE;\r
 \r
         case IDC_GLT_Restore:\r
-            strcpy( glt, lpUserGLT );\r
-            GLT_TagsToList( hDlg, glt );\r
+            GLT_TagsToList( appData.gameListTags );\r
             return TRUE;\r
 \r
         case IDC_GLT_Up:\r
@@ -8945,23 +8011,21 @@ LRESULT CALLBACK GameListOptions_Proc(HWND hDlg, UINT message, WPARAM wParam, LP
 \r
 int GameListOptions()\r
 {\r
-    char glt[64];\r
     int result;\r
     FARPROC lpProc = MakeProcInstance( (FARPROC) GameListOptions_Proc, hInst );\r
 \r
-    strcpy( glt, appData.gameListTags );\r
+    strcpy( lpUserGLT, appData.gameListTags );\r
 \r
-    result = DialogBoxParam( hInst, MAKEINTRESOURCE(DLG_GameListOptions), hwndMain, (DLGPROC)lpProc, (LPARAM)glt );\r
+    result = DialogBoxParam( hInst, MAKEINTRESOURCE(DLG_GameListOptions), hwndMain, (DLGPROC)lpProc, (LPARAM)lpUserGLT );\r
 \r
     if( result == 0 ) {\r
         /* [AS] Memory leak here! */\r
-        appData.gameListTags = strdup( glt ); \r
+        appData.gameListTags = strdup( lpUserGLT ); \r
     }\r
 \r
     return result;\r
 }\r
 \r
-\r
 VOID\r
 DisplayIcsInteractionTitle(char *str)\r
 {\r
@@ -8977,6 +8041,11 @@ DrawPosition(int fullRedraw, Board board)
   HDCDrawPosition(NULL, (BOOLEAN) fullRedraw, board); \r
 }\r
 \r
+void NotifyFrontendLogin()\r
+{\r
+       if (hwndConsole)\r
+               UpdateICSWidth(GetDlgItem(hwndConsole, OPT_ConsoleText));\r
+}\r
 \r
 VOID\r
 ResetFrontEnd()\r
@@ -8999,6 +8068,7 @@ CommentPopUp(char *title, char *str)
 {\r
   HWND hwnd = GetActiveWindow();\r
   EitherCommentPopUp(0, title, str, FALSE);\r
+  SAY(str);\r
   SetActiveWindow(hwnd);\r
 }\r
 \r
@@ -9009,7 +8079,7 @@ CommentPopDown(void)
   if (commentDialog) {\r
     ShowWindow(commentDialog, SW_HIDE);\r
   }\r
-  commentDialogUp = FALSE;\r
+  commentUp = FALSE;\r
 }\r
 \r
 VOID\r
@@ -9144,11 +8214,13 @@ void
 DisplayWhiteClock(long timeRemaining, int highlight)\r
 {\r
   HDC hdc;\r
-  hdc = GetDC(hwndMain);\r
   char *flag = whiteFlag && gameMode == TwoMachinesPlay ? "(!)" : "";\r
 \r
+  if(appData.noGUI) return;\r
+  hdc = GetDC(hwndMain);\r
   if (!IsIconic(hwndMain)) {\r
-    DisplayAClock(hdc, timeRemaining, highlight, flipClock ? &blackRect : &whiteRect, "White", flag);\r
+    DisplayAClock(hdc, timeRemaining, highlight, \r
+                       flipClock ? &blackRect : &whiteRect, "White", flag);\r
   }\r
   if (highlight && iconCurrent == iconBlack) {\r
     iconCurrent = iconWhite;\r
@@ -9168,9 +8240,11 @@ DisplayBlackClock(long timeRemaining, int highlight)
   HDC hdc;\r
   char *flag = blackFlag && gameMode == TwoMachinesPlay ? "(!)" : "";\r
 \r
+  if(appData.noGUI) return;\r
   hdc = GetDC(hwndMain);\r
   if (!IsIconic(hwndMain)) {\r
-    DisplayAClock(hdc, timeRemaining, highlight, flipClock ? &whiteRect : &blackRect, "Black", flag);\r
+    DisplayAClock(hdc, timeRemaining, highlight, \r
+                       flipClock ? &whiteRect : &blackRect, "Black", flag);\r
   }\r
   if (highlight && iconCurrent == iconWhite) {\r
     iconCurrent = iconBlack;\r
@@ -9230,11 +8304,12 @@ void
 ScheduleDelayedEvent(DelayedEventCallback cb, long millisec)\r
 {\r
   if (delayedTimerEvent != 0) {\r
-    if (appData.debugMode) {\r
+    if (appData.debugMode && cb != delayedTimerCallback) { // [HGM] alive: not too much debug\r
       fprintf(debugFP, "ScheduleDelayedEvent: event already scheduled\n");\r
     }\r
     KillTimer(hwndMain, delayedTimerEvent);\r
     delayedTimerEvent = 0;\r
+    if(delayedTimerCallback != cb) // [HGM] alive: do not "flush" same event, just postpone it\r
     delayedTimerCallback();\r
   }\r
   delayedTimerCallback = cb;\r
@@ -9261,6 +8336,23 @@ CancelDelayedEvent()
   }\r
 }\r
 \r
+DWORD GetWin32Priority(int nice)\r
+{ // [HGM] nice: translate Unix nice() value to indows priority class. (Code stolen from Polyglot 1.4w11)\r
+/*\r
+REALTIME_PRIORITY_CLASS     0x00000100\r
+HIGH_PRIORITY_CLASS         0x00000080\r
+ABOVE_NORMAL_PRIORITY_CLASS 0x00008000\r
+NORMAL_PRIORITY_CLASS       0x00000020\r
+BELOW_NORMAL_PRIORITY_CLASS 0x00004000\r
+IDLE_PRIORITY_CLASS         0x00000040\r
+*/\r
+        if (nice < -15) return 0x00000080;\r
+        if (nice < 0)   return 0x00008000;\r
+        if (nice == 0)  return 0x00000020;\r
+        if (nice < 15)  return 0x00004000;\r
+        return 0x00000040;\r
+}\r
+\r
 /* Start a child process running the given program.\r
    The process's standard output can be read from "from", and its\r
    standard input can be written to "to".\r
@@ -9376,6 +8468,11 @@ StartChildProcess(char *cmdLine, char *dir, ProcRef *pr)
     return err;\r
   }\r
 \r
+  if (appData.niceEngines){ // [HGM] nice: adjust engine proc priority\r
+    if(appData.debugMode) fprintf(debugFP, "nice engine proc to %d\n", appData.niceEngines);\r
+    SetPriorityClass(piProcInfo.hProcess, GetWin32Priority(appData.niceEngines));\r
+  }\r
+\r
   /* Close the handles we don't need in the parent */\r
   CloseHandle(piProcInfo.hThread);\r
   CloseHandle(hChildStdinRd);\r
@@ -9427,7 +8524,7 @@ DestroyChildProcess(ProcRef pr, int/*boolean*/ signal)
         result = TerminateProcess( cp->hProcess, 0 );\r
 \r
         if ( appData.debugMode) {\r
-            fprintf( debugFP, "Terminating process %u, result=%d\n", cp->pid, result );\r
+            fprintf( debugFP, "Terminating process %lu, result=%d\n", cp->pid, result );\r
         }\r
     }\r
     else if( signal == 10 ) {\r
@@ -9437,7 +8534,7 @@ DestroyChildProcess(ProcRef pr, int/*boolean*/ signal)
             result = TerminateProcess( cp->hProcess, 0 );\r
 \r
             if ( appData.debugMode) {\r
-                fprintf( debugFP, "Process %u still alive after timeout, killing... result=%d\n", cp->pid, result );\r
+                fprintf( debugFP, "Process %lu still alive after timeout, killing... result=%d\n", cp->pid, result );\r
             }\r
 \r
         }\r
@@ -9914,6 +9011,11 @@ RemoveInputSource(InputSourceRef isr)
   }\r
 }\r
 \r
+int no_wrap(char *message, int count)\r
+{\r
+    ConsoleOutput(message, count, FALSE);\r
+    return count;\r
+}\r
 \r
 int\r
 OutputToProcess(ProcRef pr, char *message, int count, int *outError)\r
@@ -9922,11 +9024,32 @@ OutputToProcess(ProcRef pr, char *message, int count, int *outError)
   int outCount = SOCKET_ERROR;\r
   ChildProc *cp = (ChildProc *) pr;\r
   static OVERLAPPED ovl;\r
+  static int line = 0;\r
 \r
-  if (pr == NoProc) {\r
-    ConsoleOutput(message, count, FALSE);\r
-    return count;\r
-  } \r
+  if (pr == NoProc)\r
+  {\r
+    if (appData.noJoin || !appData.useInternalWrap)\r
+      return no_wrap(message, count);\r
+    else\r
+    {\r
+      int width = get_term_width();\r
+      int len = wrap(NULL, message, count, width, &line);\r
+      char *msg = malloc(len);\r
+      int dbgchk;\r
+\r
+      if (!msg)\r
+        return no_wrap(message, count);\r
+      else\r
+      {\r
+        dbgchk = wrap(msg, message, count, width, &line);\r
+        if (dbgchk != len && appData.debugMode)\r
+            fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len);\r
+        ConsoleOutput(msg, len, FALSE);\r
+        free(msg);\r
+        return len;\r
+      }\r
+    }\r
+  }\r
 \r
   if (ovl.hEvent == NULL) {\r
     ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);\r
@@ -10010,126 +9133,6 @@ StartAnalysisClock()
                                        (UINT) 2000, NULL);\r
 }\r
 \r
-LRESULT CALLBACK\r
-AnalysisDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
-  static HANDLE hwndText;\r
-  RECT rect;\r
-  static int sizeX, sizeY;\r
-  int newSizeX, newSizeY, flags;\r
-  MINMAXINFO *mmi;\r
-\r
-  switch (message) {\r
-  case WM_INITDIALOG: /* message: initialize dialog box */\r
-    /* Initialize the dialog items */\r
-    hwndText = GetDlgItem(hDlg, OPT_AnalysisText);\r
-    SetWindowText(hDlg, analysisTitle);\r
-    SetDlgItemText(hDlg, OPT_AnalysisText, analysisText);\r
-    /* Size and position the dialog */\r
-    if (!analysisDialog) {\r
-      analysisDialog = hDlg;\r
-      flags = SWP_NOZORDER;\r
-      GetClientRect(hDlg, &rect);\r
-      sizeX = rect.right;\r
-      sizeY = rect.bottom;\r
-      if (analysisX != CW_USEDEFAULT && analysisY != CW_USEDEFAULT &&\r
-         analysisW != CW_USEDEFAULT && analysisH != CW_USEDEFAULT) {\r
-       WINDOWPLACEMENT wp;\r
-       EnsureOnScreen(&analysisX, &analysisY);\r
-       wp.length = sizeof(WINDOWPLACEMENT);\r
-       wp.flags = 0;\r
-       wp.showCmd = SW_SHOW;\r
-       wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;\r
-       wp.rcNormalPosition.left = analysisX;\r
-       wp.rcNormalPosition.right = analysisX + analysisW;\r
-       wp.rcNormalPosition.top = analysisY;\r
-       wp.rcNormalPosition.bottom = analysisY + analysisH;\r
-       SetWindowPlacement(hDlg, &wp);\r
-\r
-       GetClientRect(hDlg, &rect);\r
-       newSizeX = rect.right;\r
-       newSizeY = rect.bottom;\r
-        ResizeEditPlusButtons(hDlg, hwndText, sizeX, sizeY,\r
-                             newSizeX, newSizeY);\r
-       sizeX = newSizeX;\r
-       sizeY = newSizeY;\r
-      }\r
-    }\r
-    return FALSE;\r
-\r
-  case WM_COMMAND: /* message: received a command */\r
-    switch (LOWORD(wParam)) {\r
-    case IDCANCEL:\r
-      EditGameEvent();\r
-      return TRUE;\r
-    default:\r
-      break;\r
-    }\r
-    break;\r
-\r
-  case WM_SIZE:\r
-    newSizeX = LOWORD(lParam);\r
-    newSizeY = HIWORD(lParam);\r
-    ResizeEditPlusButtons(hDlg, hwndText, sizeX, sizeY, newSizeX, newSizeY);\r
-    sizeX = newSizeX;\r
-    sizeY = newSizeY;\r
-    break;\r
-\r
-  case WM_GETMINMAXINFO:\r
-    /* Prevent resizing window too small */\r
-    mmi = (MINMAXINFO *) lParam;\r
-    mmi->ptMinTrackSize.x = 100;\r
-    mmi->ptMinTrackSize.y = 100;\r
-    break;\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-VOID\r
-AnalysisPopUp(char* title, char* str)\r
-{\r
-  FARPROC lpProc;\r
-  char *p, *q;\r
-\r
-  /* [AS] */\r
-  EngineOutputPopUp();\r
-  return;\r
-\r
-  if (str == NULL) str = "";\r
-  p = (char *) malloc(2 * strlen(str) + 2);\r
-  q = p;\r
-  while (*str) {\r
-    if (*str == '\n') *q++ = '\r';\r
-    *q++ = *str++;\r
-  }\r
-  *q = NULLCHAR;\r
-  if (analysisText != NULL) free(analysisText);\r
-  analysisText = p;\r
-\r
-  if (analysisDialog) {\r
-    SetWindowText(analysisDialog, title);\r
-    SetDlgItemText(analysisDialog, OPT_AnalysisText, analysisText);\r
-    ShowWindow(analysisDialog, SW_SHOW);\r
-  } else {\r
-    analysisTitle = title;\r
-    lpProc = MakeProcInstance((FARPROC)AnalysisDialog, hInst);\r
-    CreateDialog(hInst, MAKEINTRESOURCE(DLG_Analysis),\r
-                hwndMain, (DLGPROC)lpProc);\r
-    FreeProcInstance(lpProc);\r
-  }\r
-  analysisDialogUp = TRUE;  \r
-}\r
-\r
-VOID\r
-AnalysisPopDown()\r
-{\r
-  if (analysisDialog) {\r
-    ShowWindow(analysisDialog, SW_HIDE);\r
-  }\r
-  analysisDialogUp = FALSE;  \r
-}\r
-\r
-\r
 VOID\r
 SetHighlights(int fromX, int fromY, int toX, int toY)\r
 {\r
@@ -10186,6 +9189,24 @@ static void Tween( POINT * start, POINT * mid, POINT * finish, int factor,
      POINT frames[], int * nFrames);\r
 \r
 \r
+void\r
+AnimateAtomicCapture(int fromX, int fromY, int toX, int toY, int nFrames)\r
+{      // [HGM] atomic: animate blast wave\r
+       int i;\r
+if(appData.debugMode) fprintf(debugFP, "exploding (%d,%d)\n", toX, toY);\r
+       explodeInfo.fromX = fromX;\r
+       explodeInfo.fromY = fromY;\r
+       explodeInfo.toX = toX;\r
+       explodeInfo.toY = toY;\r
+       for(i=1; i<nFrames; i++) {\r
+           explodeInfo.radius = (i*180)/(nFrames-1);\r
+           DrawPosition(FALSE, NULL);\r
+           Sleep(appData.animSpeed);\r
+       }\r
+       explodeInfo.radius = 0;\r
+       DrawPosition(TRUE, NULL);\r
+}\r
+\r
 #define kFactor 4\r
 \r
 void\r
@@ -10246,6 +9267,9 @@ AnimateMove(board, fromX, fromY, toX, toY)
   animInfo.pos = finish;\r
   DrawPosition(FALSE, NULL);\r
   animInfo.piece = EmptySquare;\r
+  if(gameInfo.variant == VariantAtomic && \r
+     (board[toY][toX] != EmptySquare || fromX != toX && (piece == WhitePawn || piece == BlackPawn) ) )\r
+       AnimateAtomicCapture(fromX, fromY, toX, toY, 2*nFrames);\r
 }\r
 \r
 /*      Convert board position to corner of screen rect and color       */\r
@@ -10309,30 +9333,7 @@ Tween(start, mid, finish, factor, frames, nFrames)
 void\r
 HistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current )\r
 {\r
-#if 0\r
-    char buf[256];\r
-\r
-    sprintf( buf, "HistorySet: first=%d, last=%d, current=%d (%s)\n",\r
-        first, last, current, current >= 0 ? movelist[current] : "n/a" );\r
-\r
-    OutputDebugString( buf );\r
-#endif\r
-\r
     MoveHistorySet( movelist, first, last, current, pvInfoList );\r
 \r
     EvalGraphSet( first, last, current, pvInfoList );\r
 }\r
-\r
-void SetProgramStats( FrontEndProgramStats * stats )\r
-{\r
-#if 0\r
-    char buf[1024];\r
-\r
-    sprintf( buf, "SetStats for %d: depth=%d, nodes=%lu, score=%5.2f, time=%5.2f, pv=%s\n",\r
-        stats->which, stats->depth, stats->nodes, stats->score / 100.0, stats->time / 100.0, stats->pv == 0 ? "n/a" : stats->pv );\r
-\r
-    OutputDebugString( buf );\r
-#endif\r
-\r
-    EngineOutputUpdate( stats );\r
-}\r