Enhancement of the way -autoLogo decides which logos to display
[xboard.git] / winboard / winboard.c
index f4e6c0d..48a6f3b 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
@@ -181,6 +188,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 +201,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
@@ -535,6 +544,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
@@ -650,13 +674,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
@@ -1236,6 +1266,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
@@ -1276,6 +1308,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
@@ -3012,7 +3045,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
@@ -3125,7 +3158,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
@@ -3139,19 +3172,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
@@ -4223,7 +4256,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
@@ -4232,13 +4265,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
@@ -4479,7 +4512,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
@@ -4498,13 +4531,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
@@ -4848,7 +4930,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
@@ -4857,7 +4939,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
@@ -5026,7 +5108,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
@@ -5097,9 +5186,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
@@ -5905,6 +5994,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
@@ -6246,6 +6336,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
@@ -6253,11 +6344,17 @@ 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
+           boardX = lpwp->x;\r
+            boardY = lpwp->y;\r
         }\r
     }\r
     break;\r
@@ -7246,6 +7343,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
@@ -8215,7 +8313,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
@@ -8233,7 +8331,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
@@ -9489,7 +9597,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
@@ -9513,7 +9621,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
@@ -10556,6 +10664,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
@@ -10616,6 +10742,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