changed font in engine output window
[xboard.git] / winboard / winboard.c
index bdfc1f3..813445b 100644 (file)
@@ -103,6 +103,7 @@ void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);
 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
 \r
 typedef struct {\r
   ChessSquare piece;  \r
@@ -130,6 +131,12 @@ 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
@@ -145,9 +152,10 @@ char installDir[MSG_SIZ];
 \r
 BoardSize boardSize;\r
 BOOLEAN chessProgram;\r
-static int boardX, boardY, consoleX, consoleY, consoleW, consoleH;\r
+static int boardX, boardY;\r
+int  minX, minY; // [HGM] placement: volatile limits on upper-left corner\r
 static int squareSize, lineGap, minorSize;\r
-static int winWidth, winHeight;\r
+static int winWidth, winHeight, 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
@@ -181,6 +189,7 @@ 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
+  explodeBrush,     /* [HGM] atomic */\r
   whitePieceBrush, blackPieceBrush, iconBkgndBrush /*, outlineBrush*/;\r
 static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];\r
 static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];\r
@@ -193,6 +202,7 @@ static HICON iconWhite, iconBlack, iconCurrent;
 static int doingSizing = FALSE;\r
 static int lastSizing = 0;\r
 static int prevStderrPort;\r
+static HBITMAP userLogo;\r
 \r
 /* [AS] Support for background textures */\r
 #define BACK_TEXTURE_MODE_DISABLED      0\r
@@ -418,6 +428,8 @@ HWND engineOutputDialog = NULL;
 BOOLEAN engineOutputDialogUp = FALSE;\r
 \r
 WindowPlacement wpEngineOutput;\r
+WindowPlacement wpGameList;\r
+WindowPlacement wpConsole;\r
 \r
 VOID MoveHistoryPopUp();\r
 VOID MoveHistoryPopDown();\r
@@ -495,6 +507,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
   if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {\r
     return (FALSE);\r
   }\r
+\r
 //  InitCommonControlsEx(&ex);\r
   InitCommonControls();\r
 \r
@@ -534,6 +547,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
@@ -576,16 +604,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
   /* 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 < 0) *x = 0;\r
-  if (*y < 0) *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
@@ -604,6 +630,7 @@ 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
   if (appData.debugMode) {\r
     debugFP = fopen(appData.nameOfDebugFile, "w");\r
@@ -649,13 +676,19 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
           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
-       char buf[MSG_SIZ];\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
@@ -665,11 +698,11 @@ 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
@@ -717,7 +750,7 @@ 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(&boardX, &boardY, minX, minY);\r
   wp.length = sizeof(WINDOWPLACEMENT);\r
   wp.flags = 0;\r
   wp.showCmd = nCmdShow;\r
@@ -731,12 +764,6 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
   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
@@ -754,7 +781,8 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
 typedef enum {\r
   ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone, \r
   ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,\r
-  ArgSettingsFilename\r
+  ArgSettingsFilename,\r
+  ArgX, ArgY, ArgZ // [HGM] placement: for window-placement options stored relative to main window\r
 } ArgType;\r
 \r
 typedef struct {\r
@@ -1090,28 +1118,6 @@ ArgDescriptor argDescriptors[] = {
   { "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
@@ -1186,25 +1192,6 @@ ArgDescriptor argDescriptors[] = {
   { "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
@@ -1235,6 +1222,8 @@ ArgDescriptor argDescriptors[] = {
   { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE },\r
   { "firstOptions", ArgString, (LPVOID) &appData.firstOptions, FALSE },\r
   { "secondOptions", ArgString, (LPVOID) &appData.secondOptions, FALSE },\r
+  { "firstNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride1, FALSE },\r
+  { "secondNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride2, FALSE },\r
 \r
 #ifdef ZIPPY\r
   { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },\r
@@ -1275,6 +1264,7 @@ ArgDescriptor argDescriptors[] = {
   { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },\r
   { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },\r
   { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },\r
+  { "zippyShortGame", ArgInt, (LPVOID)&appData.zippyShortGame, 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
@@ -1290,6 +1280,53 @@ ArgDescriptor argDescriptors[] = {
   { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },\r
   { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },\r
   { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE },\r
+\r
+  // [HGM] placement: put all window layouts last in ini file, but man X,Y before all others\r
+  { "minX", ArgZ, (LPVOID) &minX, FALSE }, // [HGM] placement: to make suer auxialary windows can be placed\r
+  { "minY", ArgZ, (LPVOID) &minY, FALSE },\r
+  { "winWidth",  ArgInt, (LPVOID) &winWidth,  TRUE }, // [HGM] placement: dummies to remember right & bottom\r
+  { "winHeight", ArgInt, (LPVOID) &winHeight, TRUE }, //       for attaching auxiliary windows to them\r
+  { "x", ArgInt, (LPVOID) &boardX, TRUE },\r
+  { "y", ArgInt, (LPVOID) &boardY, TRUE },\r
+  { "icsX", ArgX,   (LPVOID) &wpConsole.x, TRUE },\r
+  { "icsY", ArgY,   (LPVOID) &wpConsole.y, TRUE },\r
+  { "icsW", ArgInt, (LPVOID) &wpConsole.width, TRUE },\r
+  { "icsH", ArgInt, (LPVOID) &wpConsole.height, TRUE },\r
+  { "analysisX", ArgX,   (LPVOID) &analysisX, FALSE }, // [HGM] placement: analysis window no longer exists\r
+  { "analysisY", ArgY,   (LPVOID) &analysisY, FALSE }, //       provided for compatibility with old ini files\r
+  { "analysisW", ArgInt, (LPVOID) &analysisW, FALSE },\r
+  { "analysisH", ArgInt, (LPVOID) &analysisH, FALSE },\r
+  { "commentX", ArgX,   (LPVOID) &commentX, TRUE },\r
+  { "commentY", ArgY,   (LPVOID) &commentY, TRUE },\r
+  { "commentW", ArgInt, (LPVOID) &commentW, TRUE },\r
+  { "commentH", ArgInt, (LPVOID) &commentH, TRUE },\r
+  { "tagsX", ArgX,   (LPVOID) &editTagsX, TRUE },\r
+  { "tagsY", ArgY,   (LPVOID) &editTagsY, TRUE },\r
+  { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },\r
+  { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },\r
+  { "gameListX", ArgX,   (LPVOID) &wpGameList.x, TRUE },\r
+  { "gameListY", ArgY,   (LPVOID) &wpGameList.y, TRUE },\r
+  { "gameListW", ArgInt, (LPVOID) &wpGameList.width, TRUE },\r
+  { "gameListH", ArgInt, (LPVOID) &wpGameList.height, TRUE },\r
+  /* [AS] Layout stuff */\r
+  { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },\r
+  { "moveHistoryX", ArgX,   (LPVOID) &wpMoveHistory.x, TRUE },\r
+  { "moveHistoryY", ArgY,   (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", ArgX,   (LPVOID) &wpEvalGraph.x, TRUE },\r
+  { "evalGraphY", ArgY,   (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", ArgX,   (LPVOID) &wpEngineOutput.x, TRUE },\r
+  { "engineOutputY", ArgY,   (LPVOID) &wpEngineOutput.y, TRUE },\r
+  { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },\r
+  { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },\r
+\r
   { NULL, ArgNone, NULL, FALSE }\r
 };\r
 \r
@@ -1428,8 +1465,14 @@ ParseSettingsFile(char *name, char fullname[MSG_SIZ])
 {\r
   char *dummy;\r
   FILE *f;\r
+  int ok; char buf[MSG_SIZ];\r
 \r
-  if (SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy)) {\r
+  ok = SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy);\r
+  if(!ok && strchr(name, '.') == NULL) { // [HGM] append default file-name extension '.ini' when needed\r
+    sprintf(buf, "%s.ini", name);\r
+    ok = SearchPath(installDir, buf, NULL, MSG_SIZ, fullname, &dummy);\r
+  }\r
+  if (ok) {\r
     f = fopen(fullname, "r");\r
     if (f != NULL) {\r
       ParseArgs(FileGet, f);\r
@@ -1614,6 +1657,19 @@ ParseArgs(GetFunc get, void *cl)
       *(int *) ad->argLoc = atoi(argValue);\r
       break;\r
 \r
+    case ArgX:\r
+      *(int *) ad->argLoc = atoi(argValue) + boardX; // [HGM] placement: translate stored relative to absolute \r
+      break;\r
+\r
+    case ArgY:\r
+      *(int *) ad->argLoc = atoi(argValue) + boardY; // (this is really kludgey, it should be done where used...)\r
+      break;\r
+\r
+    case ArgZ:\r
+      *(int *) ad->argLoc = atoi(argValue);\r
+      EnsureOnScreen(&boardX, &boardY, minX, minY); \r
+      break;\r
+\r
     case ArgFloat:\r
       *(float *) ad->argLoc = (float) atof(argValue);\r
       break;\r
@@ -1877,10 +1933,6 @@ InitAppData(LPSTR lpCmdLine)
   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
@@ -1893,10 +1945,6 @@ InitAppData(LPSTR lpCmdLine)
   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
@@ -1954,9 +2002,11 @@ InitAppData(LPSTR lpCmdLine)
   appData.firstOptions = "";\r
   appData.secondOptions = "";\r
 \r
+  InitWindowPlacement( &wpGameList );\r
   InitWindowPlacement( &wpMoveHistory );\r
   InitWindowPlacement( &wpEvalGraph );\r
   InitWindowPlacement( &wpEngineOutput );\r
+  InitWindowPlacement( &wpConsole );\r
 \r
   /* [HGM] User-selectable board size, adjudication control, miscellaneous */\r
   appData.NrFiles      = -1;\r
@@ -2169,10 +2219,10 @@ SaveSettings(char* name)
 \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
+    wpConsole.x = wp.rcNormalPosition.left;\r
+    wpConsole.y = wp.rcNormalPosition.top;\r
+    wpConsole.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
+    wpConsole.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
   }\r
 \r
   if (analysisDialog) {\r
@@ -2201,10 +2251,10 @@ SaveSettings(char* name)
 \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
+    wpGameList.x = wp.rcNormalPosition.left;\r
+    wpGameList.y = wp.rcNormalPosition.top;\r
+    wpGameList.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
+    wpGameList.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
   }\r
 \r
   /* [AS] Move history */\r
@@ -2270,8 +2320,15 @@ SaveSettings(char* name)
       }\r
       break;\r
     case ArgInt:\r
+    case ArgZ:\r
       fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);\r
       break;\r
+    case ArgX:\r
+      fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardX); // [HGM] placement: stor relative value\r
+      break;\r
+    case ArgY:\r
+      fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardY);\r
+      break;\r
     case ArgFloat:\r
       fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);\r
       break;\r
@@ -3005,7 +3062,7 @@ InitDrawingColors()
   whitePieceBrush = CreateSolidBrush(whitePieceColor);\r
   blackPieceBrush = CreateSolidBrush(blackPieceColor);\r
   iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));\r
-\r
+  explodeBrush = CreateSolidBrush(highlightSquareColor); // [HGM] atomic\r
   /* [AS] Force rendering of the font-based pieces */\r
   if( fontBitmapSquareSize > 0 ) {\r
     fontBitmapSquareSize = 0;\r
@@ -3060,7 +3117,7 @@ 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
@@ -3070,6 +3127,11 @@ InitDrawingSizes(BoardSize boardSize, int flags)
   /* [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 = boardX; //[HGM] placement: remember previous window params\r
+  oldRect.top = boardY;\r
+  oldRect.right = boardX + winWidth;\r
+  oldRect.bottom = boardY + winHeight;\r
+\r
   tinyLayout = sizeInfo[boardSize].tinyLayout;\r
   smallLayout = sizeInfo[boardSize].smallLayout;\r
   squareSize = sizeInfo[boardSize].squareSize;\r
@@ -3118,7 +3180,7 @@ InitDrawingSizes(BoardSize boardSize, int flags)
   ReleaseDC(hwndMain, hdc);\r
 \r
   /* Compute where everything goes */\r
-  if(first.programLogo || second.programLogo) {\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
@@ -3132,19 +3194,19 @@ InitDrawingSizes(BoardSize boardSize, int flags)
        rightLogoRect.bottom = OUTER_MARGIN + logoHeight;\r
 \r
 \r
-    blackRect.left = leftLogoRect.right;\r
-    blackRect.right = rightLogoRect.left;\r
-    blackRect.top = OUTER_MARGIN;\r
-    blackRect.bottom = blackRect.top + clockSize.cy;\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
-    whiteRect.left = blackRect.left ;\r
-    whiteRect.right = blackRect.right;\r
-    whiteRect.top = blackRect.bottom;\r
-    whiteRect.bottom = leftLogoRect.bottom;\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 + logoHeight;\r
+    whiteRect.top = OUTER_MARGIN;\r
     whiteRect.bottom = whiteRect.top + clockSize.cy;\r
 \r
     blackRect.left = whiteRect.right + INNER_MARGIN;\r
@@ -3170,13 +3232,25 @@ InitDrawingSizes(BoardSize boardSize, int flags)
 \r
   sizeInfo[boardSize].cliWidth = boardRect.right + OUTER_MARGIN;\r
   sizeInfo[boardSize].cliHeight = boardRect.bottom + OUTER_MARGIN;\r
-  if(suppressVisibleEffects) return; // [HGM] when called for filling sizeInfo only\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
+  winWidth = winW;  // [HGM] placement: set through temporary which can used by initial sizing choice\r
+  winHeight = winH; //       without disturbing window attachments\r
   GetWindowRect(hwndMain, &wrect);\r
   SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,\r
               SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);\r
+\r
+  // [HGM] placement: let attached windows follow size change.\r
+  ReattachAfterSize( &oldRect, winWidth, winHeight, moveHistoryDialog, &wpMoveHistory );\r
+  ReattachAfterSize( &oldRect, winWidth, winHeight, evalGraphDialog, &wpEvalGraph );\r
+  ReattachAfterSize( &oldRect, winWidth, winHeight, engineOutputDialog, &wpEngineOutput );\r
+  ReattachAfterSize( &oldRect, winWidth, winHeight, gameListDialog, &wpGameList );\r
+  ReattachAfterSize( &oldRect, winWidth, winHeight, hwndConsole, &wpConsole );\r
+\r
   /* compensate if menu bar wrapped */\r
   GetClientRect(hwndMain, &crect);\r
   offby = boardRect.bottom + OUTER_MARGIN - crect.bottom;\r
@@ -3286,8 +3360,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
@@ -4216,7 +4288,7 @@ void fputDW(FILE *f, int x)
 #define MAX_CLIPS 200   /* more than enough */\r
 \r
 VOID\r
-DrawLogoOnDC(HDC hdc, RECT logoRect, ChessProgramState *cps)\r
+DrawLogoOnDC(HDC hdc, RECT logoRect, HBITMAP logo)\r
 {\r
 //  HBITMAP bufferBitmap;\r
   BITMAP bi;\r
@@ -4225,13 +4297,13 @@ DrawLogoOnDC(HDC hdc, RECT logoRect, ChessProgramState *cps)
   HBITMAP hbm;\r
   int w = 100, h = 50;\r
 \r
-  if(cps->programLogo == NULL) return;\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, (HBITMAP) cps->programLogo);\r
-  if( GetObject( cps->programLogo, sizeof(bi), &bi ) > 0 ) {\r
+  hbm = SelectObject(tmphdc, logo);\r
+  if( GetObject( logo, sizeof(bi), &bi ) > 0 ) {\r
             w = bi.bmWidth;\r
             h = bi.bmHeight;\r
   }\r
@@ -4472,7 +4544,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
@@ -4491,13 +4563,62 @@ 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
-\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
   if(logoHeight) {\r
-       DrawLogoOnDC(hdc, leftLogoRect, flipClock ? &second : &first);\r
-       DrawLogoOnDC(hdc, rightLogoRect, flipClock ? &first : &second);\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
@@ -4841,7 +4962,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                   gameMode == MachinePlaysWhite) {\r
          CallFlagEvent();\r
         } else if (gameMode == EditGame) {\r
-          AdjustClock((logoHeight > 0 ? flipView: flipClock), -1);\r
+          AdjustClock(flipClock, -1);\r
         }\r
       } else if (PtInRect((LPRECT) &blackRect, pt)) {\r
        if (gameMode == EditPosition) {\r
@@ -4850,7 +4971,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                   gameMode == MachinePlaysBlack) {\r
          CallFlagEvent();\r
         } else if (gameMode == EditGame) {\r
-          AdjustClock(!(logoHeight > 0 ? flipView: flipClock), -1);\r
+          AdjustClock(!flipClock, -1);\r
        }\r
       }\r
       if (!appData.highlightLastMove) {\r
@@ -5019,7 +5140,14 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                    break;\r
                  } else\r
                PromotionPopup(hwnd); /* [HGM] Popup now calls FinishMove */\r
-        } else FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);\r
+          } else {\r
+           if(saveAnimate /* ^$!%@#$!$ */  && gameInfo.variant == VariantAtomic \r
+                         && (boards[currentMove][toY][toX] != EmptySquare || \r
+                                       moveType == WhiteCapturesEnPassant || \r
+                                       moveType == BlackCapturesEnPassant   ) )\r
+               AnimateAtomicCapture(fromX, fromY, toX, toY, 20);\r
+           FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);\r
+         }\r
       }\r
       if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);\r
       appData.animate = saveAnimate;\r
@@ -5090,9 +5218,9 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     if(y == -2) {\r
       /* [HGM] right mouse button in clock area edit-game mode ups clock */\r
       if (PtInRect((LPRECT) &whiteRect, pt)) {\r
-          if (gameMode == EditGame) AdjustClock((logoHeight > 0 ? flipView: flipClock), 1);\r
+          if (gameMode == EditGame) AdjustClock(flipClock, 1);\r
       } else if (PtInRect((LPRECT) &blackRect, pt)) {\r
-          if (gameMode == EditGame) AdjustClock(!(logoHeight > 0 ? flipView: flipClock), 1);\r
+          if (gameMode == EditGame) AdjustClock(!flipClock, 1);\r
       }\r
     }\r
     DrawPosition(TRUE, NULL);\r
@@ -5898,6 +6026,7 @@ 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_GeneralOptions:\r
@@ -6239,6 +6368,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
@@ -6246,11 +6376,19 @@ 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   = boardX;           //              replace by these 4 lines to reconstruct old rect\r
+           rcMain.right  = boardX + winWidth;\r
+           rcMain.top    = boardY;\r
+           rcMain.bottom = boardY + winHeight;\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
+           boardX = lpwp->x;\r
+            boardY = lpwp->y;\r
         }\r
     }\r
     break;\r
@@ -7019,7 +7157,7 @@ CommentDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
       if (commentX != CW_USEDEFAULT && commentY != CW_USEDEFAULT &&\r
          commentW != CW_USEDEFAULT && commentH != CW_USEDEFAULT) {\r
        WINDOWPLACEMENT wp;\r
-       EnsureOnScreen(&commentX, &commentY);\r
+       EnsureOnScreen(&commentX, &commentY, 0, 0);\r
        wp.length = sizeof(WINDOWPLACEMENT);\r
        wp.flags = 0;\r
        wp.showCmd = SW_SHOW;\r
@@ -7239,6 +7377,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
@@ -7962,40 +8101,37 @@ 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
-#if 0 \r
-   // [HGM] Chessknight's change 2004-07-13\r
    else { /* Determine Defaults */\r
        WINDOWPLACEMENT wp;\r
-       consoleX = winWidth + 1;\r
-       consoleY = boardY;\r
-       consoleW = screenWidth -  winWidth;\r
-       consoleH = winHeight;\r
-       EnsureOnScreen(&consoleX, &consoleY);\r
+       wpConsole.x = winWidth + 1;\r
+       wpConsole.y = boardY;\r
+       wpConsole.width = screenWidth -  winWidth;\r
+       wpConsole.height = winHeight;\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
-#endif\r
     return FALSE;\r
 \r
   case WM_SETFOCUS:\r
@@ -8208,7 +8344,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
@@ -8226,7 +8362,17 @@ DisplayAClock(HDC hdc, int timeRemaining, int highlight,
   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", TimeString(timeRemaining), 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
@@ -9482,7 +9628,7 @@ DisplayWhiteClock(long timeRemaining, int highlight)
   hdc = GetDC(hwndMain);\r
   if (!IsIconic(hwndMain)) {\r
     DisplayAClock(hdc, timeRemaining, highlight, \r
-                       (logoHeight > 0 ? flipView: flipClock) ? &blackRect : &whiteRect, "White", flag);\r
+                       flipClock ? &blackRect : &whiteRect, "White", flag);\r
   }\r
   if (highlight && iconCurrent == iconBlack) {\r
     iconCurrent = iconWhite;\r
@@ -9506,7 +9652,7 @@ DisplayBlackClock(long timeRemaining, int highlight)
   hdc = GetDC(hwndMain);\r
   if (!IsIconic(hwndMain)) {\r
     DisplayAClock(hdc, timeRemaining, highlight, \r
-                       (logoHeight > 0 ? flipView: flipClock) ? &whiteRect : &blackRect, "Black", flag);\r
+                       flipClock ? &whiteRect : &blackRect, "Black", flag);\r
   }\r
   if (highlight && iconCurrent == iconWhite) {\r
     iconCurrent = iconBlack;\r
@@ -10393,7 +10539,7 @@ AnalysisDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
       if (analysisX != CW_USEDEFAULT && analysisY != CW_USEDEFAULT &&\r
          analysisW != CW_USEDEFAULT && analysisH != CW_USEDEFAULT) {\r
        WINDOWPLACEMENT wp;\r
-       EnsureOnScreen(&analysisX, &analysisY);\r
+       EnsureOnScreen(&analysisX, &analysisY, 0, 0);\r
        wp.length = sizeof(WINDOWPLACEMENT);\r
        wp.flags = 0;\r
        wp.showCmd = SW_SHOW;\r
@@ -10549,6 +10695,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
@@ -10609,6 +10773,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