X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=winboard%2Fwinboard.c;h=088badbace5e7777aae9d1fd9c041fb6783a0c05;hb=699d2cc5efc5e3ef959813b16528e6b23d8de50a;hp=7bd391dc79ef2beca32083aedde343da88ca602a;hpb=c2a5e9675e41feddadb6e06544dedc3afdc6ae66;p=xboard.git diff --git a/winboard/winboard.c b/winboard/winboard.c index 7bd391d..088badb 100644 --- a/winboard/winboard.c +++ b/winboard/winboard.c @@ -2,10 +2,10 @@ * WinBoard.c -- Windows NT front end to XBoard * * Copyright 1991 by Digital Equipment Corporation, Maynard, - * Massachusetts. + * Massachusetts. * * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006, - * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. + * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc. * * Enhancements Copyright 2005 Alessandro Scotti * @@ -92,6 +92,9 @@ #include "help.h" #include "wsnap.h" +#define SLASH '/' +#define DATADIR "~~" + //void InitEngineUCI( const char * iniDir, ChessProgramState * cps ); int myrandom(void); @@ -109,7 +112,6 @@ VOID NewVariantPopup(HWND hwnd); int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY, /*char*/int promoChar)); void DisplayMove P((int moveNumber)); -Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen)); void ChatPopUp P((char *s)); typedef struct { ChessSquare piece; @@ -258,7 +260,8 @@ int dialogItems[][42] = { { DLG_TimeControl, IDC_Babble, OPT_TCUseMoves, OPT_TCUseInc, OPT_TCUseFixed, OPT_TCtext1, OPT_TCtext2, OPT_TCitext1, OPT_TCitext2, OPT_TCftext, GPB_Factors, IDC_Factor1, IDC_Factor2, IDOK, IDCANCEL }, { DLG_LoadOptions, OPT_Autostep, OPT_AStext1, OPT_Exact, OPT_Subset, OPT_Struct, OPT_Material, OPT_Range, OPT_Difference, - OPT_elo1t, OPT_elo2t, OPT_datet, OPT_Stretch, OPT_Stretcht, OPT_Reversed, OPT_SearchMode, OPT_Mirror, OPT_thresholds, IDOK, IDCANCEL }, + OPT_elo1t, OPT_elo2t, OPT_datet, OPT_Stretch, OPT_Stretcht, OPT_Reversed, OPT_SearchMode, OPT_Mirror, OPT_thresholds, + OPT_Ranget, IDOK, IDCANCEL }, { DLG_SaveOptions, OPT_Autosave, OPT_AVPrompt, OPT_AVToFile, OPT_AVBrowse, 801, OPT_PGN, OPT_Old, OPT_OutOfBookInfo, IDOK, IDCANCEL }, { 1536, 1090, IDC_Directories, 1089, 1091, IDOK, IDCANCEL, 1038, IDC_IndexNr, 1037 }, @@ -982,16 +985,17 @@ InitApplication(HINSTANCE hInstance) /* Set by InitInstance, used by EnsureOnScreen */ int screenHeight, screenWidth; +RECT screenGeometry; void EnsureOnScreen(int *x, int *y, int minX, int minY) { // int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION); /* Be sure window at (x,y) is not off screen (or even mostly off screen) */ - if (*x > screenWidth - 32) *x = 0; - if (*y > screenHeight - 32) *y = 0; - if (*x < minX) *x = minX; - if (*y < minY) *y = minY; + if (*x > screenGeometry.right - 32) *x = screenGeometry.left; + if (*y > screenGeometry.bottom - 32) *y = screenGeometry.top; + if (*x < screenGeometry.left + minX) *x = screenGeometry.left + minX; + if (*y < screenGeometry.top + minY) *y = screenGeometry.top + minY; } VOID @@ -1052,6 +1056,32 @@ InitTextures() } } +#ifndef SM_CXVIRTUALSCREEN +#define SM_CXVIRTUALSCREEN 78 +#endif +#ifndef SM_CYVIRTUALSCREEN +#define SM_CYVIRTUALSCREEN 79 +#endif +#ifndef SM_XVIRTUALSCREEN +#define SM_XVIRTUALSCREEN 76 +#endif +#ifndef SM_YVIRTUALSCREEN +#define SM_YVIRTUALSCREEN 77 +#endif + +VOID +InitGeometry() +{ + screenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN); + if( !screenHeight ) screenHeight = GetSystemMetrics(SM_CYSCREEN); + screenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN); + if( !screenWidth ) screenWidth = GetSystemMetrics(SM_CXSCREEN); + screenGeometry.left = GetSystemMetrics(SM_XVIRTUALSCREEN); + screenGeometry.top = GetSystemMetrics(SM_YVIRTUALSCREEN); + screenGeometry.right = screenGeometry.left + screenWidth; + screenGeometry.bottom = screenGeometry.top + screenHeight; +} + BOOL InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) { @@ -1070,7 +1100,7 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) GetCurrentDirectory(MSG_SIZ, installDir); } gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise - screenWidth = screenHeight = 1000; // [HGM] placement: kludge to allow calling EnsureOnScreen from InitAppData + InitGeometry(); InitAppData(lpCmdLine); /* Get run-time parameters */ /* xboard, and older WinBoards, controlled the move sound with the appData.ringBellAfterMoves option. In the current WinBoard, we @@ -1117,8 +1147,7 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) iconBlack = LoadIcon(hInstance, "icon_black"); iconCurrent = iconWhite; InitDrawingColors(); - screenHeight = GetSystemMetrics(SM_CYSCREEN); - screenWidth = GetSystemMetrics(SM_CXSCREEN); + InitPosition(0); // to set nr of ranks and files, which might be non-default through command-line args for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) { /* Compute window size for each board size, and use the largest @@ -1199,6 +1228,7 @@ InitMenuChecks() (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit, MF_BYCOMMAND|(saveSettingsOnExit ? MF_CHECKED : MF_UNCHECKED)); + EnableMenuItem(hmenu, IDM_SaveSelected, MF_GRAYED); } //--------------------------------------------------------------------------------------------------------- @@ -1782,6 +1812,8 @@ static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index ) COLORREF chroma = RGB(0xFF,0x00,0xFF); RECT rc; SIZE sz; + + POINT pt; int backColor = whitePieceColor; int foreColor = blackPieceColor; @@ -2271,9 +2303,10 @@ InitDrawingSizes(BoardSize boardSize, int flags) { // correct board size to one where built-in pieces exist if((v == VariantCapablanca || v == VariantGothic || v == VariantGrand || v == VariantCapaRandom || v == VariantJanus || v == VariantSuper) && (boardSize < SizePetite || boardSize > SizeBulky) // Archbishop and Chancellor available in entire middle range + || (v == VariantShogi && boardSize != SizeModerate) // Japanese-style Shogi || v == VariantKnightmate || v == VariantSChess || v == VariantXiangqi || v == VariantSpartan - || v == VariantShatranj || v == VariantMakruk || v == VariantGreat || v == VariantFairy ) { + || v == VariantShatranj || v == VariantMakruk || v == VariantGreat || v == VariantFairy || v == VariantLion ) { if(boardSize < SizeMediocre) boardSize = SizePetite; else if(boardSize > SizeModerate) boardSize = SizeBulky; else boardSize = SizeMiddling; @@ -2629,6 +2662,9 @@ InitDrawingSizes(BoardSize boardSize, int flags) pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s"); pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o"); pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w"); + pieceBitmap[0][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "s"); + pieceBitmap[1][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "o"); + pieceBitmap[2][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "w"); if(gameInfo.variant == VariantShogi) { /* promoted Gold represemtations */ pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s"); @@ -3250,6 +3286,9 @@ BOOL HasHighlightInfo() } return result; + + + } BOOL IsDrawArrowEnabled() @@ -3441,6 +3480,7 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc) DisplayHoldingsCount(hdc, x, y, flipView, (int) board[row][column]); else if( column == BOARD_RGHT) /* right align */ DisplayHoldingsCount(hdc, x, y, !flipView, (int) board[row][column]); + else if( piece == DarkSquare) DisplayHoldingsCount(hdc, x, y, 0, 0); else if (appData.monoMode) { if (piece == EmptySquare) { @@ -3942,6 +3982,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) else if(dragInfo.from.x == BOARD_RGHT+1 ) board[dragInfo.from.y][dragInfo.from.x-1]++; + board[dragInfo.from.y][dragInfo.from.x] = dragged_piece; x = dragInfo.pos.x - squareSize / 2; y = dragInfo.pos.y - squareSize / 2; @@ -4272,8 +4313,10 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } else if (PtInRect((LPRECT) &blackRect, pt)) { ClockClick(!flipClock); break; } + if(dragging) { // [HGM] lion: don't destroy dragging info if we are already dragging dragInfo.start.x = dragInfo.start.y = -1; dragInfo.from = dragInfo.start; + } if(fromX == -1 && frozen) { // not sure where this is for fromX = fromY = -1; DrawPosition(forceFullRepaint || FALSE, NULL); /* [AS] */ @@ -4293,7 +4336,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if(PromoScroll(pt.x - boardRect.left, pt.y - boardRect.top)) break; MovePV(pt.x - boardRect.left, pt.y - boardRect.top, boardRect.bottom - boardRect.top); if ((appData.animateDragging || appData.highlightDragging) - && (wParam & MK_LBUTTON) + && (wParam & MK_LBUTTON || dragging == 2) && dragInfo.from.x >= 0) { BOOL full_repaint = FALSE; @@ -4302,7 +4345,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) dragInfo.pos = pt; } if (appData.highlightDragging) { - SetHighlights(fromX, fromY, x, y); + HoverEvent(highlightInfo.sq[1].x, highlightInfo.sq[1].y, x, y); if( IsDrawArrowEnabled() && (x < 0 || x >= BOARD_WIDTH || y < 0 || y >= BOARD_HEIGHT) ) { full_repaint = TRUE; } @@ -4437,6 +4480,8 @@ ButtonProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) return CallWindowProc(buttonDesc[i].wndproc, hwnd, message, wParam, lParam); } +static int promoStyle; + /* Process messages for Promotion dialog box */ LRESULT CALLBACK Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) @@ -4467,13 +4512,9 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) PieceToChar(BlackMarshall) != '~') ) ? SW_SHOW : SW_HIDE); /* [HGM] Hide B & R button in Shogi, use Q as promote, N as defer */ - ShowWindow(GetDlgItem(hDlg, PB_Rook), - gameInfo.variant != VariantShogi ? - SW_SHOW : SW_HIDE); - ShowWindow(GetDlgItem(hDlg, PB_Bishop), - gameInfo.variant != VariantShogi ? - SW_SHOW : SW_HIDE); - if(gameInfo.variant == VariantShogi) { + ShowWindow(GetDlgItem(hDlg, PB_Rook), !promoStyle ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hDlg, PB_Bishop), !promoStyle ? SW_SHOW : SW_HIDE); + if(promoStyle) { SetDlgItemText(hDlg, PB_Queen, "YES"); SetDlgItemText(hDlg, PB_Knight, "NO"); SetWindowText(hDlg, "Promote?"); @@ -4494,7 +4535,7 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) promoChar = gameInfo.variant == VariantSuper ? PieceToChar(BlackSilver) : PieceToChar(BlackKing); break; case PB_Queen: - promoChar = gameInfo.variant == VariantShogi ? '+' : ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteQueen : BlackQueen)); + promoChar = promoStyle ? '+' : ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteQueen : BlackQueen)); break; case PB_Rook: promoChar = ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteRook : BlackRook)); @@ -4511,7 +4552,8 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) promoChar = ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteAngel : BlackAngel)); break; case PB_Knight: - promoChar = gameInfo.variant == VariantShogi ? '=' : PieceToChar(WhiteOnMove(currentMove) ? WhiteKnight : BlackKnight); + promoChar = gameInfo.variant == VariantShogi ? '=' : promoStyle ? NULLCHAR : + ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteKnight : BlackKnight)); break; default: return FALSE; @@ -4542,8 +4584,9 @@ PromotionPopup(HWND hwnd) } void -PromotionPopUp() +PromotionPopUp(char choice) { + promoStyle = (choice == '+'); DrawPosition(TRUE, NULL); PromotionPopup(hwndMain); } @@ -4681,7 +4724,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { FARPROC lpProc; - int wmId, wmEvent; + int wmId; char *defName; FILE *f; UINT number; @@ -4784,7 +4827,6 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_COMMAND: /* message: command from application menu */ wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); switch (wmId) { case IDM_NewGame: @@ -4877,6 +4919,16 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } break; + case IDM_SaveSelected: + f = OpenFileDialog(hwnd, "a", "", + "pgn", + GAME_FILT, + _("Save Game to File"), NULL, fileTitle, NULL); + if (f != NULL) { + SaveSelected(f, 0, ""); + } + break; + case IDM_CreateBook: CreateBookEvent(); break; @@ -5103,6 +5155,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) break; case IDM_Rematch: + RematchEvent(); break; @@ -5592,7 +5645,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if( hwnd == hwndMain && appData.useStickyWindows ) { LPWINDOWPOS lpwp = (LPWINDOWPOS) lParam; - if( ((lpwp->flags & SWP_NOMOVE) == 0) && ((lpwp->flags & SWP_NOSIZE) != 0) ) { + if( ((lpwp->flags & SWP_NOMOVE) == 0) /*&& ((lpwp->flags & SWP_NOSIZE) != 0)*/ ) { // [HGM] in Win8 size always accompanies move? /* Window is moving */ RECT rcMain; @@ -6260,6 +6313,7 @@ StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) SwapEngines(singleList); // temporarily swap first and second, to load a second 'first', ... ParseArgs(StringGet, &p); SwapEngines(singleList); // ... and then make it 'second' + appData.noChessProgram = FALSE; appData.icsActive = FALSE; } else if (IsDlgButtonChecked(hDlg, OPT_ChessServer)) { @@ -6350,7 +6404,7 @@ LRESULT CALLBACK CommentDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { static HANDLE hwndText = NULL; - int len, newSizeX, newSizeY, flags; + int len, newSizeX, newSizeY; static int sizeX, sizeY; char *str; RECT rect; @@ -6378,7 +6432,6 @@ CommentDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) /* Size and position the dialog */ if (!commentDialog) { commentDialog = hDlg; - flags = SWP_NOZORDER; GetClientRect(hDlg, &rect); sizeX = rect.right; sizeY = rect.bottom; @@ -6715,7 +6768,6 @@ ErrorPopDown() LRESULT CALLBACK ErrorDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { - HANDLE hwndText; RECT rChild; switch (message) { @@ -6739,7 +6791,6 @@ ErrorDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) errorDialog = hDlg; SetWindowText(hDlg, errorTitle); - hwndText = GetDlgItem(hDlg, OPT_ErrorText); SetDlgItemText(hDlg, OPT_ErrorText, errorMessage); return FALSE; @@ -6765,7 +6816,6 @@ HWND gothicDialog = NULL; LRESULT CALLBACK GothicDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { - HANDLE hwndText; RECT rChild; int height = GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYFRAME); @@ -6784,7 +6834,6 @@ GothicDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) */ gothicDialog = hDlg; SetWindowText(hDlg, errorTitle); - hwndText = GetDlgItem(hDlg, OPT_ErrorText); SetDlgItemText(hDlg, OPT_ErrorText, errorMessage); return FALSE; @@ -6837,6 +6886,7 @@ GothicPopUp(char *title, VariantClass variant) static char *history[HISTORY_SIZE]; int histIn = 0, histP = 0; + VOID SaveInHistory(char *cmd) { @@ -6849,6 +6899,7 @@ SaveInHistory(char *cmd) histIn = (histIn + 1) % HISTORY_SIZE; if (history[histIn] != NULL) { free(history[histIn]); + history[histIn] = NULL; } histP = histIn; @@ -7659,6 +7710,7 @@ DoWriteFile(HANDLE hFile, char *buf, int count, DWORD *outCount, else err = GetLastError(); } + } return err; } @@ -8524,6 +8576,7 @@ HWND gameListOptionsDialog; // low-level front-end: clear text edit / list widget void + GLT_ClearList() { SendDlgItemMessage( gameListOptionsDialog, IDC_GameListTags, LB_RESETCONTENT, 0, 0 ); @@ -8715,6 +8768,13 @@ EditCommentPopUp(int index, char *title, char *str) } +int +Roar() +{ + MyPlaySound(&sounds[(int)SoundRoar]); + return 1; +} + VOID RingBell() { @@ -8872,6 +8932,7 @@ DisplayBlackClock(long timeRemaining, int highlight) HDC hdc; char *flag = blackFlag && gameMode == TwoMachinesPlay ? "(!)" : ""; + if(appData.noGUI) return; hdc = GetDC(hwndMain); if (!IsIconic(hwndMain)) { @@ -9183,15 +9244,15 @@ DestroyChildProcess(ProcRef pr, int/*boolean*/ signal) /*!!if (signal) GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, cp->pid);*/ /* [AS] Special termination modes for misbehaving programs... */ - if( signal == 9 ) { + if( signal & 8 ) { result = TerminateProcess( cp->hProcess, 0 ); if ( appData.debugMode) { fprintf( debugFP, "Terminating process %lu, result=%d\n", cp->pid, result ); } } - else if( signal == 10 ) { - DWORD dw = WaitForSingleObject( cp->hProcess, 3*1000 ); // Wait 3 seconds at most + else if( signal & 4 ) { + DWORD dw = WaitForSingleObject( cp->hProcess, appData.delayAfterQuit*1000 + 50 ); // Wait 3 seconds at most if( dw != WAIT_OBJECT_0 ) { result = TerminateProcess( cp->hProcess, 0 ); @@ -9890,16 +9951,23 @@ AnimateMove(board, fromX, fromY, toX, toY) int toY; { ChessSquare piece; + int x = toX, y = toY; POINT start, finish, mid; POINT frames[kFactor * 2 + 1]; int nFrames, n; + if(killX >= 0 && IS_LION(board[fromY][fromX])) Roar(); + if (!appData.animate) return; if (doingSizing) return; if (fromY < 0 || fromX < 0) return; piece = board[fromY][fromX]; if (piece >= EmptySquare) return; + if(killX >= 0) toX = killX, toY = killY; // [HGM] lion: first to kill square + +again: + ScreenSquare(fromX, fromY, &start); ScreenSquare(toX, toY, &finish); @@ -9938,6 +10006,9 @@ AnimateMove(board, fromX, fromY, toX, toY) } animInfo.pos = finish; DrawPosition(FALSE, NULL); + + if(toX != x || toY != y) { fromX = toX; fromY = toY; toX = x; toY = y; goto again; } // second leg + animInfo.piece = EmptySquare; Explode(board, fromX, fromY, toX, toY); } @@ -10015,6 +10086,7 @@ int flock(int fid, int code) ov.OffsetHigh = 0; switch(code) { case 1: LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, 1024, 0, &ov); break; // LOCK_SH + case 2: LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, 1024, 0, &ov); break; // LOCK_EX case 3: UnlockFileEx(hFile, 0, 1024, 0, &ov); break; // LOCK_UN default: return -1;