X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=winboard%2Fwinboard.c;h=fb64ff7f8448ca14613e18930600658a8908390d;hb=ea750683ac62717dd7346de17b5ae072622ff92a;hp=21460fdadcd911e403dcb1eeff1e444013f5906c;hpb=7e4f4f5718bf4efee8be4abfc981d18cfd6f8438;p=xboard.git diff --git a/winboard/winboard.c b/winboard/winboard.c index 21460fd..fb64ff7 100644 --- a/winboard/winboard.c +++ b/winboard/winboard.c @@ -86,12 +86,13 @@ #include "wsnap.h" -void InitEngineUCI( const char * iniDir, ChessProgramState * cps ); +//void InitEngineUCI( const char * iniDir, ChessProgramState * cps ); int myrandom(void); void mysrandom(unsigned int seed); extern int whiteFlag, blackFlag; +Boolean flipClock = FALSE; void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber); @@ -137,9 +138,10 @@ char installDir[MSG_SIZ]; BoardSize boardSize; BOOLEAN chessProgram; static int boardX, boardY, consoleX, consoleY, consoleW, consoleH; -static int squareSize, lineGap; +static int squareSize, lineGap, minorSize; static int winWidth, winHeight; -static RECT messageRect, whiteRect, blackRect; +static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo +static int logoHeight = 0; static char messageText[MESSAGE_TEXT_MAX]; static int clockTimerEvent = 0; static int loadGameTimerEvent = 0; @@ -387,6 +389,7 @@ LRESULT CALLBACK VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def); void ParseIcsTextMenu(char *icsTextMenuString); VOID PopUpMoveDialog(char firstchar); +VOID PopUpNameDialog(char firstchar); VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca); /* [AS] */ @@ -423,7 +426,7 @@ VOID EngineOutputPopDown(); BOOL EngineOutputIsUp(); VOID EngineOutputUpdate( FrontEndProgramStats * stats ); -VOID GothicPopUp(char *title); +VOID GothicPopUp(char *title, VariantClass variant); /* * Setting "frozen" should disable all user input other than deleting * the window. We do this while engines are initializing themselves. @@ -596,8 +599,8 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) InitBackEnd1(); - InitEngineUCI( installDir, &first ); - InitEngineUCI( installDir, &second ); +// InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1() +// InitEngineUCI( installDir, &second ); /* Create a main window for this application instance. */ hwnd = CreateWindow(szAppName, szTitle, @@ -611,6 +614,35 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) return (FALSE); } + /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */ + if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) { + first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); + + if (first.programLogo == NULL && appData.debugMode) { + fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo ); + } + } else if(appData.autoLogo) { + if(appData.firstDirectory && appData.firstDirectory[0]) { + char buf[MSG_SIZ]; + sprintf(buf, "%s/logo.bmp", appData.firstDirectory); + first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); + } + } + + if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) { + second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); + + if (second.programLogo == NULL && appData.debugMode) { + fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo ); + } + } else if(appData.autoLogo) { + if(appData.secondDirectory && appData.secondDirectory[0]) { + char buf[MSG_SIZ]; + sprintf(buf, "%s\\logo.bmp", appData.secondDirectory); + second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); + } + } + iconWhite = LoadIcon(hInstance, "icon_white"); iconBlack = LoadIcon(hInstance, "icon_black"); iconCurrent = iconWhite; @@ -628,6 +660,7 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) boardSize = (BoardSize)ibs; } } + InitDrawingSizes(boardSize, 0); InitMenuChecks(); buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS); @@ -655,11 +688,6 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) mysrandom( (unsigned) time(NULL) ); - /* Make a console window if needed */ - if (appData.icsActive) { - ConsoleCreate(); - } - /* [AS] Restore layout */ if( wpMoveHistory.visible ) { MoveHistoryPopUp(); @@ -690,17 +718,12 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +#if 0 /* [AS] Disable the FRC stuff if not playing the proper variant */ if( gameInfo.variant != VariantFischeRandom ) { EnableMenuItem( GetMenu(hwndMain), IDM_NewGameFRC, MF_GRAYED ); } -#ifdef FAIRY -#ifdef GOTHIC - /* [HGM] Gothic licensing requirement */ - if(gameInfo.variant == VariantGothic) - GothicPopUp(GOTHIC); -#endif // GOTHIC -#endif // FAIRY +#endif if (hwndConsole) { #if AOT_CONSOLE SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, @@ -1171,14 +1194,30 @@ ArgDescriptor argDescriptors[] = { { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE }, { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE }, { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE }, - { "matchPause", ArgInt, (LPVOID) &appData.matchPause, FALSE }, - { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, TRUE }, + { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE }, + { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE }, + { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE }, + { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE }, + { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE }, + { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE }, + { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE }, { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE }, { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE }, { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE }, { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE }, { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE }, { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE }, + { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE }, + { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE }, + { "userName", ArgString, (LPVOID) &appData.userName, FALSE }, + { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE }, + { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE }, + { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE }, + { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE }, + { "niceEngines", ArgInt, (LPVOID) &appData.niceEngines, TRUE }, + { "firstLogo", ArgFilename, (LPVOID) &appData.firstLogo, FALSE }, + { "secondLogo", ArgFilename, (LPVOID) &appData.secondLogo, FALSE }, + { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE }, #ifdef ZIPPY { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE }, @@ -1222,6 +1261,18 @@ ArgDescriptor argDescriptors[] = { /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */ { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE }, #endif + /* [HGM] options for broadcasting and time odds */ + { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE }, + { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE }, + { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE }, + { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE }, + { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE }, + { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE }, + { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE }, + { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE }, + { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE }, + { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE }, + { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE }, { NULL, ArgNone, NULL, FALSE } }; @@ -1783,6 +1834,7 @@ InitAppData(LPSTR lpCmdLine) appData.reuseFirst = TRUE; appData.reuseSecond = TRUE; appData.blindfold = FALSE; + appData.icsEngineAnalyze = FALSE; dcb.DCBlength = sizeof(DCB); dcb.BaudRate = 9600; dcb.fBinary = TRUE; @@ -1797,7 +1849,12 @@ InitAppData(LPSTR lpCmdLine) dcb.fNull = FALSE; dcb.fRtsControl = RTS_CONTROL_ENABLE; dcb.fAbortOnError = FALSE; - dcb.wReserved = 0; + /* Microsoft SDK >= Feb. 2003 (MS VS >= 2002) */ + #if (defined(_MSC_VER) && _MSC_VER <= 1200) + //dcb.wReserved = 0; + #else + dcb.wReserved = 0; + #endif dcb.ByteSize = 7; dcb.Parity = SPACEPARITY; dcb.StopBits = ONESTOPBIT; @@ -1896,6 +1953,20 @@ InitAppData(LPSTR lpCmdLine) appData.drawRepeats = 6; appData.matchPause = 10000; appData.alphaRank = FALSE; + appData.allWhite = FALSE; + appData.upsideDown = FALSE; + appData.serverPause = 15; + appData.serverMovesName = NULL; + appData.suppressLoadMoves = FALSE; + appData.firstTimeOdds = 1; + appData.secondTimeOdds = 1; + appData.firstAccumulateTC = 1; // combine previous and current sessions + appData.secondAccumulateTC = 1; + appData.firstNPS = -1; // [HGM] nps: use wall-clock time + appData.secondNPS = -1; + appData.engineComments = 1; + appData.smpCores = 1; // [HGM] SMP: max nr of cores + appData.egtFormats = ""; #ifdef ZIPPY appData.zippyTalk = ZIPPY_TALK; @@ -1940,6 +2011,35 @@ InitAppData(LPSTR lpCmdLine) appData.NrRanks > BOARD_SIZE ) DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2); + /* [HGM] After parsing the options from the .ini file, and overruling them + * with options from the command line, we now make an even higher priority + * overrule by WB options attached to the engine command line. This so that + * tournament managers can use WB options (such as /timeOdds) that follow + * the engines. + */ + if(appData.firstChessProgram != NULL) { + char *p = StrStr(appData.firstChessProgram, "WBopt"); + static char *f = "first"; + char buf[MSG_SIZ], *q = buf; + if(p != NULL) { // engine command line contains WinBoard options + sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first" + ParseArgs(StringGet, &q); + p[-1] = 0; // cut them offengine command line + } + } + // now do same for second chess program + if(appData.secondChessProgram != NULL) { + char *p = StrStr(appData.secondChessProgram, "WBopt"); + static char *s = "second"; + char buf[MSG_SIZ], *q = buf; + if(p != NULL) { // engine command line contains WinBoard options + sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first" + ParseArgs(StringGet, &q); + p[-1] = 0; // cut them offengine command line + } + } + + /* Propagate options that affect others */ if (appData.matchMode || appData.matchGames) chessProgram = TRUE; if (appData.icsActive || appData.noChessProgram) { @@ -2300,36 +2400,44 @@ enum { PM_WB = (int) WhiteBishop, PM_WR = (int) WhiteRook, PM_WQ = (int) WhiteQueen, -#ifdef FAIRY PM_WF = (int) WhiteFerz, PM_WW = (int) WhiteWazir, PM_WE = (int) WhiteAlfil, + PM_WM = (int) WhiteMan, + PM_WO = (int) WhiteCannon, + PM_WU = (int) WhiteUnicorn, PM_WH = (int) WhiteNightrider, - PM_WA = (int) WhiteCardinal, + PM_WA = (int) WhiteAngel, PM_WC = (int) WhiteMarshall, + PM_WAB = (int) WhiteCardinal, + PM_WD = (int) WhiteDragon, + PM_WL = (int) WhiteLance, + PM_WS = (int) WhiteCobra, + PM_WV = (int) WhiteFalcon, + PM_WSG = (int) WhiteSilver, PM_WG = (int) WhiteGrasshopper, - PM_WO = (int) WhiteCannon, - PM_WM = (int) WhiteMan, - PM_WU = (int) WhiteUnicorn, -#endif PM_WK = (int) WhiteKing, PM_BP = (int) BlackPawn, PM_BN = (int) BlackKnight, PM_BB = (int) BlackBishop, PM_BR = (int) BlackRook, PM_BQ = (int) BlackQueen, -#ifdef FAIRY PM_BF = (int) BlackFerz, PM_BW = (int) BlackWazir, PM_BE = (int) BlackAlfil, + PM_BM = (int) BlackMan, + PM_BO = (int) BlackCannon, + PM_BU = (int) BlackUnicorn, PM_BH = (int) BlackNightrider, - PM_BA = (int) BlackCardinal, + PM_BA = (int) BlackAngel, PM_BC = (int) BlackMarshall, PM_BG = (int) BlackGrasshopper, - PM_BO = (int) BlackCannon, - PM_BM = (int) BlackMan, - PM_BU = (int) BlackUnicorn, -#endif + PM_BAB = (int) BlackCardinal, + PM_BD = (int) BlackDragon, + PM_BL = (int) BlackLance, + PM_BS = (int) BlackCobra, + PM_BV = (int) BlackFalcon, + PM_BSG = (int) BlackSilver, PM_BK = (int) BlackKing }; @@ -2339,36 +2447,13 @@ static HBITMAP hPieceFace[(int) EmptySquare]; static int fontBitmapSquareSize = 0; static char pieceToFontChar[(int) EmptySquare] = { 'p', 'n', 'b', 'r', 'q', -#ifdef FAIRY 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k', -#endif 'k', 'o', 'm', 'v', 't', 'w', -#ifdef FAIRY 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l', -#endif 'l' }; -static BOOL SetPieceToFontCharTable( const char * map ) -{ - BOOL result = FALSE; int NrPieces; - - if( map != NULL && (NrPieces=strlen(map)) <= (int) EmptySquare - && NrPieces >= 12 && !(NrPieces&1)) { - int i; /* [HGM] Accept even length from 12 to 32 */ - - for( i=0; i<(int) EmptySquare; i++ ) pieceToFontChar[i] = 0; - for( i=0; i= 6 && appData.fontBackColorBlack != appData.fontForeColorBlack ) { + else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) { backColor = appData.fontBackColorBlack; foreColor = appData.fontForeColorBlack; } @@ -2483,11 +2567,15 @@ static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index ) SetBkMode( hdc, TRANSPARENT ); SetTextColor( hdc, chroma ); /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */ - TextOut( hdc, pt.x, pt.y, &pieceToFontChar[index], 1 ); + TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 ); SelectObject( hdc, GetStockObject(WHITE_BRUSH) ); /* Step 3: the area outside the piece is filled with white */ - FloodFill( hdc, 0, 0, chroma ); +// FloodFill( hdc, 0, 0, chroma ); + ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE ); + ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big + ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE ); + ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE ); SelectObject( hdc, GetStockObject(BLACK_BRUSH) ); /* Step 4: this is the tricky part, the area inside the piece is filled with black, @@ -2495,14 +2583,30 @@ static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index ) There should be a better way to do this... if we could create a region or path from the fill operation we would be fine for example. */ - FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) ); +// FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) ); + ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER ); + + { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */ + HDC dc2 = CreateCompatibleDC( hdc_window ); + HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize ); + + SelectObject( dc2, bm2 ); + BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy + BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT ); + BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT ); + BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT ); + BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT ); + + DeleteDC( dc2 ); + DeleteObject( bm2 ); + } SetTextColor( hdc, 0 ); /* Step 5: some fonts have "disconnected" areas that are skipped by the fill: draw the piece again in black for safety. */ - TextOut( hdc, pt.x, pt.y, &pieceToFontChar[index], 1 ); + TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 ); SelectObject( hdc, hbm_old ); @@ -2543,7 +2647,7 @@ static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index ) } SetTextColor( hdc, foreColor ); - TextOut( hdc, pt.x, pt.y, &pieceToFontChar[index], 1 ); + TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 ); SelectObject( hdc, hbm_old ); @@ -2581,8 +2685,8 @@ static int TranslatePieceToFontPiece( int piece ) return PM_WQ; case WhiteKing: return PM_WK; -#ifdef FAIRY - case BlackCardinal: + + case BlackAngel: return PM_BA; case BlackMarshall: return PM_BC; @@ -2602,7 +2706,20 @@ static int TranslatePieceToFontPiece( int piece ) return PM_BG; case BlackMan: return PM_BM; - case WhiteCardinal: + case BlackSilver: + return PM_BSG; + case BlackLance: + return PM_BL; + case BlackFalcon: + return PM_BV; + case BlackCobra: + return PM_BS; + case BlackCardinal: + return PM_BAB; + case BlackDragon: + return PM_BD; + + case WhiteAngel: return PM_WA; case WhiteMarshall: return PM_WC; @@ -2622,7 +2739,18 @@ static int TranslatePieceToFontPiece( int piece ) return PM_WG; case WhiteMan: return PM_WM; -#endif + case WhiteSilver: + return PM_WSG; + case WhiteLance: + return PM_WL; + case WhiteFalcon: + return PM_WV; + case WhiteCobra: + return PM_WS; + case WhiteCardinal: + return PM_WAB; + case WhiteDragon: + return PM_WD; } return 0; @@ -2655,7 +2783,7 @@ void CreatePiecesFromFont() DeleteObject( hPieceFont ); } else { - for( i=0; i<12; i++ ) { + for( i=0; i<=(int)BlackKing; i++ ) { hPieceMask[i] = NULL; hPieceFace[i] = NULL; } @@ -2692,37 +2820,35 @@ void CreatePiecesFromFont() } else { /* Setup font-to-piece character table */ - if( ! SetPieceToFontCharTable(appData.fontToPieceTable) ) { + if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) { /* No (or wrong) global settings, try to detect the font */ if( strstr(lf.lfFaceName,"Alpha") != NULL ) { /* Alpha */ - SetPieceToFontCharTable("phbrqkojntwl"); + SetCharTable(pieceToFontChar, "phbrqkojntwl"); } else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) { /* DiagramTT* family */ - SetPieceToFontCharTable("PNLRQKpnlrqk"); + SetCharTable(pieceToFontChar, "PNLRQKpnlrqk"); } -#ifdef FAIRY else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) { /* Fairy symbols */ - SetPieceToFontCharTable("PNBRACFHEWUOGMQKpnbracfewuogmqk"); + SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk"); } -#endif else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) { /* Good Companion (Some characters get warped as literal :-( */ char s[] = "1cmWG0ñueOS¯®oYI23wgQU"; s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3; - SetPieceToFontCharTable(s); + SetCharTable(pieceToFontChar, s); } else { /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */ - SetPieceToFontCharTable("pnbrqkomvtwl"); + SetCharTable(pieceToFontChar, "pnbrqkomvtwl"); } } /* Create bitmaps */ hfont_old = SelectObject( hdc, hPieceFont ); - +#if 0 CreatePieceMaskFromFont( hdc_window, hdc, PM_WP ); CreatePieceMaskFromFont( hdc_window, hdc, PM_WN ); CreatePieceMaskFromFont( hdc_window, hdc, PM_WB ); @@ -2735,7 +2861,7 @@ void CreatePiecesFromFont() CreatePieceMaskFromFont( hdc_window, hdc, PM_BR ); CreatePieceMaskFromFont( hdc_window, hdc, PM_BQ ); CreatePieceMaskFromFont( hdc_window, hdc, PM_BK ); -#ifdef FAIRY + CreatePieceMaskFromFont( hdc_window, hdc, PM_WA ); CreatePieceMaskFromFont( hdc_window, hdc, PM_WC ); CreatePieceMaskFromFont( hdc_window, hdc, PM_WF ); @@ -2746,6 +2872,12 @@ void CreatePiecesFromFont() CreatePieceMaskFromFont( hdc_window, hdc, PM_WO ); CreatePieceMaskFromFont( hdc_window, hdc, PM_WG ); CreatePieceMaskFromFont( hdc_window, hdc, PM_WM ); + CreatePieceMaskFromFont( hdc_window, hdc, PM_WSG ); + CreatePieceMaskFromFont( hdc_window, hdc, PM_WV ); + CreatePieceMaskFromFont( hdc_window, hdc, PM_WAB ); + CreatePieceMaskFromFont( hdc_window, hdc, PM_WD ); + CreatePieceMaskFromFont( hdc_window, hdc, PM_WL ); + CreatePieceMaskFromFont( hdc_window, hdc, PM_WS ); CreatePieceMaskFromFont( hdc_window, hdc, PM_BA ); CreatePieceMaskFromFont( hdc_window, hdc, PM_BC ); CreatePieceMaskFromFont( hdc_window, hdc, PM_BF ); @@ -2756,8 +2888,17 @@ void CreatePiecesFromFont() CreatePieceMaskFromFont( hdc_window, hdc, PM_BO ); CreatePieceMaskFromFont( hdc_window, hdc, PM_BG ); CreatePieceMaskFromFont( hdc_window, hdc, PM_BM ); + CreatePieceMaskFromFont( hdc_window, hdc, PM_BSG ); + CreatePieceMaskFromFont( hdc_window, hdc, PM_BV ); + CreatePieceMaskFromFont( hdc_window, hdc, PM_BAB ); + CreatePieceMaskFromFont( hdc_window, hdc, PM_BD ); + CreatePieceMaskFromFont( hdc_window, hdc, PM_BL ); + CreatePieceMaskFromFont( hdc_window, hdc, PM_BS ); +#else + for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */ + if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */ + CreatePieceMaskFromFont( hdc_window, hdc, i ); #endif - SelectObject( hdc, hfont_old ); fontBitmapSquareSize = squareSize; @@ -2875,9 +3016,10 @@ ResizeBoard(int newSizeX, int newSizeY, int flags) if (IsIconic(hwndMain)) return; if (recurse > 0) return; recurse++; - while (newSize > 0 && - (newSizeX < sizeInfo[newSize].cliWidth || - newSizeY < sizeInfo[newSize].cliHeight)) { + while (newSize > 0) { + InitDrawingSizes(newSize, 0); + if(newSizeX >= sizeInfo[newSize].cliWidth || + newSizeY >= sizeInfo[newSize].cliHeight) break; newSize--; } boardSize = newSize; @@ -2904,12 +3046,13 @@ InitDrawingSizes(BoardSize boardSize, int flags) LOGBRUSH logbrush; /* [HGM] call with -1 uses old size (for if nr of files, ranks changes) */ - if(boardSize == (BoardSize)(-1) ) boardSize = oldBoardSize; + if(boardSize == (BoardSize)(-2) ) boardSize = oldBoardSize; tinyLayout = sizeInfo[boardSize].tinyLayout; smallLayout = sizeInfo[boardSize].smallLayout; squareSize = sizeInfo[boardSize].squareSize; lineGap = sizeInfo[boardSize].lineGap; + minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted */ if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) { lineGap = appData.overrideLineGap; @@ -2953,27 +3096,52 @@ InitDrawingSizes(BoardSize boardSize, int flags) ReleaseDC(hwndMain, hdc); /* Compute where everything goes */ - whiteRect.left = OUTER_MARGIN; - whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2; - whiteRect.top = OUTER_MARGIN; - whiteRect.bottom = whiteRect.top + clockSize.cy; + if(first.programLogo || second.programLogo) { + /* [HGM] logo: if either logo is on, reserve space for it */ + logoHeight = 2*clockSize.cy; + leftLogoRect.left = OUTER_MARGIN; + leftLogoRect.right = leftLogoRect.left + 4*clockSize.cy; + leftLogoRect.top = OUTER_MARGIN; + leftLogoRect.bottom = OUTER_MARGIN + logoHeight; + + rightLogoRect.right = OUTER_MARGIN + boardWidth; + rightLogoRect.left = rightLogoRect.right - 4*clockSize.cy; + rightLogoRect.top = OUTER_MARGIN; + rightLogoRect.bottom = OUTER_MARGIN + logoHeight; + + + blackRect.left = leftLogoRect.right; + blackRect.right = rightLogoRect.left; + blackRect.top = OUTER_MARGIN; + blackRect.bottom = blackRect.top + clockSize.cy; + + whiteRect.left = blackRect.left ; + whiteRect.right = blackRect.right; + whiteRect.top = blackRect.bottom; + whiteRect.bottom = leftLogoRect.bottom; + } else { + whiteRect.left = OUTER_MARGIN; + whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2; + whiteRect.top = OUTER_MARGIN + logoHeight; + whiteRect.bottom = whiteRect.top + clockSize.cy; - blackRect.left = whiteRect.right + INNER_MARGIN; - blackRect.right = blackRect.left + boardWidth/2 - 1; - blackRect.top = whiteRect.top; - blackRect.bottom = whiteRect.bottom; + blackRect.left = whiteRect.right + INNER_MARGIN; + blackRect.right = blackRect.left + boardWidth/2 - 1; + blackRect.top = whiteRect.top; + blackRect.bottom = whiteRect.bottom; + } - messageRect.left = whiteRect.left + MESSAGE_LINE_LEFTMARGIN; + messageRect.left = OUTER_MARGIN + MESSAGE_LINE_LEFTMARGIN; if (appData.showButtonBar) { - messageRect.right = blackRect.right + messageRect.right = OUTER_MARGIN + boardWidth // [HGM] logo: expressed independent of clock placement - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN; } else { - messageRect.right = blackRect.right; + messageRect.right = OUTER_MARGIN + boardWidth; } messageRect.top = whiteRect.bottom + INNER_MARGIN; messageRect.bottom = messageRect.top + messageSize.cy; - boardRect.left = whiteRect.left; + boardRect.left = OUTER_MARGIN; boardRect.right = boardRect.left + boardWidth; boardRect.top = messageRect.bottom + INNER_MARGIN; boardRect.bottom = boardRect.top + boardHeight; @@ -3085,7 +3253,17 @@ InitDrawingSizes(BoardSize boardSize, int flags) } } - if (boardSize == oldBoardSize) return; + /* [HGM] Licensing requirement */ +#ifdef GOTHIC + if(gameInfo.variant == VariantGothic) GothicPopUp( GOTHIC, VariantGothic); else +#endif +#ifdef FALCON + if(gameInfo.variant == VariantFalcon) GothicPopUp( FALCON, VariantFalcon); else +#endif + GothicPopUp( "", VariantNormal); + + +/* if (boardSize == oldBoardSize) return; [HGM] variant might have changed */ oldBoardSize = boardSize; oldTinyLayout = tinyLayout; @@ -3099,88 +3277,198 @@ InitDrawingSizes(BoardSize boardSize, int flags) } } + fontBitmapSquareSize = 0; /* [HGM] render: make sure pieces will be recreated, as we might need others now */ + // Orthodox Chess pieces pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s"); pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s"); pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "s"); pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "s"); - pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s"); pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "s"); pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "o"); pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "o"); pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "o"); pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "o"); - pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o"); pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "o"); pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "w"); pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "w"); pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "w"); pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w"); - pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w"); pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w"); -#ifdef FAIRY - if(squareSize==72 || squareSize==49) { /* experiment with some home-made bitmaps */ - pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "s"); - pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "o"); - pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "w"); - pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "s"); - pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "o"); - pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "w"); - if(!strcmp(appData.variant, "shogi")) { /* promoted Gold represemtations */ - pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "wp", squareSize, "s"); - pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "wp", squareSize, "o"); - pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "w", squareSize, "w"); - pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "s"); - pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "o"); - pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "w", squareSize, "w"); - pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wl", squareSize, "s"); - pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "wl", squareSize, "o"); - pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "w", squareSize, "w"); - pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "ws", squareSize, "s"); - pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "ws", squareSize, "o"); - pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "w", squareSize, "w"); - } else { - pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "s"); - pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "o"); - pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "w"); - pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "s"); - pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "o"); - pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "w"); - pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "s"); - pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "o"); - pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "w"); - pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "s"); - pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "o"); - pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "w"); - pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "s"); - pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "o"); - pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "w"); - } - 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][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "s"); - pieceBitmap[1][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "o"); - pieceBitmap[2][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "w"); - if(strcmp(appData.variant, "crazyhouse") && strcmp(appData.variant, "shogi")) { - pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s"); - pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o"); - pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "w"); + if( !strcmp(appData.variant, "shogi") && (squareSize==72 || squareSize==49)) { + // in Shogi, Hijack the unused Queen for Lance + pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "s"); + pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "o"); + pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "w"); } else { - pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "dk", squareSize, "s"); - pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "dk", squareSize, "o"); - pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "dk", squareSize, "w"); - } - if(!strcmp(appData.variant, "xiangqi") || !strcmp(appData.variant, "shogi")) { - for(i=0; i<2; i++) - if (pieceBitmap[i][WhiteQueen] != NULL) - DeleteObject(pieceBitmap[i][WhiteQueen]); - pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "o", squareSize, "s"); - pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "o", squareSize, "o"); - pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "o", squareSize, "w"); - } + pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s"); + pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o"); + pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w"); + } + + if(squareSize <= 72 && squareSize >= 33) { + /* A & C are available in most sizes now */ + if(squareSize != 49 && squareSize != 72 && squareSize != 33) { // Vortex-like + pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "s"); + pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "o"); + pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "w"); + pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s"); + pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o"); + pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w"); + pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "s"); + pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "o"); + pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "w"); + pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s"); + pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o"); + pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w"); + } else { // Smirf-like + pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "s"); + pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "o"); + pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "w"); + } + if(gameInfo.variant == VariantGothic) { // Vortex-like + pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "s"); + pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "o"); + pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "w"); + } else { // WinBoard standard + pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s"); + pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o"); + pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "w"); + } + } + + + if(squareSize==72 || squareSize==49 || squareSize==33) { /* experiment with some home-made bitmaps */ + pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "s"); + pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "o"); + pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "w"); + pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "s"); + pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "o"); + pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "w"); + pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "s"); + pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "o"); + pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "w"); + pieceBitmap[0][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "s"); + pieceBitmap[1][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "o"); + pieceBitmap[2][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "w"); + pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "s"); + pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "o"); + pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "w"); + pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "s"); + pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "o"); + pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "w"); + pieceBitmap[0][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "s"); + pieceBitmap[1][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "o"); + pieceBitmap[2][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "w"); + pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "s"); + pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "o"); + pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "w"); + pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s"); + pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o"); + pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w"); + pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s"); + pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o"); + pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w"); + + if(gameInfo.variant == VariantShogi) { /* promoted Gold represemtations */ + pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s"); + pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "o"); + pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "w", squareSize, "w"); + pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "s"); + pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "o"); + pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "w", squareSize, "w"); + pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "s"); + pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "o"); + pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "w", squareSize, "w"); + pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "s"); + pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "o"); + pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "w", squareSize, "w"); + } else { + pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "s"); + pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "o"); + pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "w"); + pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "s"); + pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "o"); + pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "w"); + pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s"); + pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o"); + pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w"); + pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "s"); + pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "o"); + pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "w"); + } + + } else { /* other size, no special bitmaps available. Use smaller symbols */ + if((int)boardSize < 2) minorSize = sizeInfo[0].squareSize; + else minorSize = sizeInfo[(int)boardSize - 2].squareSize; + pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "s"); + pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "o"); + pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "w"); + pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "s"); + pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "o"); + pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "w"); + pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "s"); + pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "o"); + pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "w"); + pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "s"); + pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "o"); + pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "w"); + } + + + if(gameInfo.variant == VariantShogi && squareSize == 58) + /* special Shogi support in this size */ + { for (i=0; i<=2; i++) { /* replace all bitmaps */ + for (piece = WhitePawn; + (int) piece < (int) BlackPawn; + piece = (ChessSquare) ((int) piece + 1)) { + if (pieceBitmap[i][piece] != NULL) + DeleteObject(pieceBitmap[i][piece]); + } + } + pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o"); + pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o"); + pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o"); + pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o"); + pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o"); + pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o"); + pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o"); + pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o"); + pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o"); + pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o"); + pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o"); + pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o"); + pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o"); + pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o"); + pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o"); + pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o"); + pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o"); + pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o"); + pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o"); + pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o"); + pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o"); + pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o"); + pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o"); + pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o"); + pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o"); + pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o"); + pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o"); + pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o"); + pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "w"); + pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "w"); + pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "sr", squareSize, "w"); + pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "w"); + pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "w"); + pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "w"); + pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "sw", squareSize, "w"); + pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "w"); + pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "sp", squareSize, "w"); + pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "sn", squareSize, "w"); + pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "sr", squareSize, "w"); + pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "sr", squareSize, "w"); + pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "sl", squareSize, "w"); + pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "sw", squareSize, "w"); + minorSize = 0; } -#endif - } HBITMAP @@ -3234,7 +3522,7 @@ DrawCoordsOnDC(HDC hdc) oldFont = SelectObject(hdc, font[boardSize][COORD_FONT]->hf); y = boardRect.top + lineGap; - x = boardRect.left + lineGap; + x = boardRect.left + lineGap + gameInfo.holdingsWidth*(squareSize + lineGap); SetTextAlign(hdc, TA_LEFT|TA_TOP); for (i = 0; i < BOARD_HEIGHT; i++) { @@ -3243,10 +3531,10 @@ DrawCoordsOnDC(HDC hdc) y += squareSize + lineGap; } - start = flipView ? 12-BOARD_WIDTH : 12; + start = flipView ? 12-(BOARD_RGHT-BOARD_LEFT) : 12; SetTextAlign(hdc, TA_RIGHT|TA_BOTTOM); - for (i = 0; i < BOARD_WIDTH; i++) { + for (i = 0; i < BOARD_RGHT - BOARD_LEFT; i++) { str[0] = ranks[start + i]; ExtTextOut(hdc, x + squareSize - 2, y - 1, 0, NULL, str, 1, NULL); x += squareSize + lineGap; @@ -3329,6 +3617,7 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, { HBITMAP oldBitmap; HBRUSH oldBrush; + int tmpSize; if (appData.blindfold) return; @@ -3338,7 +3627,7 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, CreatePiecesFromFont(); if( fontBitmapSquareSize == squareSize ) { - int index = TranslatePieceToFontPiece( piece ); + int index = TranslatePieceToFontPiece(piece); SelectObject( tmphdc, hPieceMask[ index ] ); @@ -3368,21 +3657,39 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, sqcolor ? SRCCOPY : NOTSRCCOPY); } else { - if (color) { + tmpSize = squareSize; + if(minorSize && + (piece >= (int)WhiteNightrider && piece <= WhiteGrasshopper || + piece >= (int)BlackNightrider && piece <= BlackGrasshopper) ) { + /* [HGM] no bitmap available for promoted pieces in Crazyhouse */ + /* Bitmaps of smaller size are substituted, but we have to align them */ + x += (squareSize - minorSize)>>1; + y += squareSize - minorSize - 2; + tmpSize = minorSize; + } + if (color || appData.allWhite ) { oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, WHITE_PIECE)); - oldBrush = SelectObject(hdc, whitePieceBrush); - BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A); + if( color ) + oldBrush = SelectObject(hdc, whitePieceBrush); + else oldBrush = SelectObject(hdc, blackPieceBrush); + if(appData.upsideDown && color==flipView) + StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, 0x00B8074A); + else + BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A); #if 0 /* Use black piece color for outline of white pieces */ /* Not sure this looks really good (though xboard does it). Maybe better to have another selectable color, default black */ SelectObject(hdc, blackPieceBrush); /* could have own brush */ SelectObject(tmphdc, PieceBitmap(piece, OUTLINE_PIECE)); - BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A); + BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A); #else /* Use black for outline of white pieces */ SelectObject(tmphdc, PieceBitmap(piece, OUTLINE_PIECE)); - BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, SRCAND); + if(appData.upsideDown && color==flipView) + StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, SRCAND); + else + BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, SRCAND); #endif } else { #if 0 @@ -3393,15 +3700,18 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, Maybe better to have another selectable color, default medium gray? */ oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, BLACK_PIECE)); oldBrush = SelectObject(hdc, whitePieceBrush); /* could have own brush */ - BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A); + BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A); SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE)); SelectObject(hdc, blackPieceBrush); - BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A); + BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A); #else /* Use square color for details of black pieces */ oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE)); oldBrush = SelectObject(hdc, blackPieceBrush); - BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A); + if(appData.upsideDown && !flipView) + StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, 0x00B8074A); + else + BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A); #endif } SelectObject(hdc, oldBrush); @@ -3462,16 +3772,16 @@ VOID RebuildTextureSquareInfo() if( (col + row) & 1 ) { /* Lite square */ if( lite_w >= squareSize && lite_h >= squareSize ) { - backTextureSquareInfo[row][col].x = col * (lite_w - squareSize) / BOARD_WIDTH; - backTextureSquareInfo[row][col].y = row * (lite_h - squareSize) / BOARD_HEIGHT; + backTextureSquareInfo[row][col].x = col * (lite_w - squareSize) / (BOARD_WIDTH-1); /* [HGM] divide by size-1 in stead of size! */ + backTextureSquareInfo[row][col].y = (BOARD_HEIGHT-1-row) * (lite_h - squareSize) / (BOARD_HEIGHT-1); backTextureSquareInfo[row][col].mode = GetBackTextureMode(liteBackTextureMode); } } else { /* Dark square */ if( dark_w >= squareSize && dark_h >= squareSize ) { - backTextureSquareInfo[row][col].x = col * (dark_w - squareSize) / BOARD_WIDTH; - backTextureSquareInfo[row][col].y = row * (dark_h - squareSize) / BOARD_HEIGHT; + backTextureSquareInfo[row][col].x = col * (dark_w - squareSize) / (BOARD_WIDTH-1); + backTextureSquareInfo[row][col].y = (BOARD_HEIGHT-1-row) * (dark_h - squareSize) / (BOARD_HEIGHT-1); backTextureSquareInfo[row][col].mode = GetBackTextureMode(darkBackTextureMode); } } @@ -3778,7 +4088,10 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc) /* [AS] Initialize background textures if needed */ if( liteBackTexture != NULL || darkBackTexture != NULL ) { - if( backTextureSquareSize != squareSize ) { + static int backTextureBoardSize; /* [HGM] boardsize: also new texture if board format changed */ + if( backTextureSquareSize != squareSize + || backTextureBoardSize != BOARD_WIDTH+BOARD_SIZE*BOARD_HEIGHT) { + backTextureBoardSize = BOARD_WIDTH+BOARD_SIZE*BOARD_HEIGHT; backTextureSquareSize = squareSize; RebuildTextureSquareInfo(); } @@ -3794,7 +4107,7 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc) piece = board[row][column]; square_color = ((column + row) % 2) == 1; - if(!strcmp(appData.variant, "xiangqi") ) { + if( gameInfo.variant == VariantXiangqi ) { square_color = !InPalace(row, column); if(BOARD_HEIGHT&1) { if(row==BOARD_HEIGHT/2) square_color ^= 1; } else if(row < BOARD_HEIGHT/2) square_color ^= 1; @@ -3802,7 +4115,6 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc) piece_color = (int) piece < (int) BlackPawn; -#ifdef FAIRY /* [HGM] holdings file: light square or black */ if(column == BOARD_LEFT-2) { if( row > BOARD_HEIGHT - gameInfo.holdingsSize - 1 ) @@ -3821,11 +4133,10 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc) } } if(column == BOARD_LEFT-1 ) /* left align */ - DisplayHoldingsCount(hdc, x, y, 0, (int) board[row][column]); + DisplayHoldingsCount(hdc, x, y, flipView, (int) board[row][column]); else if( column == BOARD_RGHT) /* right align */ - DisplayHoldingsCount(hdc, x, y, 1, (int) board[row][column]); + DisplayHoldingsCount(hdc, x, y, !flipView, (int) board[row][column]); else -#endif if (appData.monoMode) { if (piece == EmptySquare) { BitBlt(hdc, x, y, squareSize, squareSize, 0, 0, 0, @@ -3837,14 +4148,16 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc) else if( backTextureSquareInfo[row][column].mode > 0 ) { /* [AS] Draw the square using a texture bitmap */ HBITMAP hbm = SelectObject( texture_hdc, square_color ? liteBackTexture : darkBackTexture ); + int r = row, c = column; // [HGM] do not flip board in flipView + if(flipView) { r = BOARD_HEIGHT-1 - r; c = BOARD_WIDTH-1 - c; } DrawTile( x, y, squareSize, squareSize, hdc, texture_hdc, - backTextureSquareInfo[row][column].mode, - backTextureSquareInfo[row][column].x, - backTextureSquareInfo[row][column].y ); + backTextureSquareInfo[r][c].mode, + backTextureSquareInfo[r][c].x, + backTextureSquareInfo[r][c].y ); SelectObject( texture_hdc, hbm ); @@ -3869,9 +4182,44 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc) } } +int saveDiagFlag = 0; FILE *diagFile; // [HGM] diag +void fputDW(FILE *f, int x) +{ + fputc(x & 255, f); + fputc(x>>8 & 255, f); + fputc(x>>16 & 255, f); + fputc(x>>24 & 255, f); +} + #define MAX_CLIPS 200 /* more than enough */ VOID +DrawLogoOnDC(HDC hdc, RECT logoRect, ChessProgramState *cps) +{ + HBITMAP bufferBitmap; + BITMAP bi; + RECT Rect; + HDC tmphdc; + HBITMAP hbm; + int w = 100, h = 50; + + if(cps->programLogo == NULL) return; +// GetClientRect(hwndMain, &Rect); +// bufferBitmap = CreateCompatibleBitmap(hdc, Rect.right-Rect.left+1, +// Rect.bottom-Rect.top+1); + tmphdc = CreateCompatibleDC(hdc); + hbm = SelectObject(tmphdc, (HBITMAP) cps->programLogo); + if( GetObject( cps->programLogo, sizeof(bi), &bi ) > 0 ) { + w = bi.bmWidth; + h = bi.bmHeight; + } + StretchBlt(hdc, logoRect.left, logoRect.top, logoRect.right - logoRect.left, + logoRect.bottom - logoRect.top, tmphdc, 0, 0, w, h, SRCCOPY); + SelectObject(tmphdc, hbm); + DeleteDC(tmphdc); +} + +VOID HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) { static Board lastReq, lastDrawn; @@ -4125,6 +4473,11 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) DrawHighlightsOnDC(hdcmem); DrawBoardOnDC(hdcmem, board, tmphdc); + if(logoHeight) { + DrawLogoOnDC(hdc, leftLogoRect, flipClock ? &second : &first); + DrawLogoOnDC(hdc, rightLogoRect, flipClock ? &first : &second); + } + if( appData.highlightMoveWithArrow ) { DrawArrowHighlight(hdcmem); } @@ -4183,6 +4536,80 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) boardRect.right - boardRect.left, boardRect.bottom - boardRect.top, tmphdc, boardRect.left, boardRect.top, SRCCOPY); + if(saveDiagFlag) { + BITMAP b; int i, j, m, w, wb, fac=0; char pData[1000000]; + BITMAPINFOHEADER bih; int color[16], nrColors=0; + + GetObject(bufferBitmap, sizeof(b), &b); + if(b.bmWidthBytes*b.bmHeight <= 990000) { + bih.biSize = sizeof(BITMAPINFOHEADER); + bih.biWidth = b.bmWidth; + bih.biHeight = b.bmHeight; + bih.biPlanes = 1; + bih.biBitCount = b.bmBitsPixel; + bih.biCompression = 0; + bih.biSizeImage = b.bmWidthBytes*b.bmHeight; + bih.biXPelsPerMeter = 0; + bih.biYPelsPerMeter = 0; + bih.biClrUsed = 0; + bih.biClrImportant = 0; +// fprintf(diagFile, "t=%d\nw=%d\nh=%d\nB=%d\nP=%d\nX=%d\n", +// b.bmType, b.bmWidth, b.bmHeight, b.bmWidthBytes, b.bmPlanes, b.bmBitsPixel); + GetDIBits(tmphdc,bufferBitmap,0,b.bmHeight,pData,(BITMAPINFO*)&bih,DIB_RGB_COLORS); +// fprintf(diagFile, "%8x\n", (int) pData); + +#if 1 + wb = b.bmWidthBytes; + // count colors + for(i=0; i>2; i++) { + int k = ((int*) pData)[i]; + for(j=0; j= 16) break; + color[j] = k; + if(j >= nrColors) nrColors = j+1; + } + if(j<16) { // 16 colors is enough. Compress to 4 bits per pixel + INT p = 0; + for(i=0; i>2); w+=2) { + int k = ((int*) pData)[(wb*i>>2) + w]; + for(j=0; j>2) + w + 1]; + for(m=0; m>5)<<2; + } + // write BITMAPFILEHEADER + fprintf(diagFile, "BM"); + fputDW(diagFile, wb*(b.bmHeight - boardRect.top + OUTER_MARGIN)+0x36 + (fac?64:0)); + fputDW(diagFile, 0); + fputDW(diagFile, 0x36 + (fac?64:0)); + // write BITMAPINFOHEADER + fputDW(diagFile, 40); + fputDW(diagFile, b.bmWidth); + fputDW(diagFile, b.bmHeight - boardRect.top + OUTER_MARGIN); + if(fac) fputDW(diagFile, 0x040001); // planes and bits/pixel + else fputDW(diagFile, 0x200001); // planes and bits/pixel + fputDW(diagFile, 0); + fputDW(diagFile, 0); + fputDW(diagFile, 0); + fputDW(diagFile, 0); + fputDW(diagFile, 0); + fputDW(diagFile, 0); + // write color table + if(fac) + for(i=0; i<16; i++) fputDW(diagFile, color[i]); + // write bitmap data + for(i=0; i 0 + : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) { + // click in right holdings, for determining promotion piece + ChessSquare p = boards[currentMove][y][x]; + if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p); + if(p != EmptySquare) { + FinishMove(WhitePromotionQueen, fromX, fromY, toX, toY, ToLower(PieceToChar(p))); + fromX = fromY = -1; + break; + } + } + DrawPosition(FALSE, boards[currentMove]); + break; + } ErrorPopDown(); sameAgain = FALSE; if (y == -2) { /* Downclick vertically off board; check if on clock */ if (PtInRect((LPRECT) &whiteRect, pt)) { - if (gameMode == EditPosition) { + if (gameMode == EditPosition) { SetWhiteToPlayEvent(); } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) { CallFlagEvent(); - } + } else if (gameMode == EditGame) { + AdjustClock((logoHeight > 0 ? flipView: flipClock), -1); + } } else if (PtInRect((LPRECT) &blackRect, pt)) { if (gameMode == EditPosition) { SetBlackToPlayEvent(); } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) { CallFlagEvent(); + } else if (gameMode == EditGame) { + AdjustClock(!(logoHeight > 0 ? flipView: flipClock), -1); } } if (!appData.highlightLastMove) { @@ -4378,6 +4847,8 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) || x == BOARD_LEFT-1 || x == BOARD_RGHT || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize + /* EditPosition, empty square, or different color piece; + click-click move is possible */ ) { break; } else if (fromX == x && fromY == y) { @@ -4390,37 +4861,45 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) ) { /* Downclick on different square. */ /* [HGM] if on holdings file, should count as new first click ! */ - - ChessSquare pdown, pup; - pdown = boards[currentMove][fromY][fromX]; - pup = boards[currentMove][y][x]; - if (gameMode == EditPosition || /* [HGM] max piece > King! */ - !((WhitePawn <= pdown && pdown < BlackPawn && - WhitePawn <= pup && pup < BlackPawn) || - (BlackPawn <= pdown && pdown < EmptySquare && - BlackPawn <= pup && pup < EmptySquare))) { - /* EditPosition, empty square, or different color piece; - click-click move is possible */ + { /* [HGM] now always do UserMoveTest(), and check colors there */ toX = x; toY = y; + /* [HGM] UserMoveEvent requires two calls now, + to make sure move is legal before showing promotion popup */ moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR); + if(moveType == AmbiguousMove) { /* [HGM] Edit-Position move executed */ + fromX = fromY = -1; + ClearHighlights(); + DrawPosition(FALSE, boards[currentMove]); + break; + } else if(moveType != ImpossibleMove) { - if (IsPromotion(fromX, fromY, toX, toY)) { - /* [HGM] UserMoveEvent requires two calls now, - to make sure move is legal before showing promotion popup */ - if (appData.alwaysPromoteToQueen) { + /* [HGM] We use PromotionToKnight in Shogi to indicate frorced promotion */ + if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight || + (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) && + appData.alwaysPromoteToQueen) { FinishMove(moveType, fromX, fromY, toX, toY, 'q'); if (!appData.highlightLastMove) { ClearHighlights(); DrawPosition(forceFullRepaint || FALSE, NULL); } - } else { + } else + if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) { SetHighlights(fromX, fromY, toX, toY); DrawPosition(forceFullRepaint || FALSE, NULL); /* [HGM] Popup calls FinishMove now. If promotion to Q is legal, all are legal! */ + if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) + { ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX]; + // kludge to temporarily execute move on display, wthout promotng yet + promotionChoice = TRUE; + boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank + boards[currentMove][toY][toX] = p; + DrawPosition(FALSE, boards[currentMove]); + boards[currentMove][fromY][fromX] = p; // take back, but display stays + boards[currentMove][toY][toX] = q; + } else PromotionPopup(hwnd); - } } else { /* not a promotion */ if (appData.animate || appData.highlightLastMove) { SetHighlights(fromX, fromY, toX, toY); @@ -4428,15 +4907,20 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) ClearHighlights(); } FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR); + fromX = fromY = -1; if (appData.animate && !appData.highlightLastMove) { ClearHighlights(); DrawPosition(forceFullRepaint || FALSE, NULL); } } + break; + } + if (gotPremove) { + /* [HGM] it seemed that braces were missing here */ + SetPremoveHighlights(fromX, fromY, toX, toY); + fromX = fromY = -1; + break; } - if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY); - fromX = fromY = -1; - break; } ClearHighlights(); DrawPosition(forceFullRepaint || FALSE, NULL); @@ -4462,6 +4946,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) ReleaseCapture(); if (fromX == -1) break; if (x == fromX && y == fromY) { + dragInfo.from.x = dragInfo.from.y = -1; /* Upclick on same square */ if (sameAgain) { /* Clicked same square twice: abort click-click move */ @@ -4472,7 +4957,6 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* First square clicked: start click-click move */ SetHighlights(fromX, fromY, -1, -1); } - dragInfo.from.x = dragInfo.from.y = -1; DrawPosition(forceFullRepaint || FALSE, NULL); } else if (dragInfo.from.x < 0 || dragInfo.from.y < 0) { /* Errant click; ignore */ @@ -4488,14 +4972,34 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) saveAnimate = appData.animate; /* sorry, Hawk :) */ appData.animate = appData.animate && !appData.animateDragging; moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR); + if(moveType == AmbiguousMove) { /* [HGM] Edit-Position move executed */ + fromX = fromY = -1; + ClearHighlights(); + DrawPosition(FALSE, boards[currentMove]); + break; + } else if(moveType != ImpossibleMove) { - if (IsPromotion(fromX, fromY, toX, toY)) { - if (appData.alwaysPromoteToQueen) - FinishMove(moveType, fromX, fromY, toX, toY, 'q'); - else { - DrawPosition(forceFullRepaint || FALSE, NULL); - PromotionPopup(hwnd); /* [HGM] Popup now calls FinishMove */ - } + /* [HGM] use move type to determine if move is promotion. + Knight is Shogi kludge for mandatory promotion, Queen means choice */ + if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight || + (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) && + appData.alwaysPromoteToQueen) + FinishMove(moveType, fromX, fromY, toX, toY, 'q'); + else + if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) { + DrawPosition(forceFullRepaint || FALSE, NULL); + if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) + { ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX]; + // kludge to temporarily execute move on display, wthout promotng yet + promotionChoice = TRUE; + boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank + boards[currentMove][toY][toX] = p; + DrawPosition(FALSE, boards[currentMove]); + boards[currentMove][fromY][fromX] = p; // take back, but display stays + boards[currentMove][toY][toX] = q; + break; + } else + PromotionPopup(hwnd); /* [HGM] Popup now calls FinishMove */ } else FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR); } if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY); @@ -4537,6 +5041,17 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } break; + case WM_MOUSEWHEEL: // [DM] + /* Mouse Wheel is being rolled forward + * Play moves forward + */ + if((short)HIWORD(wParam) > 0 && currentMove < forwardMostMove) ForwardEvent(); + /* Mouse Wheel is being rolled backward + * Play moves backward + */ + if((short)HIWORD(wParam) < 0 && currentMove > backwardMostMove) BackwardEvent(); + break; + case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: ErrorPopDown(); @@ -4549,6 +5064,14 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (appData.highlightDragging) { ClearHighlights(); } + if(y == -2) { + /* [HGM] right mouse button in clock area edit-game mode ups clock */ + if (PtInRect((LPRECT) &whiteRect, pt)) { + if (gameMode == EditGame) AdjustClock((logoHeight > 0 ? flipView: flipClock), 1); + } else if (PtInRect((LPRECT) &blackRect, pt)) { + if (gameMode == EditGame) AdjustClock(!(logoHeight > 0 ? flipView: flipClock), 1); + } + } DrawPosition(TRUE, NULL); switch (gameMode) { @@ -4577,7 +5100,10 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* Just have one menu, on the right button. Windows users don't think to try the middle one, and sometimes other software steals it, or it doesn't really exist. */ - MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1); + if(gameInfo.variant != VariantShogi) + MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1); + else + MenuPopup(hwnd, pt, LoadMenu(hInst, "ShogiPieceMenu"), -1); #endif } break; @@ -4676,19 +5202,37 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER)); ShowWindow(GetDlgItem(hDlg, PB_King), (!appData.testLegality || gameInfo.variant == VariantSuicide || - gameInfo.variant == VariantGiveaway) ? + gameInfo.variant == VariantGiveaway || gameInfo.variant == VariantSuper ) ? SW_SHOW : SW_HIDE); -#ifdef FAIRY - /* [HGM] Only allow C & A promotions in Capablanca Chess */ + /* [HGM] Only allow C & A promotions if these pieces are defined */ ShowWindow(GetDlgItem(hDlg, PB_Archbishop), - (gameInfo.variant == VariantCapablanca || - gameInfo.variant == VariantGothic) ? + (PieceToChar(WhiteAngel) >= 'A' && + PieceToChar(WhiteAngel) != '~' || + PieceToChar(BlackAngel) >= 'A' && + PieceToChar(BlackAngel) != '~' ) ? SW_SHOW : SW_HIDE); ShowWindow(GetDlgItem(hDlg, PB_Chancellor), - (gameInfo.variant == VariantCapablanca || - gameInfo.variant == VariantGothic) ? + (PieceToChar(WhiteMarshall) >= 'A' && + PieceToChar(WhiteMarshall) != '~' || + PieceToChar(BlackMarshall) >= 'A' && + 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); + ShowWindow(GetDlgItem(hDlg, IDC_Yes), + gameInfo.variant == VariantShogi ? + SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hDlg, IDC_No), + gameInfo.variant == VariantShogi ? + SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hDlg, IDC_Centaur), + gameInfo.variant == VariantSuper ? SW_SHOW : SW_HIDE); -#endif return TRUE; case WM_COMMAND: /* message: received a command */ @@ -4699,27 +5243,25 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) DrawPosition(FALSE, NULL); return TRUE; case PB_King: - promoChar = 'k'; + promoChar = gameInfo.variant == VariantSuper ? PieceToChar(BlackSilver) : PieceToChar(BlackKing); break; case PB_Queen: - promoChar = 'q'; + promoChar = gameInfo.variant == VariantShogi ? '+' : PieceToChar(BlackQueen); break; case PB_Rook: - promoChar = 'r'; + promoChar = PieceToChar(BlackRook); break; case PB_Bishop: - promoChar = 'b'; + promoChar = PieceToChar(BlackBishop); break; -#ifdef FAIRY case PB_Chancellor: - promoChar = 'c'; + promoChar = PieceToChar(BlackMarshall); break; case PB_Archbishop: - promoChar = 'a'; + promoChar = PieceToChar(BlackAngel); break; -#endif case PB_Knight: - promoChar = 'n'; + promoChar = gameInfo.variant == VariantShogi ? '=' : PieceToChar(BlackKnight); break; default: return FALSE; @@ -4755,7 +5297,8 @@ PromotionPopup(HWND hwnd) VOID ToggleShowThinking() { - ShowThinkingEvent(!appData.showThinking); + appData.showThinking = !appData.showThinking; + ShowThinkingEvent(); } VOID @@ -4764,7 +5307,7 @@ LoadGameDialog(HWND hwnd, char* title) UINT number = 0; FILE *f; char fileTitle[MSG_SIZ]; - f = OpenFileDialog(hwnd, FALSE, "", + f = OpenFileDialog(hwnd, "rb", "", appData.oldSaveStyle ? "gam" : "pgn", GAME_FILT, title, &number, fileTitle, NULL); @@ -4843,6 +5386,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) FILE *f; UINT number; char fileTitle[MSG_SIZ]; + char buf[MSG_SIZ]; static SnapData sd; switch (message) { @@ -4867,6 +5411,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_MBUTTONUP: case WM_RBUTTONUP: case WM_MOUSEMOVE: + case WM_MOUSEWHEEL: MouseEvent(hwnd, message, wParam, lParam); break; @@ -4971,7 +5516,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) Reset(FALSE, TRUE); } number = 1; - f = OpenFileDialog(hwnd, FALSE, "", + f = OpenFileDialog(hwnd, "rb", "", appData.oldSaveStyle ? "pos" : "fen", POSITION_FILT, "Load Position from File", &number, fileTitle, NULL); @@ -4994,7 +5539,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case IDM_SaveGame: defName = DefaultFileName(appData.oldSaveStyle ? "gam" : "pgn"); - f = OpenFileDialog(hwnd, TRUE, defName, + f = OpenFileDialog(hwnd, "a", defName, appData.oldSaveStyle ? "gam" : "pgn", GAME_FILT, "Save Game to File", NULL, fileTitle, NULL); @@ -5005,7 +5550,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case IDM_SavePosition: defName = DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"); - f = OpenFileDialog(hwnd, TRUE, defName, + f = OpenFileDialog(hwnd, "a", defName, appData.oldSaveStyle ? "pos" : "fen", POSITION_FILT, "Save Position to File", NULL, fileTitle, NULL); @@ -5014,6 +5559,17 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } break; + case IDM_SaveDiagram: + defName = "diagram"; + f = OpenFileDialog(hwnd, "wb", defName, + "bmp", + DIAGRAM_FILT, + "Save Diagram to File", NULL, fileTitle, NULL); + if (f != NULL) { + SaveDiagram(f); + } + break; + case IDM_CopyGame: CopyGameToClipboard(); break; @@ -5145,10 +5701,34 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case IDM_AnalysisMode: if (!first.analysisSupport) { - char buf[MSG_SIZ]; sprintf(buf, "%s does not support analysis", first.tidy); DisplayError(buf, 0); } else { + /* [DM] icsEngineAnlyze [HGM] Why is this front-end??? */ + if (appData.icsActive) { + if (gameMode != IcsObserving) { + sprintf(buf, "You are not observing a game"); + DisplayError(buf, 0); + /* secure check */ + if (appData.icsEngineAnalyze) { + if (appData.debugMode) + fprintf(debugFP, "Found unexpected active ICS engine analyze \n"); + ExitAnalyzeMode(); + ModeHighlight(); + break; + } + break; + } else { + /* if enable, user want disable icsEngineAnalyze */ + if (appData.icsEngineAnalyze) { + ExitAnalyzeMode(); + ModeHighlight(); + break; + } + appData.icsEngineAnalyze = TRUE; + if (appData.debugMode) fprintf(debugFP, "ICS engine analyze starting...\n"); + } + } if (!appData.showThinking) ToggleShowThinking(); AnalyzeModeEvent(); } @@ -5247,6 +5827,10 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) PopUpMoveDialog('\000'); break; + case IDM_TypeInName: + PopUpNameDialog('\000'); + break; + case IDM_Backward: BackwardEvent(); SetFocus(hwndMain); @@ -5288,6 +5872,11 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) DrawPosition(FALSE, NULL); break; + case IDM_FlipClock: + flipClock = !flipClock; + DisplayBothClocks(); + break; + case IDM_GeneralOptions: GeneralOptionsPopup(hwnd); DrawPosition(TRUE, NULL); @@ -5437,6 +6026,36 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) fromX = fromY = -1; break; + case EP_WhiteFerz: + EditPositionMenuEvent(WhiteFerz, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_WhiteWazir: + EditPositionMenuEvent(WhiteWazir, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_WhiteAlfil: + EditPositionMenuEvent(WhiteAlfil, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_WhiteCannon: + EditPositionMenuEvent(WhiteCannon, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_WhiteCardinal: + EditPositionMenuEvent(WhiteAngel, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_WhiteMarshall: + EditPositionMenuEvent(WhiteMarshall, fromX, fromY); + fromX = fromY = -1; + break; + case EP_WhiteKing: EditPositionMenuEvent(WhiteKing, fromX, fromY); fromX = fromY = -1; @@ -5467,6 +6086,36 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) fromX = fromY = -1; break; + case EP_BlackFerz: + EditPositionMenuEvent(BlackFerz, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_BlackWazir: + EditPositionMenuEvent(BlackWazir, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_BlackAlfil: + EditPositionMenuEvent(BlackAlfil, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_BlackCannon: + EditPositionMenuEvent(BlackCannon, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_BlackCardinal: + EditPositionMenuEvent(BlackAngel, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_BlackMarshall: + EditPositionMenuEvent(BlackMarshall, fromX, fromY); + fromX = fromY = -1; + break; + case EP_BlackKing: EditPositionMenuEvent(BlackKing, fromX, fromY); fromX = fromY = -1; @@ -5492,6 +6141,16 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) fromX = fromY = -1; break; + case EP_Promote: + EditPositionMenuEvent(PromotePiece, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_Demote: + EditPositionMenuEvent(DemotePiece, fromX, fromY); + fromX = fromY = -1; + break; + case DP_Pawn: DropMenuEvent(WhitePawn, fromX, fromY); fromX = fromY = -1; @@ -5535,8 +6194,8 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) AutoPlayGameLoop(); /* call into back end */ break; case ANALYSIS_TIMER_ID: - if ((gameMode == AnalyzeMode || gameMode == AnalyzeFile) && - appData.periodicUpdates) { + if ((gameMode == AnalyzeMode || gameMode == AnalyzeFile + || appData.icsEngineAnalyze) && appData.periodicUpdates) { AnalysisPeriodicEvent(0); } else { KillTimer(hwnd, analysisTimerEvent); @@ -5575,6 +6234,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* [AS] Snapping */ case WM_ENTERSIZEMOVE: + if(appData.debugMode) { fprintf(debugFP, "size-move\n"); } if (hwnd == hwndMain) { doingSizing = TRUE; lastSizing = 0; @@ -5583,15 +6243,18 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_SIZING: + if(appData.debugMode) { fprintf(debugFP, "sizing\n"); } if (hwnd == hwndMain) { lastSizing = wParam; } break; case WM_MOVING: + if(appData.debugMode) { fprintf(debugFP, "moving\n"); } return OnMoving( &sd, hwnd, wParam, lParam ); case WM_EXITSIZEMOVE: + if(appData.debugMode) { fprintf(debugFP, "exit size-move, size = %d\n", squareSize); } if (hwnd == hwndMain) { RECT client; doingSizing = FALSE; @@ -5599,6 +6262,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) GetClientRect(hwnd, &client); ResizeBoard(client.right, client.bottom, lastSizing); lastSizing = 0; + if(appData.debugMode) { fprintf(debugFP, "square size = %d\n", squareSize); } } return OnExitSizeMove( &sd, hwnd, wParam, lParam ); break; @@ -5846,7 +6510,7 @@ OpenFileHook(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) FILE * -OpenFileDialog(HWND hwnd, BOOL write, char *defName, char *defExt, +OpenFileDialog(HWND hwnd, char *write, char *defName, char *defExt, // [HGM] diag: type of 'write' now string char *nameFilt, char *dlgTitle, UINT *number, char fileTitle[MSG_SIZ], char fileName[MSG_SIZ]) { @@ -5878,7 +6542,7 @@ OpenFileDialog(HWND hwnd, BOOL write, char *defName, char *defExt, openFileName.lpstrInitialDir = NULL; openFileName.lpstrTitle = dlgTitle; openFileName.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY - | (write ? 0 : OFN_FILEMUSTEXIST) + | (write[0] != 'r' ? 0 : OFN_FILEMUSTEXIST) | (number ? OFN_ENABLETEMPLATE | OFN_ENABLEHOOK: 0) | (oldDialog ? 0 : OFN_EXPLORER); openFileName.nFileOffset = 0; @@ -5889,10 +6553,10 @@ OpenFileDialog(HWND hwnd, BOOL write, char *defName, char *defExt, (LPOFNHOOKPROC) OldOpenFileHook : (LPOFNHOOKPROC) OpenFileHook; openFileName.lpTemplateName = (LPSTR)(oldDialog ? 1536 : DLG_IndexNumber); - if (write ? GetSaveFileName(&openFileName) : - GetOpenFileName(&openFileName)) { + if (write[0] != 'r' ? GetSaveFileName(&openFileName) : + GetOpenFileName(&openFileName)) { /* open the file */ - f = fopen(openFileName.lpstrFile, write ? "a" : "rb"); + f = fopen(openFileName.lpstrFile, write); if (f == NULL) { MessageBox(hwnd, "File open failed", NULL, MB_OK|MB_ICONEXCLAMATION); @@ -6526,6 +7190,59 @@ PopUpMoveDialog(char firstchar) /*---------------------------------------------------------------------------*\ * + * Type-in name dialog functions + * +\*---------------------------------------------------------------------------*/ + +LRESULT CALLBACK +TypeInNameDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char move[MSG_SIZ]; + HWND hInput; + + switch (message) { + case WM_INITDIALOG: + move[0] = (char) lParam; + move[1] = NULLCHAR; + CenterWindowEx(hDlg, GetWindow(hDlg, GW_OWNER), 1 ); + hInput = GetDlgItem(hDlg, OPT_Name); + SetWindowText(hInput, move); + SetFocus(hInput); + SendMessage(hInput, EM_SETSEL, (WPARAM)9999, (LPARAM)9999); + return FALSE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + GetDlgItemText(hDlg, OPT_Name, move, sizeof(move)); + appData.userName = strdup(move); + + EndDialog(hDlg, TRUE); + return TRUE; + case IDCANCEL: + EndDialog(hDlg, FALSE); + return TRUE; + default: + break; + } + break; + } + return FALSE; +} + +VOID +PopUpNameDialog(char firstchar) +{ + FARPROC lpProc; + + lpProc = MakeProcInstance((FARPROC)TypeInNameDialog, hInst); + DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_TypeInName), + hwndMain, (DLGPROC)lpProc, (LPARAM)firstchar); + FreeProcInstance(lpProc); +} + +/*---------------------------------------------------------------------------*\ + * * Error dialogs * \*---------------------------------------------------------------------------*/ @@ -6626,6 +7343,8 @@ ErrorDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) } #ifdef GOTHIC +HWND gothicDialog = NULL; + LRESULT CALLBACK GothicDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { @@ -6646,7 +7365,7 @@ GothicDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) and it doesn't work when you resize the dialog. For now, just give it a default position. */ - + gothicDialog = hDlg; SetWindowText(hDlg, errorTitle); hwndText = GetDlgItem(hDlg, OPT_ErrorText); SetDlgItemText(hDlg, OPT_ErrorText, errorMessage); @@ -6669,19 +7388,27 @@ GothicDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) } VOID -GothicPopUp(char *title) +GothicPopUp(char *title, VariantClass variant) { FARPROC lpProc; char *p, *q; BOOLEAN modal = hwndMain == NULL; + static char *lastTitle; strncpy(errorTitle, title, sizeof(errorTitle)); errorTitle[sizeof(errorTitle) - 1] = '\0'; - + + if(lastTitle != title && gothicDialog != NULL) { + DestroyWindow(gothicDialog); + gothicDialog = NULL; + } + if(variant != VariantNormal && gothicDialog == NULL) { + title = lastTitle; lpProc = MakeProcInstance((FARPROC)GothicDialog, hInst); CreateDialog(hInst, MAKEINTRESOURCE(DLG_Error), hwndMain, (DLGPROC)lpProc); FreeProcInstance(lpProc); + } } #endif @@ -7228,6 +7955,26 @@ ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) wp.rcNormalPosition.bottom = consoleY + consoleH; SetWindowPlacement(hDlg, &wp); } +#if 0 + // [HGM] Chessknight's change 2004-07-13 + else { /* Determine Defaults */ + WINDOWPLACEMENT wp; + consoleX = winWidth + 1; + consoleY = boardY; + consoleW = screenWidth - winWidth; + consoleH = winHeight; + EnsureOnScreen(&consoleX, &consoleY); + wp.length = sizeof(WINDOWPLACEMENT); + wp.flags = 0; + wp.showCmd = SW_SHOW; + wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0; + wp.rcNormalPosition.left = consoleX; + wp.rcNormalPosition.right = consoleX + consoleW; + wp.rcNormalPosition.top = consoleY; + wp.rcNormalPosition.bottom = consoleY + consoleH; + SetWindowPlacement(hDlg, &wp); + } +#endif return FALSE; case WM_SETFOCUS: @@ -7438,7 +8185,7 @@ DisplayAClock(HDC hdc, int timeRemaining, int highlight, if (appData.clockMode) { if (tinyLayout) - sprintf(buf, "%c %s %s %s", color[0], TimeString(timeRemaining), flagFell); + sprintf(buf, "%c %s %s", color[0], TimeString(timeRemaining), flagFell); else sprintf(buf, "%s: %s %s", color, TimeString(timeRemaining), flagFell); str = buf; @@ -7753,7 +8500,7 @@ Enables icsEnables[] = { { IDM_MachineWhite, MF_BYCOMMAND|MF_GRAYED }, { IDM_MachineBlack, MF_BYCOMMAND|MF_GRAYED }, { IDM_TwoMachines, MF_BYCOMMAND|MF_GRAYED }, - { IDM_AnalysisMode, MF_BYCOMMAND|MF_GRAYED }, + { IDM_AnalysisMode, MF_BYCOMMAND|MF_ENABLED }, { IDM_AnalyzeFile, MF_BYCOMMAND|MF_GRAYED }, { IDM_TimeControl, MF_BYCOMMAND|MF_GRAYED }, { IDM_MoveNow, MF_BYCOMMAND|MF_GRAYED }, @@ -7948,6 +8695,17 @@ ModeHighlight() } prevChecked = nowChecked; + + /* [DM] icsEngineAnalyze - Do a sceure check too */ + if (appData.icsActive) { + if (appData.icsEngineAnalyze) { + (void) CheckMenuItem(GetMenu(hwndMain), IDM_AnalysisMode, + MF_BYCOMMAND|MF_CHECKED); + } else { + (void) CheckMenuItem(GetMenu(hwndMain), IDM_AnalysisMode, + MF_BYCOMMAND|MF_UNCHECKED); + } + } } VOID @@ -7960,6 +8718,9 @@ SetICSMode() #ifdef ZIPPY if (appData.zippyPlay) { SetMenuEnables(hmenu, zippyEnables); + if (!appData.noChessProgram) /* [DM] icsEngineAnalyze */ + (void) EnableMenuItem(GetMenu(hwndMain), IDM_AnalysisMode, + MF_BYCOMMAND|MF_ENABLED); } #endif } @@ -8271,6 +9032,7 @@ LRESULT CALLBACK NewGameFRC_Proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM case IDOK: *lpIndexFRC = GetDlgItemInt(hDlg, IDC_NFG_Edit, &index_is_ok, TRUE ); EndDialog( hDlg, 0 ); + shuffleOpenings = TRUE; /* [HGM] shuffle: switch shuffling on for as long as we stay in current variant */ return TRUE; case IDCANCEL: EndDialog( hDlg, 1 ); @@ -8283,7 +9045,7 @@ LRESULT CALLBACK NewGameFRC_Proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM } return TRUE; case IDC_NFG_Random: - sprintf( buf, "%d", myrandom() % 960 ); + sprintf( buf, "%d", myrandom() ); /* [HGM] shuffle: no longer limit to 960 */ SetDlgItemText(hDlg, IDC_NFG_Edit, buf ); return TRUE; } @@ -8643,6 +9405,9 @@ UserName() static char buf[MSG_SIZ]; DWORD bufsiz = MSG_SIZ; + if(appData.userName != NULL && appData.userName[0] != 0) { + return appData.userName; /* [HGM] username: prefer name selected by user over his system login */ + } if (!GetUserName(buf, &bufsiz)) { /*DisplayError("Error getting user name", GetLastError());*/ strcpy(buf, "User"); @@ -8690,11 +9455,13 @@ void DisplayWhiteClock(long timeRemaining, int highlight) { HDC hdc; - hdc = GetDC(hwndMain); char *flag = whiteFlag && gameMode == TwoMachinesPlay ? "(!)" : ""; + if(appData.noGUI) return; + hdc = GetDC(hwndMain); if (!IsIconic(hwndMain)) { - DisplayAClock(hdc, timeRemaining, highlight, &whiteRect, "White", flag); + DisplayAClock(hdc, timeRemaining, highlight, + (logoHeight > 0 ? flipView: flipClock) ? &blackRect : &whiteRect, "White", flag); } if (highlight && iconCurrent == iconBlack) { iconCurrent = iconWhite; @@ -8714,9 +9481,11 @@ DisplayBlackClock(long timeRemaining, int highlight) HDC hdc; char *flag = blackFlag && gameMode == TwoMachinesPlay ? "(!)" : ""; + if(appData.noGUI) return; hdc = GetDC(hwndMain); if (!IsIconic(hwndMain)) { - DisplayAClock(hdc, timeRemaining, highlight, &blackRect, "Black", flag); + DisplayAClock(hdc, timeRemaining, highlight, + (logoHeight > 0 ? flipView: flipClock) ? &whiteRect : &blackRect, "Black", flag); } if (highlight && iconCurrent == iconWhite) { iconCurrent = iconBlack; @@ -8761,7 +9530,7 @@ AutoSaveGame() char fileTitle[MSG_SIZ]; defName = DefaultFileName(appData.oldSaveStyle ? "gam" : "pgn"); - f = OpenFileDialog(hwndMain, TRUE, defName, + f = OpenFileDialog(hwndMain, "a", defName, appData.oldSaveStyle ? "gam" : "pgn", GAME_FILT, "Save Game to File", NULL, fileTitle, NULL); @@ -8807,6 +9576,23 @@ CancelDelayedEvent() } } +DWORD GetWin32Priority(int nice) +{ // [HGM] nice: translate Unix nice() value to indows priority class. (Code stolen from Polyglot 1.4w11) +/* +REALTIME_PRIORITY_CLASS 0x00000100 +HIGH_PRIORITY_CLASS 0x00000080 +ABOVE_NORMAL_PRIORITY_CLASS 0x00008000 +NORMAL_PRIORITY_CLASS 0x00000020 +BELOW_NORMAL_PRIORITY_CLASS 0x00004000 +IDLE_PRIORITY_CLASS 0x00000040 +*/ + if (nice < -15) return 0x00000080; + if (nice < 0) return 0x00008000; + if (nice == 0) return 0x00000020; + if (nice < 15) return 0x00004000; + return 0x00000040; +} + /* Start a child process running the given program. The process's standard output can be read from "from", and its standard input can be written to "to". @@ -8922,6 +9708,11 @@ StartChildProcess(char *cmdLine, char *dir, ProcRef *pr) return err; } + if (appData.niceEngines){ // [HGM] nice: adjust engine proc priority + if(appData.debugMode) fprintf(debugFP, "nice engine proc to %d\n", appData.niceEngines); + SetPriorityClass(piProcInfo.hProcess, GetWin32Priority(appData.niceEngines)); + } + /* Close the handles we don't need in the parent */ CloseHandle(piProcInfo.hThread); CloseHandle(hChildStdinRd); @@ -8952,7 +9743,7 @@ StartChildProcess(char *cmdLine, char *dir, ProcRef *pr) void DestroyChildProcess(ProcRef pr, int/*boolean*/ signal) { - ChildProc *cp; + ChildProc *cp; int result; cp = (ChildProc *) pr; if (cp == NULL) return; @@ -8969,22 +9760,23 @@ 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 == 9 ) { + result = TerminateProcess( cp->hProcess, 0 ); + if ( appData.debugMode) { - fprintf( debugFP, "Terminating process %u\n", cp->pid ); + fprintf( debugFP, "Terminating process %u, result=%d\n", cp->pid, result ); } - - TerminateProcess( cp->hProcess, 0 ); } else if( signal == 10 ) { DWORD dw = WaitForSingleObject( cp->hProcess, 3*1000 ); // Wait 3 seconds at most if( dw != WAIT_OBJECT_0 ) { + result = TerminateProcess( cp->hProcess, 0 ); + if ( appData.debugMode) { - fprintf( debugFP, "Process %u still alive after timeout, killing...\n", cp->pid ); + fprintf( debugFP, "Process %u still alive after timeout, killing... result=%d\n", cp->pid, result ); } - TerminateProcess( cp->hProcess, 0 ); } } @@ -9605,6 +10397,11 @@ AnalysisDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) case WM_COMMAND: /* message: received a command */ switch (LOWORD(wParam)) { case IDCANCEL: + if (appData.icsActive && appData.icsEngineAnalyze) { /* [DM] icsEngineAnalyze */ + ExitAnalyzeMode(); + ModeHighlight(); + return TRUE; + } EditGameEvent(); return TRUE; default: