Provide menus for editing WinBoard engine and server lists
[xboard.git] / winboard / winboard.c
index afef6ae..24fa20e 100644 (file)
@@ -105,7 +105,6 @@ 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
 void DisplayMove P((int moveNumber));\r
 Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen));\r
 void ChatPopUp P((char *s));\r
@@ -187,6 +186,7 @@ COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
 HPALETTE hPal;\r
 ColorClass currentColorClass;\r
 \r
+static HWND savedHwnd;\r
 HWND hCommPort = NULL;    /* currently open comm port */\r
 static HWND hwndPause;    /* pause button */\r
 static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */\r
@@ -306,7 +306,7 @@ int dialogItems[][40] = {
   OPT_VariantBughouse, OPT_VariantTwilight, OPT_VariantShogi, OPT_VariantSuper,\r
   OPT_VariantKnightmate, OPT_VariantBerolina, OPT_VariantCylinder, OPT_VariantFairy,\r
   OPT_VariantMakruk, OPT_VariantGothic, OPT_VariantCapablanca, OPT_VariantJanus,\r
-  OPT_VariantCRC, OPT_VariantFalcon, OPT_VariantCourier, OPT_VariantGreat,\r
+  OPT_VariantCRC, OPT_VariantFalcon, OPT_VariantCourier, OPT_VariantGreat, OPT_VariantSChess,\r
   OPT_VariantShatranj, OPT_VariantXiangqi, GPB_Variant, GPB_Board, IDC_Height,\r
   IDC_Width, IDC_Hand, IDC_Pieces, IDC_Def }, \r
 { DLG_Fonts, IDOK, IDCANCEL, OPT_ChooseClockFont, OPT_ChooseMessageFont,\r
@@ -334,7 +334,7 @@ static char languageBuf[50000], *foreign[1000], *english[1000], *languageFile[MS
 static int lastChecked;\r
 static char oldLanguage[MSG_SIZ], *menuText[10][30];\r
 extern int tinyLayout;\r
-extern char * menuBarText[][8];\r
+extern char * menuBarText[][10];\r
 \r
 void\r
 LoadLanguageFile(char *name)\r
@@ -549,10 +549,10 @@ MyButtonDesc buttonDesc[N_BUTTONS] =
 };\r
 \r
 int tinyLayout = 0, smallLayout = 0;\r
-#define MENU_BAR_ITEMS 7\r
+#define MENU_BAR_ITEMS 9\r
 char *menuBarText[2][MENU_BAR_ITEMS+1] = {\r
-  { N_("&File"), N_("&Mode"), N_("&Action"), N_("&Step"), N_("&Options"), N_("&Help"), NULL },\r
-  { N_("&F"), N_("&M"), N_("&A"), N_("&S"), N_("&O"), N_("&H"), NULL },\r
+  { N_("&File"), N_("&Edit"), N_("&View"), N_("&Mode"), N_("&Action"), N_("E&ngine"), N_("&Options"), N_("&Help"), NULL },\r
+  { N_("&F"), N_("&E"), N_("&V"), N_("&M"), N_("&A"), N_("&N"), N_("&O"), N_("&H"), NULL },\r
 };\r
 \r
 \r
@@ -2459,7 +2459,7 @@ InitDrawingSizes(BoardSize boardSize, int flags)
   pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "w");\r
   pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w");\r
   pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w");\r
-  if( gameInfo.variant == VariantShogi && (squareSize==72 || squareSize==49)) {\r
+  if( gameInfo.variant == VariantShogi && squareSize <= 72 && squareSize >= 33) {\r
     // in Shogi, Hijack the unused Queen for Lance\r
     pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "s");\r
     pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "o");\r
@@ -2486,14 +2486,24 @@ InitDrawingSizes(BoardSize boardSize, int flags)
       pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");\r
       pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");\r
     } else { // Smirf-like\r
-      pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "s");\r
-      pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "o");\r
-      pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "w");\r
+      if(gameInfo.variant == VariantSChess) {\r
+        pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "v", squareSize, "s");\r
+        pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "v", squareSize, "o");\r
+        pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "v", squareSize, "w");\r
+      } else {\r
+        pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "s");\r
+        pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "o");\r
+        pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "w");\r
+      }\r
     }\r
     if(gameInfo.variant == VariantGothic) { // Vortex-like\r
       pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "s");\r
       pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "o");\r
       pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "w");\r
+    } else if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {\r
+      pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "e", squareSize, "s");\r
+      pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "e", squareSize, "o");\r
+      pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "e", squareSize, "w");\r
     } else { // WinBoard standard\r
       pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s");\r
       pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o");\r
@@ -2942,7 +2952,7 @@ VOID RebuildTextureSquareInfo()
 \r
 /* [AS] Arrow highlighting support */\r
 \r
-static int A_WIDTH = 5; /* Width of arrow body */\r
+static double A_WIDTH = 5; /* Width of arrow body */\r
 \r
 #define A_HEIGHT_FACTOR 6   /* Length of arrow "point", relative to body width */\r
 #define A_WIDTH_FACTOR  3   /* Width of arrow "point", relative to body width */\r
@@ -2966,50 +2976,50 @@ VOID DrawArrowBetweenPoints( HDC hdc, int s_x, int s_y, int d_x, int d_y )
     if( d_x == s_x ) {\r
         int h = (d_y > s_y) ? +A_WIDTH*A_HEIGHT_FACTOR : -A_WIDTH*A_HEIGHT_FACTOR;\r
 \r
-        arrow[0].x = s_x + A_WIDTH;\r
+        arrow[0].x = s_x + A_WIDTH + 0.5;\r
         arrow[0].y = s_y;\r
 \r
-        arrow[1].x = s_x + A_WIDTH;\r
+        arrow[1].x = s_x + A_WIDTH + 0.5;\r
         arrow[1].y = d_y - h;\r
 \r
-        arrow[2].x = s_x + A_WIDTH*A_WIDTH_FACTOR;\r
+        arrow[2].x = arrow[1].x + A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5;\r
         arrow[2].y = d_y - h;\r
 \r
         arrow[3].x = d_x;\r
         arrow[3].y = d_y;\r
 \r
-        arrow[4].x = s_x - A_WIDTH*A_WIDTH_FACTOR;\r
-        arrow[4].y = d_y - h;\r
-\r
-        arrow[5].x = s_x - A_WIDTH;\r
+        arrow[5].x = arrow[1].x - 2*A_WIDTH + 0.5;\r
         arrow[5].y = d_y - h;\r
 \r
-        arrow[6].x = s_x - A_WIDTH;\r
+        arrow[4].x = arrow[5].x - A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5;\r
+        arrow[4].y = d_y - h;\r
+\r
+        arrow[6].x = arrow[1].x - 2*A_WIDTH + 0.5;\r
         arrow[6].y = s_y;\r
     }\r
     else if( d_y == s_y ) {\r
         int w = (d_x > s_x) ? +A_WIDTH*A_HEIGHT_FACTOR : -A_WIDTH*A_HEIGHT_FACTOR;\r
 \r
         arrow[0].x = s_x;\r
-        arrow[0].y = s_y + A_WIDTH;\r
+        arrow[0].y = s_y + A_WIDTH + 0.5;\r
 \r
         arrow[1].x = d_x - w;\r
-        arrow[1].y = s_y + A_WIDTH;\r
+        arrow[1].y = s_y + A_WIDTH + 0.5;\r
 \r
         arrow[2].x = d_x - w;\r
-        arrow[2].y = s_y + A_WIDTH*A_WIDTH_FACTOR;\r
+        arrow[2].y = arrow[1].y + A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5;\r
 \r
         arrow[3].x = d_x;\r
         arrow[3].y = d_y;\r
 \r
-        arrow[4].x = d_x - w;\r
-        arrow[4].y = s_y - A_WIDTH*A_WIDTH_FACTOR;\r
-\r
         arrow[5].x = d_x - w;\r
-        arrow[5].y = s_y - A_WIDTH;\r
+        arrow[5].y = arrow[1].y - 2*A_WIDTH + 0.5;\r
+\r
+        arrow[4].x = d_x - w;\r
+        arrow[4].y = arrow[5].y - A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5;\r
 \r
         arrow[6].x = s_x;\r
-        arrow[6].y = s_y - A_WIDTH;\r
+        arrow[6].y = arrow[1].y - 2*A_WIDTH + 0.5;\r
     }\r
     else {\r
         /* [AS] Needed a lot of paper for this! :-) */\r
@@ -3026,8 +3036,8 @@ VOID DrawArrowBetweenPoints( HDC hdc, int s_x, int s_y, int d_x, int d_y )
         arrow[0].x = Round(x - j);\r
         arrow[0].y = Round(y + j*dx);\r
 \r
-        arrow[1].x = Round(x + j);\r
-        arrow[1].y = Round(y - j*dx);\r
+        arrow[1].x = Round(arrow[0].x + 2*j);   // [HGM] prevent width to be affected by rounding twice\r
+        arrow[1].y = Round(arrow[0].y - 2*j*dx);\r
 \r
         if( d_x > s_x ) {\r
             x = (double) d_x - k;\r
@@ -3038,20 +3048,22 @@ VOID DrawArrowBetweenPoints( HDC hdc, int s_x, int s_y, int d_x, int d_y )
             y = (double) d_y + k*dy;\r
         }\r
 \r
-        arrow[2].x = Round(x + j);\r
-        arrow[2].y = Round(y - j*dx);\r
+        x = Round(x); y = Round(y); // [HGM] make sure width of shaft is rounded the same way on both ends\r
+\r
+        arrow[6].x = Round(x - j);\r
+        arrow[6].y = Round(y + j*dx);\r
+\r
+        arrow[2].x = Round(arrow[6].x + 2*j);\r
+        arrow[2].y = Round(arrow[6].y - 2*j*dx);\r
 \r
-        arrow[3].x = Round(x + j*A_WIDTH_FACTOR);\r
-        arrow[3].y = Round(y - j*A_WIDTH_FACTOR*dx);\r
+        arrow[3].x = Round(arrow[2].x + j*(A_WIDTH_FACTOR-1));\r
+        arrow[3].y = Round(arrow[2].y - j*(A_WIDTH_FACTOR-1)*dx);\r
 \r
         arrow[4].x = d_x;\r
         arrow[4].y = d_y;\r
 \r
-        arrow[5].x = Round(x - j*A_WIDTH_FACTOR);\r
-        arrow[5].y = Round(y + j*A_WIDTH_FACTOR*dx);\r
-\r
-        arrow[6].x = Round(x - j);\r
-        arrow[6].y = Round(y + j*dx);\r
+        arrow[5].x = Round(arrow[6].x - j*(A_WIDTH_FACTOR-1));\r
+        arrow[5].y = Round(arrow[6].y + j*(A_WIDTH_FACTOR-1)*dx);\r
     }\r
 \r
     Polygon( hdc, arrow, 7 );\r
@@ -3076,20 +3088,20 @@ VOID DrawArrowBetweenSquares( HDC hdc, int s_col, int s_row, int d_col, int d_ro
     SquareToPos( d_row, d_col, &d_x, &d_y);\r
 \r
     if( d_y > s_y ) {\r
-        d_y += squareSize / 4;\r
+        d_y += squareSize / 2 - squareSize / 4; // [HGM] round towards same centers on all sides!\r
     }\r
     else if( d_y < s_y ) {\r
-        d_y += 3 * squareSize / 4;\r
+        d_y += squareSize / 2 + squareSize / 4;\r
     }\r
     else {\r
         d_y += squareSize / 2;\r
     }\r
 \r
     if( d_x > s_x ) {\r
-        d_x += squareSize / 4;\r
+        d_x += squareSize / 2 - squareSize / 4;\r
     }\r
     else if( d_x < s_x ) {\r
-        d_x += 3 * squareSize / 4;\r
+        d_x += squareSize / 2 + squareSize / 4;\r
     }\r
     else {\r
         d_x += squareSize / 2;\r
@@ -3099,7 +3111,7 @@ VOID DrawArrowBetweenSquares( HDC hdc, int s_col, int s_row, int d_col, int d_ro
     s_y += squareSize / 2;\r
 \r
     /* Adjust width */\r
-    A_WIDTH = squareSize / 14;\r
+    A_WIDTH = squareSize / 14.; //[HGM] make float\r
 \r
     /* Draw */\r
     stLB.lbStyle = BS_SOLID;\r
@@ -3505,7 +3517,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
             if(--board[dragInfo.from.y][dragInfo.from.x-1] == 0 )\r
         board[dragInfo.from.y][dragInfo.from.x] = EmptySquare;\r
     } else \r
-        board[dragInfo.from.y][dragInfo.from.x] = EmptySquare;\r
+        board[dragInfo.from.y][dragInfo.from.x] = gatingPiece;\r
   }\r
 \r
   /* Figure out which squares need updating by comparing the \r
@@ -3667,6 +3679,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
   if(explodeInfo.radius) { // [HGM] atomic\r
        HBRUSH oldBrush;\r
        int x, y, r=(explodeInfo.radius * squareSize)/100;\r
+        ChessSquare piece = board[explodeInfo.fromY][explodeInfo.fromX];\r
         board[explodeInfo.fromY][explodeInfo.fromX] = EmptySquare; // suppress display of capturer\r
        SquareToPos(explodeInfo.toY, explodeInfo.toX, &x, &y);\r
        x += squareSize/2;\r
@@ -3679,6 +3692,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
        DrawHighlightsOnDC(hdcmem, &highlightInfo, HIGHLIGHT_PEN);\r
        DrawHighlightsOnDC(hdcmem, &premoveHighlightInfo, PREMOVE_PEN);\r
        DrawBoardOnDC(hdcmem, board, tmphdc);\r
+        board[explodeInfo.fromY][explodeInfo.fromX] = piece;\r
        oldBrush = SelectObject(hdcmem, explodeBrush);\r
        Ellipse(hdcmem, x-r, y-r, x+r, y+r);\r
        SelectObject(hdcmem, oldBrush);\r
@@ -4295,12 +4309,11 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
     ShowWindow(GetDlgItem(hDlg, PB_Bishop), \r
        gameInfo.variant != VariantShogi ?\r
               SW_SHOW : SW_HIDE);\r
-    ShowWindow(GetDlgItem(hDlg, IDC_Yes), \r
-       gameInfo.variant == VariantShogi ?\r
-              SW_SHOW : SW_HIDE);\r
-    ShowWindow(GetDlgItem(hDlg, IDC_No), \r
-       gameInfo.variant == VariantShogi ?\r
-              SW_SHOW : SW_HIDE);\r
+    if(gameInfo.variant == VariantShogi) {\r
+        SetDlgItemText(hDlg, PB_Queen, "YES");\r
+        SetDlgItemText(hDlg, PB_Knight, "NO");\r
+        SetWindowText(hDlg, "Promote?");\r
+    }\r
     ShowWindow(GetDlgItem(hDlg, IDC_Centaur), \r
        gameInfo.variant == VariantSuper ?\r
               SW_SHOW : SW_HIDE);\r
@@ -4816,7 +4829,9 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       break;\r
 \r
     case IDM_Match: // [HGM] match: flows into next case, after setting Match Mode and nr of Games\r
-      if(gameMode != BeginningOfGame) break; // allow menu item to remain enabled for better mode highligting\r
+      if(gameMode != BeginningOfGame) { // allow menu item to remain enabled for better mode highligting\r
+        DisplayError(_("You can only start a match from the initial position."), 0); break;\r
+      }\r
       matchMode = 2;// distinguish from command-line-triggered case (matchMode=1)\r
       appData.matchGames = appData.defaultMatchGames;\r
       matchGame = 1;\r
@@ -4906,11 +4921,25 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       ShowGameListProc();\r
       break;\r
 \r
+    case IDM_EditProgs1:\r
+      EditTagsPopUp(firstChessProgramNames, &firstChessProgramNames);\r
+      break;\r
+\r
+    case IDM_EditProgs2:\r
+      EditTagsPopUp(secondChessProgramNames, &secondChessProgramNames);\r
+      break;\r
+\r
+    case IDM_EditServers:\r
+      EditTagsPopUp(icsNames, &icsNames);\r
+      break;\r
+\r
     case IDM_EditTags:\r
+    case IDM_Tags:\r
       EditTagsProc();\r
       break;\r
 \r
     case IDM_EditComment:\r
+    case IDM_Comment:\r
       if (commentUp && editComment) {\r
        CommentPopDown();\r
       } else {\r
@@ -5051,6 +5080,8 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       break;\r
 \r
     case IDM_Engine2Options:\r
+      savedHwnd = hwnd;\r
+      if(WaitForSecond(SettingsMenuIfReady)) break;\r
       EngineOptionsPopup(hwnd, &second);\r
       break;\r
 \r
@@ -5709,12 +5740,12 @@ OpenFileDialog(HWND hwnd, char *write, char *defName, char *defExt, // [HGM] dia
 \r
   if (fileName == NULL) fileName = buf1;\r
   if (defName == NULL) {\r
-    safeStrCpy(fileName, "*.", sizeof(fileName)/sizeof(fileName[0]) );\r
+    safeStrCpy(fileName, "*.", 3 );\r
     strcat(fileName, defExt);\r
   } else {\r
-    safeStrCpy(fileName, defName, sizeof(fileName)/sizeof(fileName[0]) );\r
+    safeStrCpy(fileName, defName, MSG_SIZ );\r
   }\r
-    if (fileTitle) safeStrCpy(fileTitle, "", sizeof(fileTitle)/sizeof(fileTitle[0]) );\r
+    if (fileTitle) safeStrCpy(fileTitle, "", MSG_SIZ );\r
   if (number) *number = 0;\r
 \r
   openFileName.lStructSize       = sizeof(OPENFILENAME);\r
@@ -6308,7 +6339,7 @@ EitherCommentPopUp(int index, char *title, char *str, BOOLEAN edit)
   FARPROC lpProc;\r
   char *p, *q;\r
 \r
-  CheckMenuItem(GetMenu(hwndMain), IDM_EditComment, edit ? MF_CHECKED : MF_UNCHECKED);\r
+  CheckMenuItem(GetMenu(hwndMain), IDM_Comment, edit ? MF_CHECKED : MF_UNCHECKED);\r
 \r
   if (str == NULL) str = "";\r
   p = (char *) malloc(2 * strlen(str) + 2);\r
@@ -6798,6 +6829,7 @@ CommandX(HWND hwnd, char *command, BOOLEAN getname, BOOLEAN immediate)
     SendMessage(hwnd, EM_GETSELTEXT, 0, (LPARAM) name);\r
   }\r
   if (immediate) {\r
+    if(strstr(command, "%s")) snprintf(buf, MSG_SIZ, command, name); else\r
     snprintf(buf, MSG_SIZ, "%s %s", command, name);\r
     SetWindowText(hInput, buf);\r
     SendMessage(hInput, WM_CHAR, '\r', 0);\r
@@ -7427,7 +7459,7 @@ DisplayAClock(HDC hdc, int timeRemaining, int highlight,
             rect, str, strlen(str), NULL);\r
   if(logoHeight > 0 && appData.clockMode) {\r
       RECT r;\r
-      snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s %s", buf+7, flagFell);\r
+      str += strlen(color)+2;\r
       r.top = rect->top + logoHeight/2;\r
       r.left = rect->left;\r
       r.right = rect->right;\r
@@ -7793,6 +7825,7 @@ Enables ncpEnables[] = {
 \r
 Enables trainingOnEnables[] = {\r
   { IDM_EditComment, MF_BYCOMMAND|MF_GRAYED },\r
+  { IDM_Comment, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_Pause, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_Forward, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_Backward, MF_BYCOMMAND|MF_GRAYED },\r
@@ -7805,6 +7838,7 @@ Enables trainingOnEnables[] = {
 \r
 Enables trainingOffEnables[] = {\r
   { IDM_EditComment, MF_BYCOMMAND|MF_ENABLED },\r
+  { IDM_Comment, MF_BYCOMMAND|MF_ENABLED },\r
   { IDM_Pause, MF_BYCOMMAND|MF_ENABLED },\r
   { IDM_Forward, MF_BYCOMMAND|MF_ENABLED },\r
   { IDM_Backward, MF_BYCOMMAND|MF_ENABLED },\r
@@ -8502,7 +8536,7 @@ CommentPopUp(char *title, char *str)
 VOID\r
 CommentPopDown(void)\r
 {\r
-  CheckMenuItem(GetMenu(hwndMain), IDM_EditComment, MF_UNCHECKED);\r
+  CheckMenuItem(GetMenu(hwndMain), IDM_Comment, MF_UNCHECKED);\r
   if (commentDialog) {\r
     ShowWindow(commentDialog, SW_HIDE);\r
   }\r
@@ -9616,26 +9650,26 @@ static void Tween( POINT * start, POINT * mid, POINT * finish, int factor,
      POINT frames[], int * nFrames);\r
 \r
 \r
+#define kFactor 4\r
+\r
 void\r
-AnimateAtomicCapture(int fromX, int fromY, int toX, int toY, int nFrames)\r
+AnimateAtomicCapture(Board board, int fromX, int fromY, int toX, int toY)\r
 {      // [HGM] atomic: animate blast wave\r
        int i;\r
-if(appData.debugMode) fprintf(debugFP, "exploding (%d,%d)\n", toX, toY);\r
+\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
+       for(i=1; i<4*kFactor; i++) {\r
+           explodeInfo.radius = (i*180)/(4*kFactor-1);\r
+           DrawPosition(FALSE, board);\r
            Sleep(appData.animSpeed);\r
        }\r
        explodeInfo.radius = 0;\r
-       DrawPosition(TRUE, NULL);\r
+       DrawPosition(TRUE, board);\r
 }\r
 \r
-#define kFactor 4\r
-\r
 void\r
 AnimateMove(board, fromX, fromY, toX, toY)\r
      Board board;\r
@@ -9658,17 +9692,17 @@ AnimateMove(board, fromX, fromY, toX, toY)
   ScreenSquare(fromX, fromY, &start);\r
   ScreenSquare(toX, toY, &finish);\r
 \r
-  /* All pieces except knights move in straight line */\r
-  if (piece != WhiteKnight && piece != BlackKnight) {\r
+  /* All moves except knight jumps move in straight line */\r
+  if (!(abs(fromX-toX) == 1 && abs(fromY-toY) == 2 || abs(fromX-toX) == 2 && abs(fromY-toY) == 1)) {\r
     mid.x = start.x + (finish.x - start.x) / 2;\r
     mid.y = start.y + (finish.y - start.y) / 2;\r
   } else {\r
-    /* Knight: make diagonal movement then straight */\r
+    /* Knight: make straight movement then diagonal */\r
     if (abs(toY - fromY) < abs(toX - fromX)) {\r
        mid.x = start.x + (finish.x - start.x) / 2;\r
-       mid.y = finish.y;\r
+       mid.y = start.y;\r
      } else {\r
-       mid.x = finish.x;\r
+       mid.x = start.x;\r
        mid.y = start.y + (finish.y - start.y) / 2;\r
      }\r
   }\r
@@ -9694,9 +9728,7 @@ 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
+  Explode(board, fromX, fromY, toX, toY);\r
 }\r
 \r
 /*      Convert board position to corner of screen rect and color       */\r
@@ -9764,3 +9796,9 @@ HistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current )
 \r
     EvalGraphSet( first, last, current, pvInfoList );\r
 }\r
+\r
+void\r
+SettingsPopUp(ChessProgramState *cps)\r
+{     // [HGM] wrapper needed because handles must not be passed through back-end\r
+      EngineOptionsPopup(savedHwnd, cps);\r
+}\r