Updated copyright notice to 2015
[xboard.git] / winboard / winboard.c
index 2b13222..c82ae8a 100644 (file)
@@ -2,10 +2,10 @@
  * WinBoard.c -- Windows NT front end to XBoard\r
  *\r
  * Copyright 1991 by Digital Equipment Corporation, Maynard,\r
- * Massachusetts. \r
+ * Massachusetts.\r
  *\r
  * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,\r
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.\r
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Free Software Foundation, Inc.\r
  *\r
  * Enhancements Copyright 2005 Alessandro Scotti\r
  *\r
@@ -92,6 +92,9 @@
 #include "help.h"\r
 #include "wsnap.h"\r
 \r
+#define SLASH '/'\r
+#define DATADIR "~~"\r
+\r
 //void InitEngineUCI( const char * iniDir, ChessProgramState * cps );\r
 \r
   int myrandom(void);\r
@@ -109,7 +112,6 @@ VOID NewVariantPopup(HWND hwnd);
 int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,\r
                   /*char*/int promoChar));\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
@@ -164,7 +166,7 @@ BoardSize boardSize;
 Boolean chessProgram;\r
 //static int boardX, boardY;\r
 int  minX, minY; // [HGM] placement: volatile limits on upper-left corner\r
-int squareSize, lineGap, minorSize, border;\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
@@ -258,7 +260,8 @@ int dialogItems[][42] = {
 { DLG_TimeControl, IDC_Babble, OPT_TCUseMoves, OPT_TCUseInc, OPT_TCUseFixed, \r
   OPT_TCtext1, OPT_TCtext2, OPT_TCitext1, OPT_TCitext2, OPT_TCftext, GPB_Factors,   IDC_Factor1, IDC_Factor2, IDOK, IDCANCEL }, \r
 { DLG_LoadOptions, OPT_Autostep, OPT_AStext1, OPT_Exact, OPT_Subset, OPT_Struct, OPT_Material, OPT_Range, OPT_Difference,\r
-  OPT_elo1t, OPT_elo2t, OPT_datet, OPT_Stretch, OPT_Stretcht, OPT_Reversed, OPT_SearchMode, OPT_Mirror, OPT_thresholds, IDOK, IDCANCEL }, \r
+  OPT_elo1t, OPT_elo2t, OPT_datet, OPT_Stretch, OPT_Stretcht, OPT_Reversed, OPT_SearchMode, OPT_Mirror, OPT_thresholds,\r
+  OPT_Ranget, IDOK, IDCANCEL }, \r
 { DLG_SaveOptions, OPT_Autosave, OPT_AVPrompt, OPT_AVToFile, OPT_AVBrowse,\r
   801, OPT_PGN, OPT_Old, OPT_OutOfBookInfo, IDOK, IDCANCEL }, \r
 { 1536, 1090, IDC_Directories, 1089, 1091, IDOK, IDCANCEL, 1038, IDC_IndexNr, 1037 }, \r
@@ -783,12 +786,14 @@ void ThawUI()
  *\r
 \*---------------------------------------------------------------------------*/\r
 \r
+static void HandleMessage P((MSG *message));\r
+static HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;\r
+\r
 int APIENTRY\r
 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,\r
        LPSTR lpCmdLine, int nCmdShow)\r
 {\r
   MSG msg;\r
-  HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;\r
 //  INITCOMMONCONTROLSEX ex;\r
 \r
   debugFP = stderr;\r
@@ -820,6 +825,17 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    0,    /* lowest message to examine */\r
                    0))   /* highest message to examine */\r
     {\r
+       HandleMessage(&msg);\r
+    }\r
+\r
+\r
+  return (msg.wParam); /* Returns the value from PostQuitMessage */\r
+}\r
+\r
+static void\r
+HandleMessage (MSG *message)\r
+{\r
+    MSG msg = *message;\r
 \r
       if(msg.message == WM_CHAR && msg.wParam == '\t') {\r
        // [HGM] navigate: switch between all windows with tab\r
@@ -887,7 +903,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
          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
+         return; // this message now has been processed\r
        }\r
       }\r
 \r
@@ -906,14 +922,24 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
            if(chatHandle[i] && IsDialogMessage(chatHandle[i], &msg)) {\r
                done = 1; break;\r
        }\r
-       if(done) continue; // [HGM] chat: end patch\r
+       if(done) return; // [HGM] chat: end patch\r
        TranslateMessage(&msg); /* Translates virtual key codes */\r
        DispatchMessage(&msg);  /* Dispatches message to window */\r
       }\r
-    }\r
-\r
+}\r
 \r
-  return (msg.wParam); /* Returns the value from PostQuitMessage */\r
+void\r
+DoEvents ()\r
+{ /* Dispatch pending messages */\r
+  MSG msg;\r
+  while (PeekMessage(&msg, /* message structure */\r
+                    NULL, /* handle of window receiving the message */\r
+                    0,    /* lowest message to examine */\r
+                    0,    /* highest message to examine */\r
+                    PM_REMOVE))\r
+    {\r
+       HandleMessage(&msg);\r
+    }\r
 }\r
 \r
 /*---------------------------------------------------------------------------*\\r
@@ -982,16 +1008,17 @@ InitApplication(HINSTANCE hInstance)
 \r
 /* Set by InitInstance, used by EnsureOnScreen */\r
 int screenHeight, screenWidth;\r
+RECT screenGeometry;\r
 \r
 void\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 < minX) *x = minX;\r
-  if (*y < minY) *y = minY;\r
+  if (*x > screenGeometry.right - 32) *x = screenGeometry.left;\r
+  if (*y > screenGeometry.bottom - 32) *y = screenGeometry.top;\r
+  if (*x < screenGeometry.left + minX) *x = screenGeometry.left + minX;\r
+  if (*y < screenGeometry.top + minY) *y = screenGeometry.top + minY;\r
 }\r
 \r
 VOID\r
@@ -1052,6 +1079,32 @@ InitTextures()
   }\r
 }\r
 \r
+#ifndef SM_CXVIRTUALSCREEN\r
+#define SM_CXVIRTUALSCREEN 78\r
+#endif\r
+#ifndef SM_CYVIRTUALSCREEN\r
+#define SM_CYVIRTUALSCREEN 79\r
+#endif\r
+#ifndef SM_XVIRTUALSCREEN \r
+#define SM_XVIRTUALSCREEN 76\r
+#endif\r
+#ifndef SM_YVIRTUALSCREEN \r
+#define SM_YVIRTUALSCREEN 77\r
+#endif\r
+\r
+VOID\r
+InitGeometry()\r
+{\r
+  screenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);\r
+  if( !screenHeight ) screenHeight = GetSystemMetrics(SM_CYSCREEN);\r
+  screenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);\r
+  if( !screenWidth ) screenWidth = GetSystemMetrics(SM_CXSCREEN);\r
+  screenGeometry.left = GetSystemMetrics(SM_XVIRTUALSCREEN);\r
+  screenGeometry.top = GetSystemMetrics(SM_YVIRTUALSCREEN);\r
+  screenGeometry.right = screenGeometry.left + screenWidth;\r
+  screenGeometry.bottom = screenGeometry.top + screenHeight;\r
+}\r
+\r
 BOOL\r
 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)\r
 {\r
@@ -1070,7 +1123,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
+  InitGeometry();\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
@@ -1117,8 +1170,7 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
   iconBlack = LoadIcon(hInstance, "icon_black");\r
   iconCurrent = iconWhite;\r
   InitDrawingColors();\r
-  screenHeight = GetSystemMetrics(SM_CYSCREEN);\r
-  screenWidth = GetSystemMetrics(SM_CXSCREEN);\r
+\r
   InitPosition(0); // to set nr of ranks and files, which might be non-default through command-line args\r
   for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {\r
     /* Compute window size for each board size, and use the largest\r
@@ -1199,6 +1251,7 @@ InitMenuChecks()
   (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,\r
                       MF_BYCOMMAND|(saveSettingsOnExit ?\r
                                     MF_CHECKED : MF_UNCHECKED));\r
+  EnableMenuItem(hmenu, IDM_SaveSelected, MF_GRAYED);\r
 }\r
 \r
 //---------------------------------------------------------------------------------------------------------\r
@@ -1229,6 +1282,7 @@ LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
   lf->lfStrikeOut = mfp->strikeout;\r
   lf->lfCharSet = mfp->charset;\r
   lf->lfOutPrecision = OUT_DEFAULT_PRECIS;\r
+\r
   lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;\r
   lf->lfQuality = DEFAULT_QUALITY;\r
   lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;\r
@@ -1782,6 +1836,8 @@ static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
     COLORREF chroma = RGB(0xFF,0x00,0xFF);\r
     RECT rc;\r
     SIZE sz;\r
+\r
+\r
     POINT pt;\r
     int backColor = whitePieceColor; \r
     int foreColor = blackPieceColor;\r
@@ -2271,9 +2327,10 @@ InitDrawingSizes(BoardSize boardSize, int flags)
   { // correct board size to one where built-in pieces exist\r
     if((v == VariantCapablanca || v == VariantGothic || v == VariantGrand || v == VariantCapaRandom || v == VariantJanus || v == VariantSuper)\r
        && (boardSize < SizePetite || boardSize > SizeBulky) // Archbishop and Chancellor available in entire middle range\r
+\r
       || (v == VariantShogi && boardSize != SizeModerate)   // Japanese-style Shogi\r
       ||  v == VariantKnightmate || v == VariantSChess || v == VariantXiangqi || v == VariantSpartan\r
-      ||  v == VariantShatranj || v == VariantMakruk || v == VariantGreat || v == VariantFairy ) {\r
+      ||  v == VariantShatranj || v == VariantMakruk || v == VariantGreat || v == VariantFairy || v == VariantLion ) {\r
       if(boardSize < SizeMediocre) boardSize = SizePetite; else\r
       if(boardSize > SizeModerate) boardSize = SizeBulky;  else\r
                                    boardSize = SizeMiddling;\r
@@ -2629,8 +2686,11 @@ InitDrawingSizes(BoardSize boardSize, int flags)
     pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s");\r
     pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o");\r
     pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w");\r
+    pieceBitmap[0][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "s");\r
+    pieceBitmap[1][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "o");\r
+    pieceBitmap[2][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "w");\r
 \r
-    if(gameInfo.variant == VariantShogi) { /* promoted Gold represemtations */\r
+    if(gameInfo.variant == VariantShogi && BOARD_HEIGHT != 7) { /* promoted Gold representations (but not in Tori!)*/\r
       pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s");\r
       pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "o");\r
       pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
@@ -3250,6 +3310,9 @@ BOOL HasHighlightInfo()
     }\r
 \r
     return result;\r
+\r
+\r
+\r
 }\r
 \r
 BOOL IsDrawArrowEnabled()\r
@@ -3441,6 +3504,7 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc)
             DisplayHoldingsCount(hdc, x, y, flipView, (int) board[row][column]);\r
       else if( column == BOARD_RGHT) /* right align */\r
             DisplayHoldingsCount(hdc, x, y, !flipView, (int) board[row][column]);\r
+      else if( piece == DarkSquare) DisplayHoldingsCount(hdc, x, y, 0, 0);\r
       else\r
       if (appData.monoMode) {\r
         if (piece == EmptySquare) {\r
@@ -3942,6 +4006,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
     else\r
     if(dragInfo.from.x == BOARD_RGHT+1 )\r
                  board[dragInfo.from.y][dragInfo.from.x-1]++;\r
+\r
     board[dragInfo.from.y][dragInfo.from.x] = dragged_piece;\r
     x = dragInfo.pos.x - squareSize / 2;\r
     y = dragInfo.pos.y - squareSize / 2;\r
@@ -4272,8 +4337,10 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       } else if (PtInRect((LPRECT) &blackRect, pt)) {\r
        ClockClick(!flipClock); break;\r
       }\r
+    if(dragging) { // [HGM] lion: don't destroy dragging info if we are already dragging\r
       dragInfo.start.x = dragInfo.start.y = -1;\r
       dragInfo.from = dragInfo.start;\r
+    }\r
     if(fromX == -1 && frozen) { // not sure where this is for\r
                fromX = fromY = -1; \r
       DrawPosition(forceFullRepaint || FALSE, NULL); /* [AS] */\r
@@ -4293,7 +4360,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     if(PromoScroll(pt.x - boardRect.left, pt.y - boardRect.top)) 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
+       && (wParam & MK_LBUTTON || dragging == 2)\r
        && dragInfo.from.x >= 0) \r
     {\r
       BOOL full_repaint = FALSE;\r
@@ -4437,6 +4504,8 @@ ButtonProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
   return CallWindowProc(buttonDesc[i].wndproc, hwnd, message, wParam, lParam);\r
 }\r
 \r
+static int promoStyle;\r
+\r
 /* Process messages for Promotion dialog box */\r
 LRESULT CALLBACK\r
 Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
@@ -4444,6 +4513,7 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
   char promoChar;\r
 \r
   switch (message) {\r
+\r
   case WM_INITDIALOG: /* message: initialize dialog box */\r
     /* Center the dialog over the application window */\r
     CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER));\r
@@ -4467,13 +4537,9 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
          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
-       gameInfo.variant != VariantShogi ?\r
-              SW_SHOW : SW_HIDE);\r
-    ShowWindow(GetDlgItem(hDlg, PB_Bishop), \r
-       gameInfo.variant != VariantShogi ?\r
-              SW_SHOW : SW_HIDE);\r
-    if(gameInfo.variant == VariantShogi) {\r
+    ShowWindow(GetDlgItem(hDlg, PB_Rook),   !promoStyle ? SW_SHOW : SW_HIDE);\r
+    ShowWindow(GetDlgItem(hDlg, PB_Bishop), !promoStyle ? SW_SHOW : SW_HIDE);\r
+    if(promoStyle) {\r
         SetDlgItemText(hDlg, PB_Queen, "YES");\r
         SetDlgItemText(hDlg, PB_Knight, "NO");\r
         SetWindowText(hDlg, "Promote?");\r
@@ -4494,7 +4560,7 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
       promoChar = gameInfo.variant == VariantSuper ? PieceToChar(BlackSilver) : PieceToChar(BlackKing);\r
       break;\r
     case PB_Queen:\r
-      promoChar = gameInfo.variant == VariantShogi ? '+' : ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteQueen : BlackQueen));\r
+      promoChar = promoStyle ? '+' : ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteQueen : BlackQueen));\r
       break;\r
     case PB_Rook:\r
       promoChar = ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteRook : BlackRook));\r
@@ -4511,7 +4577,8 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
       promoChar = ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteAngel : BlackAngel));\r
       break;\r
     case PB_Knight:\r
-      promoChar = gameInfo.variant == VariantShogi ? '=' : PieceToChar(WhiteOnMove(currentMove) ? WhiteKnight : BlackKnight);\r
+      promoChar = gameInfo.variant == VariantShogi ? '=' : promoStyle ? NULLCHAR : \r
+                  ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteKnight : BlackKnight));\r
       break;\r
     default:\r
       return FALSE;\r
@@ -4542,8 +4609,9 @@ PromotionPopup(HWND hwnd)
 }\r
 \r
 void\r
-PromotionPopUp()\r
+PromotionPopUp(char choice)\r
 {\r
+  promoStyle = (choice == '+');\r
   DrawPosition(TRUE, NULL);\r
   PromotionPopup(hwndMain);\r
 }\r
@@ -4681,7 +4749,7 @@ LRESULT CALLBACK
 WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
 {\r
   FARPROC lpProc;\r
-  int wmId, wmEvent;\r
+  int wmId;\r
   char *defName;\r
   FILE *f;\r
   UINT number;\r
@@ -4784,7 +4852,6 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 \r
   case WM_COMMAND: /* message: command from application menu */\r
     wmId    = LOWORD(wParam);\r
-    wmEvent = HIWORD(wParam);\r
 \r
     switch (wmId) {\r
     case IDM_NewGame:\r
@@ -4877,6 +4944,16 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       }\r
       break;\r
 \r
+    case IDM_SaveSelected:\r
+      f = OpenFileDialog(hwnd, "a", "",\r
+                        "pgn",\r
+                        GAME_FILT,\r
+                        _("Save Game to File"), NULL, fileTitle, NULL);\r
+      if (f != NULL) {\r
+       SaveSelected(f, 0, "");\r
+      }\r
+      break;\r
+\r
     case IDM_CreateBook:\r
       CreateBookEvent();\r
       break;\r
@@ -5103,6 +5180,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       break;\r
 \r
     case IDM_Rematch:\r
+\r
       RematchEvent();\r
       break;\r
 \r
@@ -5592,7 +5670,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     if( hwnd == hwndMain && appData.useStickyWindows ) {\r
         LPWINDOWPOS lpwp = (LPWINDOWPOS) lParam;\r
 \r
-        if( ((lpwp->flags & SWP_NOMOVE) == 0) && ((lpwp->flags & SWP_NOSIZE) != 0) ) {\r
+        if( ((lpwp->flags & SWP_NOMOVE) == 0) /*&& ((lpwp->flags & SWP_NOSIZE) != 0)*/ ) { // [HGM] in Win8 size always accompanies move?\r
             /* Window is moving */\r
             RECT rcMain;\r
 \r
@@ -5661,6 +5739,8 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
   default:     /* Passes it on if unprocessed */\r
     return (DefWindowProc(hwnd, message, wParam, lParam));\r
   }\r
+\r
+\r
   return 0;\r
 }\r
 \r
@@ -6260,6 +6340,7 @@ StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
        SwapEngines(singleList); // temporarily swap first and second, to load a second 'first', ...\r
        ParseArgs(StringGet, &p);\r
        SwapEngines(singleList); // ... and then make it 'second'\r
+\r
        appData.noChessProgram = FALSE;\r
        appData.icsActive = FALSE;\r
       } else if (IsDlgButtonChecked(hDlg, OPT_ChessServer)) {\r
@@ -6350,7 +6431,7 @@ LRESULT CALLBACK
 CommentDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
 {\r
   static HANDLE hwndText = NULL;\r
-  int len, newSizeX, newSizeY, flags;\r
+  int len, newSizeX, newSizeY;\r
   static int sizeX, sizeY;\r
   char *str;\r
   RECT rect;\r
@@ -6378,7 +6459,6 @@ CommentDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
     /* Size and position the dialog */\r
     if (!commentDialog) {\r
       commentDialog = hDlg;\r
-      flags = SWP_NOZORDER;\r
       GetClientRect(hDlg, &rect);\r
       sizeX = rect.right;\r
       sizeY = rect.bottom;\r
@@ -6715,7 +6795,6 @@ ErrorPopDown()
 LRESULT CALLBACK\r
 ErrorDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
 {\r
-  HANDLE hwndText;\r
   RECT rChild;\r
 \r
   switch (message) {\r
@@ -6739,7 +6818,6 @@ ErrorDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
 \r
     errorDialog = hDlg;\r
     SetWindowText(hDlg, errorTitle);\r
-    hwndText = GetDlgItem(hDlg, OPT_ErrorText);\r
     SetDlgItemText(hDlg, OPT_ErrorText, errorMessage);\r
     return FALSE;\r
 \r
@@ -6765,7 +6843,6 @@ HWND gothicDialog = NULL;
 LRESULT CALLBACK\r
 GothicDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
 {\r
-  HANDLE hwndText;\r
   RECT rChild;\r
   int height = GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYFRAME);\r
 \r
@@ -6784,7 +6861,6 @@ GothicDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
     */\r
     gothicDialog = hDlg;\r
     SetWindowText(hDlg, errorTitle);\r
-    hwndText = GetDlgItem(hDlg, OPT_ErrorText);\r
     SetDlgItemText(hDlg, OPT_ErrorText, errorMessage);\r
     return FALSE;\r
 \r
@@ -6837,6 +6913,7 @@ GothicPopUp(char *title, VariantClass variant)
 static char *history[HISTORY_SIZE];\r
 int histIn = 0, histP = 0;\r
 \r
+\r
 VOID\r
 SaveInHistory(char *cmd)\r
 {\r
@@ -6849,6 +6926,7 @@ SaveInHistory(char *cmd)
   histIn = (histIn + 1) % HISTORY_SIZE;\r
   if (history[histIn] != NULL) {\r
     free(history[histIn]);\r
+\r
     history[histIn] = NULL;\r
   }\r
   histP = histIn;\r
@@ -7659,6 +7737,7 @@ DoWriteFile(HANDLE hFile, char *buf, int count, DWORD *outCount,
       else\r
        err = GetLastError();\r
     }\r
+\r
   }\r
   return err;\r
 }\r
@@ -8524,6 +8603,7 @@ HWND gameListOptionsDialog;
 \r
 // low-level front-end: clear text edit / list widget\r
 void\r
+\r
 GLT_ClearList()\r
 {\r
     SendDlgItemMessage( gameListOptionsDialog, IDC_GameListTags, LB_RESETCONTENT, 0, 0 );\r
@@ -8632,8 +8712,11 @@ int GameListOptions()
     result = DialogBoxParam( hInst, MAKEINTRESOURCE(DLG_GameListOptions), hwndMain, (DLGPROC)lpProc, (LPARAM)lpUserGLT );\r
 \r
     if( result == 0 ) {\r
+        char *oldTags = appData.gameListTags;\r
         /* [AS] Memory leak here! */\r
         appData.gameListTags = strdup( lpUserGLT ); \r
+        if(strcmp(oldTags, appData.gameListTags)) // [HGM] redo Game List when we changed something\r
+            GameListToListBox(NULL, TRUE, ".", NULL, FALSE, FALSE); // "." as filter is kludge to select all\r
     }\r
 \r
     return result;\r
@@ -8715,6 +8798,13 @@ EditCommentPopUp(int index, char *title, char *str)
 }\r
 \r
 \r
+int\r
+Roar()\r
+{\r
+  MyPlaySound(&sounds[(int)SoundRoar]);\r
+  return 1;\r
+}\r
+\r
 VOID\r
 RingBell()\r
 {\r
@@ -8872,6 +8962,7 @@ DisplayBlackClock(long timeRemaining, int highlight)
   HDC hdc;\r
   char *flag = blackFlag && gameMode == TwoMachinesPlay ? "(!)" : "";\r
 \r
+\r
   if(appData.noGUI) return;\r
   hdc = GetDC(hwndMain);\r
   if (!IsIconic(hwndMain)) {\r
@@ -9183,15 +9274,15 @@ DestroyChildProcess(ProcRef pr, int/*boolean*/ signal)
     /*!!if (signal) GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, cp->pid);*/\r
 \r
     /* [AS] Special termination modes for misbehaving programs... */\r
-    if( signal == 9 ) { \r
+    if( signal & 8 ) { \r
         result = TerminateProcess( cp->hProcess, 0 );\r
 \r
         if ( appData.debugMode) {\r
             fprintf( debugFP, "Terminating process %lu, result=%d\n", cp->pid, result );\r
         }\r
     }\r
-    else if( signal == 10 ) {\r
-        DWORD dw = WaitForSingleObject( cp->hProcess, 3*1000 ); // Wait 3 seconds at most\r
+    else if( signal & 4 ) {\r
+        DWORD dw = WaitForSingleObject( cp->hProcess, appData.delayAfterQuit*1000 + 50 ); // Wait 3 seconds at most\r
 \r
         if( dw != WAIT_OBJECT_0 ) {\r
             result = TerminateProcess( cp->hProcess, 0 );\r
@@ -9688,6 +9779,7 @@ OutputToProcess(ProcRef pr, char *message, int count, int *outError)
   int outCount = SOCKET_ERROR;\r
   ChildProc *cp = (ChildProc *) pr;\r
   static OVERLAPPED ovl;\r
+\r
   static int line = 0;\r
 \r
   if (pr == NoProc)\r
@@ -9890,16 +9982,23 @@ AnimateMove(board, fromX, fromY, toX, toY)
      int toY;\r
 {\r
   ChessSquare piece;\r
+  int x = toX, y = toY;\r
   POINT start, finish, mid;\r
   POINT frames[kFactor * 2 + 1];\r
   int nFrames, n;\r
 \r
+  if(killX >= 0 && IS_LION(board[fromY][fromX])) Roar();\r
+\r
   if (!appData.animate) return;\r
   if (doingSizing) return;\r
   if (fromY < 0 || fromX < 0) return;\r
   piece = board[fromY][fromX];\r
   if (piece >= EmptySquare) return;\r
 \r
+  if(killX >= 0) toX = killX, toY = killY; // [HGM] lion: first to kill square\r
+\r
+again:\r
+\r
   ScreenSquare(fromX, fromY, &start);\r
   ScreenSquare(toX, toY, &finish);\r
 \r
@@ -9938,6 +10037,9 @@ AnimateMove(board, fromX, fromY, toX, toY)
   }\r
   animInfo.pos = finish;\r
   DrawPosition(FALSE, NULL);\r
+\r
+  if(toX != x || toY != y) { fromX = toX; fromY = toY; toX = x; toY = y; goto again; } // second leg\r
+\r
   animInfo.piece = EmptySquare;\r
   Explode(board, fromX, fromY, toX, toY);\r
 }\r
@@ -10015,6 +10117,7 @@ int flock(int fid, int code)
     ov.OffsetHigh = 0;\r
     switch(code) {\r
       case 1: LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, 1024, 0, &ov); break;   // LOCK_SH\r
+\r
       case 2: LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, 1024, 0, &ov); break;   // LOCK_EX\r
       case 3: UnlockFileEx(hFile, 0, 1024, 0, &ov); break; // LOCK_UN\r
       default: return -1;\r