Lock game an position file during writing
[xboard.git] / winboard / winboard.c
index 34832f0..c8bf0b2 100644 (file)
@@ -73,6 +73,7 @@
 #include <richedit.h>\r
 #include <mmsystem.h>\r
 #include <ctype.h>\r
+#include <io.h>\r
 \r
 #if __GNUC__\r
 #include <errno.h>\r
@@ -123,9 +124,10 @@ typedef struct {
   POINT pos;      /* window coordinates of current pos */\r
   POINT lastpos;  /* window coordinates of last pos - used for clipping */\r
   POINT from;     /* board coordinates of the piece's orig pos */\r
+  ChessSquare piece;\r
 } DragInfo;\r
 \r
-static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} };\r
+static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, EmptySquare };\r
 \r
 typedef struct {\r
   POINT sq[2];   /* board coordinates of from, to squares */\r
@@ -652,7 +654,6 @@ LRESULT CALLBACK
   StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);\r
 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);\r
 void ParseIcsTextMenu(char *icsTextMenuString);\r
-VOID PopUpMoveDialog(char firstchar);\r
 VOID PopUpNameDialog(char firstchar);\r
 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);\r
 \r
@@ -3796,8 +3797,8 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
     board[dragInfo.from.y][dragInfo.from.x] = dragged_piece;\r
     x = dragInfo.pos.x - squareSize / 2;\r
     y = dragInfo.pos.y - squareSize / 2;\r
-    DrawPieceOnDC(hdcmem, dragged_piece,\r
-                 ((int) dragged_piece < (int) BlackPawn), \r
+    DrawPieceOnDC(hdcmem, dragInfo.piece,\r
+                 ((int) dragInfo.piece < (int) BlackPawn), \r
                   (dragInfo.from.y + dragInfo.from.x) % 2, x, y, tmphdc);\r
   }   \r
   \r
@@ -3842,11 +3843,11 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
         boardRect.bottom - boardRect.top,\r
         tmphdc, boardRect.left, boardRect.top, SRCCOPY);\r
   if(saveDiagFlag) { \r
-    BITMAP b; int i, j=0, m, w, wb, fac=0; char pData[1000000]; \r
+    BITMAP b; int i, j=0, m, w, wb, fac=0; char *pData; \r
     BITMAPINFOHEADER bih; int color[16], nrColors=0;\r
 \r
     GetObject(bufferBitmap, sizeof(b), &b);\r
-    if(b.bmWidthBytes*b.bmHeight <= 990000) {\r
+    if(pData = malloc(b.bmWidthBytes*b.bmHeight + 10000)) {\r
        bih.biSize = sizeof(BITMAPINFOHEADER);\r
        bih.biWidth = b.bmWidth;\r
        bih.biHeight = b.bmHeight;\r
@@ -3910,6 +3911,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
        // write bitmap data\r
        for(i=0; i<wb*(b.bmHeight - boardRect.top + OUTER_MARGIN); i++) \r
                fputc(pData[i], diagFile);\r
+       free(pData);\r
      }\r
   }\r
 \r
@@ -3946,11 +3948,8 @@ SaveDiagram(f)
 {\r
     saveDiagFlag = 1; diagFile = f;\r
     HDCDrawPosition(NULL, TRUE, NULL);\r
-\r
     saveDiagFlag = 0;\r
 \r
-//    if(f != NULL) fprintf(f, "Sorry, but this feature is still in preparation\n");\r
-    \r
     fclose(f);\r
     return TRUE;\r
 }\r
@@ -4063,6 +4062,7 @@ void DragPieceBegin(int x, int y)
       dragInfo.lastpos.y = boardRect.top + y;\r
       dragInfo.from.x = fromX;\r
       dragInfo.from.y = fromY;\r
+      dragInfo.piece = boards[currentMove][fromY][fromX];\r
       dragInfo.start = dragInfo.from;\r
       SetCapture(hwndMain);\r
 }\r
@@ -4075,6 +4075,11 @@ void DragPieceEnd(int x, int y)
     dragInfo.pos = dragInfo.lastpos = dragInfo.start;\r
 }\r
 \r
+void ChangeDragPiece(ChessSquare piece)\r
+{\r
+    dragInfo.piece = piece;\r
+}\r
+\r
 /* Event handler for mouse messages */\r
 VOID\r
 MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
@@ -4135,6 +4140,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 \r
   case WM_MOUSEMOVE:\r
     if(SeekGraphClick(Press, pt.x - boardRect.left, pt.y - boardRect.top, 1)) break;\r
+    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
@@ -4272,7 +4278,7 @@ ButtonProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        SendMessage(h, WM_CHAR, wParam, lParam);\r
        return TRUE;\r
       } else if (isalpha((char)wParam) || isdigit((char)wParam)){\r
-       PopUpMoveDialog((char)wParam);\r
+       TypeInEvent((char)wParam);\r
       }\r
       break;\r
     }\r
@@ -4581,7 +4587,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        SendMessage(h, message, wParam, lParam);\r
     } else if(lParam != KF_REPEAT) {\r
        if (isalpha((char)wParam) || isdigit((char)wParam)) {\r
-               PopUpMoveDialog((char)wParam);\r
+               TypeInEvent((char)wParam);\r
        } else if((char)wParam == 003) CopyGameToClipboard();\r
         else if((char)wParam == 026) PasteGameOrFENFromClipboard();\r
     }\r
@@ -4839,10 +4845,9 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       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
-      first.matchWins = second.matchWins = 0;\r
+      appData.matchGames = appData.defaultMatchGames;
+      MatchEvent(2); // distinguish from command-line-triggered case (matchMode=1)\r
+      break;\r
 \r
     case IDM_TwoMachines:\r
       TwoMachinesEvent();\r
@@ -5006,7 +5011,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       break;\r
 \r
     case IDM_TypeInMove:\r
-      PopUpMoveDialog('\000');\r
+      TypeInEvent('\000');\r
       break;\r
 \r
     case IDM_TypeInName:\r
@@ -5091,7 +5096,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 \r
     case IDM_Engine2Options:\r
       savedHwnd = hwnd;\r
-      if(WaitForSecond(SettingsMenuIfReady)) break;\r
+      if(WaitForEngine(&second, SettingsMenuIfReady)) break;\r
       EngineOptionsPopup(hwnd, &second);\r
       break;\r
 \r
@@ -6397,9 +6402,6 @@ TypeInMoveDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
 {\r
   char move[MSG_SIZ];\r
   HWND hInput;\r
-  ChessMove moveType;\r
-  int fromX, fromY, toX, toY;\r
-  char promoChar;\r
 \r
   switch (message) {\r
   case WM_INITDIALOG:\r
@@ -6418,36 +6420,8 @@ TypeInMoveDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
     case IDOK:
 \r
       shiftKey = GetKeyState(VK_SHIFT) < 0; // [HGM] remember last shift status\r
-      GetDlgItemText(hDlg, OPT_Move, move, sizeof(move));\r
-      { int n; Board board;\r
-       // [HGM] FENedit\r
-       if(gameMode == EditPosition && ParseFEN(board, &n, move) ) {\r
-               EditPositionPasteFEN(move);\r
-               EndDialog(hDlg, TRUE);\r
-               return TRUE;\r
-       }\r
-       // [HGM] movenum: allow move number to be typed in any mode\r
-       if(sscanf(move, "%d", &n) == 1 && n != 0 ) {\r
-         ToNrEvent(2*n-1);\r
-         EndDialog(hDlg, TRUE);\r
-         return TRUE;\r
-       }\r
-      }\r
-      if (gameMode != EditGame && currentMove != forwardMostMove && \r
-       gameMode != Training) {\r
-       DisplayMoveError(_("Displayed move is not current"));\r
-      } else {\r
-//     GetDlgItemText(hDlg, OPT_Move, move, sizeof(move)); // moved upstream\r
-       int ok = ParseOneMove(move, gameMode == EditPosition ? blackPlaysFirst : currentMove, \r
-         &moveType, &fromX, &fromY, &toX, &toY, &promoChar);\r
-       if(!ok && move[0] >= 'a') { move[0] += 'A' - 'a'; ok = 2; } // [HGM] try also capitalized\r
-       if (ok==1 || ok && ParseOneMove(move, gameMode == EditPosition ? blackPlaysFirst : currentMove, \r
-         &moveType, &fromX, &fromY, &toX, &toY, &promoChar)) {\r
-         UserMoveEvent(fromX, fromY, toX, toY, promoChar);     \r
-       } else {\r
-         DisplayMoveError(_("Could not parse move"));\r
-       }\r
-      }\r
+      GetDlgItemText(hDlg, OPT_Move, move, sizeof(move));
+      TypeInDoneEvent(move);\r
       EndDialog(hDlg, TRUE);\r
       return TRUE;\r
     case IDCANCEL:\r
@@ -6465,21 +6439,11 @@ VOID
 PopUpMoveDialog(char firstchar)\r
 {\r
     FARPROC lpProc;\r
-    \r
-    if ((gameMode == BeginningOfGame && !appData.icsActive) || \r
-        gameMode == MachinePlaysWhite || gameMode == MachinePlaysBlack ||\r
-       gameMode == AnalyzeMode || gameMode == EditGame || \r
-       gameMode == EditPosition || gameMode == IcsExamining ||\r
-       gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack ||\r
-       isdigit(firstchar) && // [HGM] movenum: allow typing in of move nr in 'passive' modes\r
-               ( gameMode == AnalyzeFile || gameMode == PlayFromGameFile ||\r
-                 gameMode == IcsObserving || gameMode == TwoMachinesPlay    ) ||\r
-       gameMode == Training) {\r
+\r
       lpProc = MakeProcInstance((FARPROC)TypeInMoveDialog, hInst);\r
       DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_TypeInMove),\r
        hwndMain, (DLGPROC)lpProc, (LPARAM)firstchar);\r
       FreeProcInstance(lpProc);\r
-    }\r
 }\r
 \r
 /*---------------------------------------------------------------------------*\\r
@@ -8150,7 +8114,8 @@ DisplayMessage(char *str1, char *str2)
     if (len > remain) len = remain;\r
     strncat(messageText, str2, len);\r
   }\r
-  messageText[MESSAGE_TEXT_MAX - 1] = NULLCHAR;\r
+  messageText[MESSAGE_TEXT_MAX - 1] = NULLCHAR;
+  safeStrCpy(lastMsg, messageText, MSG_SIZ);
 \r
   if (hwndMain == NULL || IsIconic(hwndMain)) return;\r
 \r
@@ -9820,3 +9785,19 @@ SettingsPopUp(ChessProgramState *cps)
 {     // [HGM] wrapper needed because handles must not be passed through back-end\r
       EngineOptionsPopup(savedHwnd, cps);\r
 }\r
+\r
+int flock(int fid, int code)\r
+{\r
+    HANDLE hFile = (HANDLE) _get_osfhandle(fid);\r
+    OVERLAPPED ov;\r
+    ov.hEvent = NULL;\r
+    ov.Offset = 0;\r
+    ov.OffsetHigh = 0;\r
+    switch(code) {\r
+      case 1: LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, 1024, 0, &ov); break;   // LOCK_SH\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
+    }\r
+    return 0;\r
+}\r