X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=winboard%2Fwinboard.c;h=08cafb995bd779a9e2f78e4becf2f3e7fc06f89d;hb=47b84d7023fd7405ec1cec9b14f49ac8be13f891;hp=0d33b09eeff05cabee9645ee6320e33d07441a3f;hpb=266def07442d78b0841cd716422ff9a3774fdfaa;p=xboard.git diff --git a/winboard/winboard.c b/winboard/winboard.c index 0d33b09..08cafb9 100644 --- a/winboard/winboard.c +++ b/winboard/winboard.c @@ -5,7 +5,7 @@ * Massachusetts. * * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006, - * 2007, 2008, 2009 Free Software Foundation, Inc. + * 2007, 2008, 2009, 2010 Free Software Foundation, Inc. * * Enhancements Copyright 2005 Alessandro Scotti * @@ -105,10 +105,9 @@ void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber); VOID NewVariantPopup(HWND hwnd); int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY, /*char*/int promoChar)); -void AnimateAtomicCapture(int fromX, int fromY, int toX, int toY, int nFrames); void DisplayMove P((int moveNumber)); Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen)); -void ChatPopUp P(()); +void ChatPopUp P((char *s)); typedef struct { ChessSquare piece; POINT pos; /* window coordinates of current pos */ @@ -134,6 +133,8 @@ typedef struct { static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} }; static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} }; +static HighlightInfo partnerHighlightInfo = { {{-1, -1}, {-1, -1}} }; +static HighlightInfo oldPartnerHighlight = { {{-1, -1}, {-1, -1}} }; typedef struct { // [HGM] atomic int fromX, fromY, toX, toY, radius; @@ -159,7 +160,7 @@ BoardSize boardSize; Boolean chessProgram; //static int boardX, boardY; int minX, minY; // [HGM] placement: volatile limits on upper-left corner -static int squareSize, lineGap, minorSize; +int squareSize, lineGap, minorSize; static int winW, winH; static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo static int logoHeight = 0; @@ -185,12 +186,14 @@ COLORREF lightSquareColor, darkSquareColor, whitePieceColor, HPALETTE hPal; ColorClass currentColorClass; +static HWND savedHwnd; HWND hCommPort = NULL; /* currently open comm port */ static HWND hwndPause; /* pause button */ static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */ static HBRUSH lightSquareBrush, darkSquareBrush, blackSquareBrush, /* [HGM] for band between board and holdings */ explodeBrush, /* [HGM] atomic */ + markerBrush, /* [HGM] markers */ whitePieceBrush, blackPieceBrush, iconBkgndBrush /*, outlineBrush*/; static POINT gridEndpoints[(BOARD_RANKS + BOARD_FILES + 2) * 2]; static DWORD gridVertexCounts[BOARD_RANKS + BOARD_FILES + 2]; @@ -222,6 +225,253 @@ static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_RANKS][BOA #endif #endif +#define INTERNATIONAL + +#ifdef INTERNATIONAL +# define _(s) T_(s) +# define N_(s) s +#else +# define _(s) s +# define N_(s) s +# define T_(s) s +# define Translate(x, y) +# define LoadLanguageFile(s) +#endif + +#ifdef INTERNATIONAL + +Boolean barbaric; // flag indicating if translation is needed + +// list of item numbers used in each dialog (used to alter language at run time) + +#define ABOUTBOX -1 /* not sure why these are needed */ +#define ABOUTBOX2 -1 + +int dialogItems[][40] = { +{ ABOUTBOX, IDOK, 400 }, +{ 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, 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 }, +{ DLG_CommPort, IDOK, IDCANCEL, IDC_Port, IDC_Rate, IDC_Bits, IDC_Parity, + IDC_Stop, IDC_Flow, OPT_SerialHelp }, +{ DLG_EditComment, IDOK, OPT_CancelComment, OPT_ClearComment, OPT_EditComment }, +{ DLG_PromotionKing, PB_Chancellor, PB_Archbishop, PB_Queen, PB_Rook, + PB_Bishop, PB_Knight, PB_King, IDCANCEL, IDC_Yes, IDC_No, IDC_Centaur }, +{ ABOUTBOX2, IDC_ChessBoard }, +{ DLG_GameList, OPT_GameListLoad, OPT_GameListPrev, OPT_GameListNext, + OPT_GameListClose, IDC_GameListDoFilter }, +{ DLG_EditTags, IDOK, OPT_TagsCancel, OPT_EditTags }, +{ DLG_Error, IDOK }, +{ DLG_Colorize, IDOK, IDCANCEL, OPT_ChooseColor, OPT_Bold, OPT_Italic, + OPT_Underline, OPT_Strikeout, OPT_Sample }, +{ DLG_Question, IDOK, IDCANCEL, OPT_QuestionText }, +{ DLG_Startup, IDC_Welcome, OPT_ChessEngine, OPT_ChessServer, OPT_View, + IDC_SPECIFY_ENG_STATIC, IDC_SPECIFY_SERVER_STATIC, OPT_AnyAdditional, + IDOK, IDCANCEL, IDM_HELPCONTENTS }, +{ DLG_IndexNumber, IDC_Index }, +{ DLG_TypeInMove, IDOK, IDCANCEL }, +{ DLG_TypeInName, IDOK, IDCANCEL }, +{ DLG_Sound, IDC_Event, OPT_NoSound, OPT_DefaultBeep, OPT_BuiltInSound, + OPT_WavFile, OPT_BrowseSound, OPT_DefaultSounds, IDOK, IDCANCEL, OPT_PlaySound }, +{ DLG_GeneralOptions, IDOK, IDCANCEL, OPT_AlwaysOnTop, OPT_HighlightLastMove, + OPT_AlwaysQueen, OPT_PeriodicUpdates, OPT_AnimateDragging, OPT_PonderNextMove, + OPT_AnimateMoving, OPT_PopupExitMessage, OPT_AutoFlag, OPT_PopupMoveErrors, + OPT_AutoFlipView, OPT_ShowButtonBar, OPT_AutoRaiseBoard, OPT_ShowCoordinates, + OPT_Blindfold, OPT_ShowThinking, OPT_HighlightDragging, OPT_TestLegality, + OPT_SaveExtPGN, OPT_HideThinkFromHuman, OPT_ExtraInfoInMoveHistory, + OPT_HighlightMoveArrow, OPT_AutoLogo }, +{ DLG_IcsOptions, IDOK, IDCANCEL, OPT_AutoComment, OPT_AutoKibitz, OPT_AutoObserve, + OPT_GetMoveList, OPT_LocalLineEditing, OPT_QuietPlay, OPT_SeekGraph, OPT_AutoRefresh, + OPT_BgObserve, OPT_DualBoard, OPT_Premove, OPT_PremoveWhite, OPT_PremoveBlack, + OPT_SmartMove, OPT_IcsAlarm, IDC_Sec, OPT_ChooseShoutColor, OPT_ChooseSShoutColor, + OPT_ChooseChannel1Color, OPT_ChooseChannelColor, OPT_ChooseKibitzColor, + OPT_ChooseTellColor, OPT_ChooseChallengeColor, OPT_ChooseRequestColor, + OPT_ChooseSeekColor, OPT_ChooseNormalColor, OPT_ChooseBackgroundColor, + OPT_DefaultColors, OPT_DontColorize, IDC_Boxes, GPB_Colors, GPB_Premove, + GPB_General, GPB_Alarm }, +{ DLG_BoardOptions, IDOK, IDCANCEL, OPT_SizeTiny, OPT_SizeTeeny, OPT_SizeDinky, + OPT_SizePetite, OPT_SizeSlim, OPT_SizeSmall, OPT_SizeMediocre, OPT_SizeMiddling, + OPT_SizeAverage, OPT_SizeModerate, OPT_SizeMedium, OPT_SizeBulky, OPT_SizeLarge, + OPT_SizeBig, OPT_SizeHuge, OPT_SizeGiant, OPT_SizeColossal, OPT_SizeTitanic, + OPT_ChooseLightSquareColor, OPT_ChooseDarkSquareColor, OPT_ChooseWhitePieceColor, + OPT_ChooseBlackPieceColor, OPT_ChooseHighlightSquareColor, OPT_ChoosePremoveHighlightColor, + OPT_Monochrome, OPT_AllWhite, OPT_UpsideDown, OPT_DefaultBoardColors, GPB_Colors, + IDC_Light, IDC_Dark, IDC_White, IDC_Black, IDC_High, IDC_PreHigh, GPB_Size }, +{ DLG_NewVariant, IDOK, IDCANCEL, OPT_VariantNormal, OPT_VariantFRC, OPT_VariantWildcastle, + OPT_VariantNocastle, OPT_VariantLosers, OPT_VariantGiveaway, OPT_VariantSuicide, + OPT_Variant3Check, OPT_VariantTwoKings, OPT_VariantAtomic, OPT_VariantCrazyhouse, + OPT_VariantBughouse, OPT_VariantTwilight, OPT_VariantShogi, OPT_VariantSuper, + OPT_VariantKnightmate, OPT_VariantBerolina, OPT_VariantCylinder, OPT_VariantFairy, + OPT_VariantMakruk, OPT_VariantGothic, OPT_VariantCapablanca, OPT_VariantJanus, + OPT_VariantCRC, OPT_VariantFalcon, OPT_VariantCourier, OPT_VariantGreat, OPT_VariantSChess, + OPT_VariantShatranj, OPT_VariantXiangqi, GPB_Variant, GPB_Board, IDC_Height, + IDC_Width, IDC_Hand, IDC_Pieces, IDC_Def }, +{ DLG_Fonts, IDOK, IDCANCEL, OPT_ChooseClockFont, OPT_ChooseMessageFont, + OPT_ChooseCoordFont, OPT_ChooseTagFont, OPT_ChooseCommentsFont, OPT_ChooseConsoleFont, OPT_ChooseMoveHistoryFont, OPT_DefaultFonts, + OPT_ClockFont, OPT_MessageFont, OPT_CoordFont, OPT_EditTagsFont, + OPT_CommentsFont, OPT_MessageFont5, GPB_Current, GPB_All, OPT_MessageFont6 }, +{ DLG_NewGameFRC, IDC_NFG_Label, IDC_NFG_Random, IDOK, IDCANCEL }, +{ DLG_GameListOptions, IDC_GLT, IDC_GLT_Up, IDC_GLT_Down, IDC_GLT_Restore, + IDC_GLT_Default, IDOK, IDCANCEL, IDC_GLT_RestoreTo }, +{ DLG_MoveHistory }, +{ DLG_EvalGraph }, +{ DLG_EngineOutput, IDC_EngineLabel1, IDC_Engine1_NPS, IDC_EngineLabel2, IDC_Engine2_NPS }, +{ DLG_Chat, IDC_Partner, IDC_Clear, IDC_Send, }, +{ DLG_EnginePlayOptions, IDC_EpPonder, IDC_EpShowThinking, IDC_EpHideThinkingHuman, + IDC_EpPeriodicUpdates, GPB_Adjudications, IDC_Draw, IDC_Moves, IDC_Threshold, + IDC_Centi, IDC_TestClaims, IDC_DetectMates, IDC_MaterialDraws, IDC_TrivialDraws, + GPB_Apply, IDC_Rule, IDC_Repeats, IDC_ScoreAbs1, IDC_ScoreAbs2, IDOK, IDCANCEL }, +{ DLG_OptionsUCI, IDC_PolyDir, IDC_BrowseForPolyglotDir, IDC_Hash, IDC_Path, + IDC_BrowseForEGTB, IDC_Cache, IDC_UseBook, IDC_BrowseForBook, IDC_CPU, IDC_OwnBook1, + IDC_OwnBook2, IDC_Depth, IDC_Variation, IDC_DefGames, IDOK, IDCANCEL }, +{ 0 } +}; + +static char languageBuf[50000], *foreign[1000], *english[1000], *languageFile[MSG_SIZ]; +static int lastChecked; +static char oldLanguage[MSG_SIZ], *menuText[10][30]; +extern int tinyLayout; +extern char * menuBarText[][10]; + +void +LoadLanguageFile(char *name) +{ //load the file with translations, and make a list of the strings to be translated, and their translations + FILE *f; + int i=0, j=0, n=0, k; + char buf[MSG_SIZ]; + + if(!name || name[0] == NULLCHAR) return; + snprintf(buf, MSG_SIZ, "%s%s", name, strchr(name, '.') ? "" : ".lng"); // auto-append lng extension + if(!strcmp(buf, oldLanguage)) { barbaric = 1; return; } // this language already loaded; just switch on + if((f = fopen(buf, "r")) == NULL) return; + while((k = fgetc(f)) != EOF) { + if(i >= sizeof(languageBuf)) { DisplayError("Language file too big", 0); return; } + languageBuf[i] = k; + if(k == '\n') { + if(languageBuf[n] == '"' && languageBuf[i-1] == '"') { + char *p; + if(p = strstr(languageBuf + n + 1, "\" === \"")) { + if(p > languageBuf+n+2 && p+8 < languageBuf+i) { + if(j >= sizeof(english)) { DisplayError("Too many translated strings", 0); return; } + english[j] = languageBuf + n + 1; *p = 0; + foreign[j++] = p + 7; languageBuf[i-1] = 0; +//if(appData.debugMode) fprintf(debugFP, "translation: replace '%s' by '%s'\n", english[j-1], foreign[j-1]); + } + } + } + n = i + 1; + } else if(i > 0 && languageBuf[i-1] == '\\') { + switch(k) { + case 'n': k = '\n'; break; + case 'r': k = '\r'; break; + case 't': k = '\t'; break; + } + languageBuf[--i] = k; + } + i++; + } + fclose(f); + barbaric = (j != 0); + safeStrCpy(oldLanguage, buf, sizeof(oldLanguage)/sizeof(oldLanguage[0]) ); +} + +char * +T_(char *s) +{ // return the translation of the given string + // efficiency can be improved a lot... + int i=0; +//if(appData.debugMode) fprintf(debugFP, "T_(%s)\n", s); + if(!barbaric) return s; + if(!s) return ""; // sanity + while(english[i]) { + if(!strcmp(s, english[i])) return foreign[i]; + i++; + } + return s; +} + +void +Translate(HWND hDlg, int dialogID) +{ // translate all text items in the given dialog + int i=0, j, k; + char buf[MSG_SIZ], *s; +//if(appData.debugMode) fprintf(debugFP, "Translate(%d)\n", dialogID); + if(!barbaric) return; + while(dialogItems[i][0] && dialogItems[i][0] != dialogID) i++; // find the dialog description + if(dialogItems[i][0] != dialogID) return; // unknown dialog, should not happen + GetWindowText( hDlg, buf, MSG_SIZ ); + s = T_(buf); +//if(appData.debugMode) fprintf(debugFP, "WindowText '%s' -> '%s'\n", buf, s); + if(strcmp(buf, s)) SetWindowText(hDlg, s); // replace by translated string (if different) + for(j=1; k=dialogItems[i][j]; j++) { // translate all listed dialog items + GetDlgItemText(hDlg, k, buf, MSG_SIZ); + if(strlen(buf) == 0) continue; + s = T_(buf); + if(strcmp(buf, s)) SetDlgItemText(hDlg, k, s); // replace by translated string (if different) + } +} + +void +TranslateMenus(int addLanguage) +{ + int i, j; + WIN32_FIND_DATA fileData; + HANDLE hFind; +#define IDM_English 1895 + if(1) { + HMENU mainMenu = GetMenu(hwndMain); + for (i=GetMenuItemCount(mainMenu)-1; i>=0; i--) { + HMENU subMenu = GetSubMenu(mainMenu, i); + ModifyMenu(mainMenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP|EnableMenuItem(mainMenu, i, MF_BYPOSITION), + (UINT) subMenu, T_(menuBarText[tinyLayout][i])); + for(j=GetMenuItemCount(subMenu)-1; j>=0; j--){ + char buf[MSG_SIZ]; + UINT k = GetMenuItemID(subMenu, j); + if(menuText[i][j]) + safeStrCpy(buf, menuText[i][j], sizeof(buf)/sizeof(buf[0]) ); else { + GetMenuString(subMenu, j, buf, MSG_SIZ, MF_BYPOSITION); + menuText[i][j] = strdup(buf); // remember original on first change + } + if(buf[0] == NULLCHAR) continue; +//fprintf(debugFP, "menu(%d,%d) = %s (%08x, %08x) %d\n", i, j, buf, mainMenu, subMenu, k); + ModifyMenu(subMenu, j, MF_STRING|MF_BYPOSITION + |CheckMenuItem(subMenu, j, MF_BYPOSITION) + |EnableMenuItem(subMenu, j, MF_BYPOSITION), k, T_(buf)); + } + } + DrawMenuBar(hwndMain); + } + + if(!addLanguage) return; + if((hFind = FindFirstFile("*.LNG", &fileData)) != INVALID_HANDLE_VALUE) { + HMENU mainMenu = GetMenu(hwndMain); + HMENU subMenu = GetSubMenu(mainMenu, GetMenuItemCount(mainMenu)-1); + AppendMenu(subMenu, MF_SEPARATOR, (UINT_PTR) 0, NULL); + AppendMenu(subMenu, MF_ENABLED|MF_STRING|(barbaric?MF_UNCHECKED:MF_CHECKED), (UINT_PTR) IDM_English, (LPCTSTR) "English"); + i = 0; lastChecked = IDM_English; + do { + char *p, *q = fileData.cFileName; + int checkFlag = MF_UNCHECKED; + languageFile[i] = strdup(q); + if(barbaric && !strcmp(oldLanguage, q)) { + checkFlag = MF_CHECKED; + lastChecked = IDM_English + i + 1; + CheckMenuItem(mainMenu, IDM_English, MF_BYCOMMAND|MF_UNCHECKED); + } + *q = ToUpper(*q); while(*++q) *q = ToLower(*q); + p = strstr(fileData.cFileName, ".lng"); + if(p) *p = 0; + AppendMenu(subMenu, MF_ENABLED|MF_STRING|checkFlag, (UINT_PTR) IDM_English + ++i, (LPCTSTR) fileData.cFileName); + } while(FindNextFile(hFind, &fileData)); + FindClose(hFind); + } +} + +#endif + typedef struct { char *name; int squareSize; @@ -299,10 +549,10 @@ MyButtonDesc buttonDesc[N_BUTTONS] = }; int tinyLayout = 0, smallLayout = 0; -#define MENU_BAR_ITEMS 7 +#define MENU_BAR_ITEMS 9 char *menuBarText[2][MENU_BAR_ITEMS+1] = { - { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL }, - { "&F", "&M", "&A", "&S", "&O", "&H", NULL }, + { N_("&File"), N_("&Edit"), N_("&View"), N_("&Mode"), N_("&Action"), N_("E&ngine"), N_("&Options"), N_("&Help"), NULL }, + { N_("&F"), N_("&E"), N_("&V"), N_("&M"), N_("&A"), N_("&N"), N_("&O"), N_("&H"), NULL }, }; @@ -310,17 +560,17 @@ MySound sounds[(int)NSoundClasses]; MyTextAttribs textAttribs[(int)NColorClasses]; MyColorizeAttribs colorizeAttribs[] = { - { (COLORREF)0, 0, "Shout Text" }, - { (COLORREF)0, 0, "SShout/CShout" }, - { (COLORREF)0, 0, "Channel 1 Text" }, - { (COLORREF)0, 0, "Channel Text" }, - { (COLORREF)0, 0, "Kibitz Text" }, - { (COLORREF)0, 0, "Tell Text" }, - { (COLORREF)0, 0, "Challenge Text" }, - { (COLORREF)0, 0, "Request Text" }, - { (COLORREF)0, 0, "Seek Text" }, - { (COLORREF)0, 0, "Normal Text" }, - { (COLORREF)0, 0, "None" } + { (COLORREF)0, 0, N_("Shout Text") }, + { (COLORREF)0, 0, N_("SShout/CShout") }, + { (COLORREF)0, 0, N_("Channel 1 Text") }, + { (COLORREF)0, 0, N_("Channel Text") }, + { (COLORREF)0, 0, N_("Kibitz Text") }, + { (COLORREF)0, 0, N_("Tell Text") }, + { (COLORREF)0, 0, N_("Challenge Text") }, + { (COLORREF)0, 0, N_("Request Text") }, + { (COLORREF)0, 0, N_("Seek Text") }, + { (COLORREF)0, 0, N_("Normal Text") }, + { (COLORREF)0, 0, N_("None") } }; @@ -631,9 +881,9 @@ SetUserLogo() if(appData.autoLogo) { curName = UserName(); if(strcmp(curName, oldUserName)) { - sprintf(oldUserName, "logos\\%s.bmp", curName); + snprintf(oldUserName, MSG_SIZ, "logos\\%s.bmp", curName); userLogo = LoadImage( 0, oldUserName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); - strcpy(oldUserName, curName); + safeStrCpy(oldUserName, curName, sizeof(oldUserName)/sizeof(oldUserName[0]) ); } } } @@ -725,6 +975,8 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) setbuf(debugFP, NULL); } + LoadLanguageFile(appData.language); + InitBackEnd1(); // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1() @@ -752,7 +1004,7 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) } else if(appData.autoLogo) { if(appData.firstDirectory && appData.firstDirectory[0]) { char buf[MSG_SIZ]; - sprintf(buf, "%s/logo.bmp", appData.firstDirectory); + snprintf(buf, MSG_SIZ, "%s/logo.bmp", appData.firstDirectory); first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); } } @@ -766,11 +1018,11 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) } else if(appData.autoLogo) { char buf[MSG_SIZ]; if(appData.icsActive) { // [HGM] logo: in ICS mode second can be used for ICS - sprintf(buf, "logos\\%s.bmp", appData.icsHost); + snprintf(buf, MSG_SIZ, "logos\\%s.bmp", appData.icsHost); second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); } else if(appData.secondDirectory && appData.secondDirectory[0]) { - sprintf(buf, "%s\\logo.bmp", appData.secondDirectory); + snprintf(buf, MSG_SIZ, "%s\\logo.bmp", appData.secondDirectory); second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); } } @@ -796,6 +1048,7 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) } InitDrawingSizes(boardSize, 0); + TranslateMenus(1); InitMenuChecks(); buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS); @@ -835,8 +1088,6 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) EngineOutputPopUp(); } - InitBackEnd2(); - /* Make the window visible; update its client area; and return "success" */ EnsureOnScreen(&wpMain.x, &wpMain.y, minX, minY); wp.length = sizeof(WINDOWPLACEMENT); @@ -849,6 +1100,8 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) wp.rcNormalPosition.bottom = wpMain.y + wpMain.height; SetWindowPlacement(hwndMain, &wp); + InitBackEnd2(); // [HGM] moved until after all windows placed, to save correct position if fatal error on engine start + if(!appData.noGUI) SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); @@ -858,6 +1111,16 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); #endif ShowWindow(hwndConsole, nCmdShow); + if(appData.chatBoxes) { // [HGM] chat: open chat boxes + char buf[MSG_SIZ], *p = buf, *q; + safeStrCpy(buf, appData.chatBoxes, sizeof(buf)/sizeof(buf[0]) ); + do { + q = strchr(p, ';'); + if(q) *q++ = 0; + if(*p) ChatPopUp(p); + } while(p=q); + } + SetActiveWindow(hwndConsole); } if(!appData.noGUI) UpdateWindow(hwnd); else ShowWindow(hwnd, SW_MINIMIZE); if(gameListDialog) SetFocus(gameListDialog); // [HGM] jaws: for if we clicked multi-game game file @@ -910,7 +1173,7 @@ LFfromMFP(LOGFONT* lf, MyFontParams *mfp) lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; lf->lfQuality = DEFAULT_QUALITY; lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE; - strcpy(lf->lfFaceName, mfp->faceName); + safeStrCpy(lf->lfFaceName, mfp->faceName, sizeof(lf->lfFaceName)/sizeof(lf->lfFaceName[0]) ); } void @@ -955,7 +1218,7 @@ ParseFontName(char *name, MyFontParams *mfp) q = strchr(p, ':'); if (q) { if (q - p >= sizeof(mfp->faceName)) - ExitArgError("Font name too long:", name); + ExitArgError(_("Font name too long:"), name); memcpy(mfp->faceName, p, q - p); mfp->faceName[q - p] = NULLCHAR; p = q + 1; @@ -964,12 +1227,12 @@ ParseFontName(char *name, MyFontParams *mfp) while (*p && !isdigit(*p)) { *q++ = *p++; if (q - mfp->faceName >= sizeof(mfp->faceName)) - ExitArgError("Font name too long:", name); + ExitArgError(_("Font name too long:"), name); } while (q > mfp->faceName && q[-1] == ' ') q--; *q = NULLCHAR; } - if (!*p) ExitArgError("Font point size missing:", name); + if (!*p) ExitArgError(_("Font point size missing:"), name); mfp->pointSize = (float) atof(p); mfp->bold = (strchr(p, 'b') != NULL); mfp->italic = (strchr(p, 'i') != NULL); @@ -1026,7 +1289,7 @@ ParseColorName(char *name) &red, &green, &blue); } if (count != 3) { - sprintf(buf, "Can't parse color name %s", name); + snprintf(buf, MSG_SIZ, _("Can't parse color name %s"), name); DisplayError(buf, 0); return RGB(0, 0, 0); } @@ -1075,7 +1338,7 @@ ParseBoardSize(void *addr, char *name) } bs++; } - ExitArgError("Unrecognized board size value", name); + ExitArgError(_("Unrecognized board size value"), name); } void @@ -1209,7 +1472,19 @@ PrintCommPortSettings(FILE *f, char *name) int MySearchPath(char *installDir, char *name, char *fullname) { - char *dummy; + char *dummy, buf[MSG_SIZ], *p = name, *q; + if(name[0]== '%') { + fullname[0] = 0; // [HGM] first expand any environment variables in the given name + while(*p == '%' && (q = strchr(p+1, '%'))) { // [HGM] recognize %*% as environment variable + safeStrCpy(buf, p+1, sizeof(buf)/sizeof(buf[0]) ); + *strchr(buf, '%') = 0; + strcat(fullname, getenv(buf)); + p = q+1; while(*p == '\\') { strcat(fullname, "\\"); p++; } + } + strcat(fullname, p); // after environment variables (if any), take the remainder of the given name + if(appData.debugMode) fprintf(debugFP, "name = '%s', expanded name = '%s'\n", name, fullname); + return (int) strlen(fullname); + } return (int) SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy); } @@ -1231,6 +1506,7 @@ PopUpStartupDialog() { FARPROC lpProc; + LoadLanguageFile(appData.language); lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst); DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc); FreeProcInstance(lpProc); @@ -1785,11 +2061,11 @@ DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix) { char name[128]; - sprintf(name, "%s%d%s", piece, squareSize, suffix); + snprintf(name, sizeof(name)/sizeof(name[0]), "%s%d%s", piece, squareSize, suffix); if (gameInfo.event && strcmp(gameInfo.event, "Easter Egg Hunt") == 0 && strcmp(name, "k80s") == 0) { - strcpy(name, "tim"); + safeStrCpy(name, "tim", sizeof(name)/sizeof(name[0]) ); } return LoadBitmap(hinst, name); } @@ -1806,7 +2082,7 @@ InsertInPalette(COLORREF color) LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]); if (pLogPal->palNumEntries++ >= PALETTESIZE) { - DisplayFatalError("Too many colors", 0, 1); + DisplayFatalError(_("Too many colors"), 0, 1); pLogPal->palNumEntries--; return; } @@ -1853,6 +2129,7 @@ InitDrawingColors() blackPieceBrush = CreateSolidBrush(blackPieceColor); iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND)); explodeBrush = CreateSolidBrush(highlightSquareColor); // [HGM] atomic + markerBrush = CreateSolidBrush(premoveHighlightColor); // [HGM] markers /* [AS] Force rendering of the font-based pieces */ if( fontBitmapSquareSize > 0 ) { fontBitmapSquareSize = 0; @@ -1894,6 +2171,7 @@ ResizeBoard(int newSizeX, int newSizeY, int flags) } +extern Boolean twoBoards, partnerUp; // [HGM] dual VOID InitDrawingSizes(BoardSize boardSize, int flags) @@ -1946,7 +2224,7 @@ InitDrawingSizes(BoardSize boardSize, int flags) for (i=0; menuBarText[tinyLayout][i]; i++) { ModifyMenu(hmenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP, - (UINT)GetSubMenu(hmenu, i), menuBarText[tinyLayout][i]); + (UINT)GetSubMenu(hmenu, i), T_(menuBarText[tinyLayout][i])); } DrawMenuBar(hwndMain); } @@ -1957,14 +2235,14 @@ InitDrawingSizes(BoardSize boardSize, int flags) /* Get text area sizes */ hdc = GetDC(hwndMain); if (appData.clockMode) { - sprintf(buf, "White: %s", TimeString(23*60*60*1000L)); + snprintf(buf, MSG_SIZ, _("White: %s"), TimeString(23*60*60*1000L)); } else { - sprintf(buf, "White"); + snprintf(buf, MSG_SIZ, _("White")); } oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf); GetTextExtentPoint(hdc, buf, strlen(buf), &clockSize); SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf); - str = "We only care about the height here"; + str = _("We only care about the height here"); GetTextExtentPoint(hdc, str, strlen(str), &messageSize); SelectObject(hdc, oldFont); ReleaseDC(hwndMain, hdc); @@ -2003,6 +2281,8 @@ InitDrawingSizes(BoardSize boardSize, int flags) blackRect.right = blackRect.left + boardWidth/2 - 1; blackRect.top = whiteRect.top; blackRect.bottom = whiteRect.bottom; + + logoHeight = 0; // [HGM] logo: suppress logo after change to tiny layout! } messageRect.left = OUTER_MARGIN + MESSAGE_LINE_LEFTMARGIN; @@ -2027,6 +2307,7 @@ InitDrawingSizes(BoardSize boardSize, int flags) winW = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN; winH = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYCAPTION) + boardRect.bottom + OUTER_MARGIN; + winW *= 1 + twoBoards; if(suppressVisibleEffects) return; // [HGM] when called for filling sizeInfo only wpMain.width = winW; // [HGM] placement: set through temporary which can used by initial sizing choice wpMain.height = winH; // without disturbing window attachments @@ -2178,7 +2459,7 @@ InitDrawingSizes(BoardSize boardSize, int flags) pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "w"); pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w"); pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w"); - if( !strcmp(appData.variant, "shogi") && (squareSize==72 || squareSize==49)) { + if( gameInfo.variant == VariantShogi && squareSize <= 72 && squareSize >= 33) { // in Shogi, Hijack the unused Queen for Lance pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "s"); pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "o"); @@ -2205,14 +2486,24 @@ InitDrawingSizes(BoardSize boardSize, int flags) 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 == VariantSChess) { + pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "v", squareSize, "s"); + pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "v", squareSize, "o"); + pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "v", squareSize, "w"); + } else { + 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 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) { + pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "e", squareSize, "s"); + pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "e", squareSize, "o"); + pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "e", squareSize, "w"); } else { // WinBoard standard pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s"); pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o"); @@ -2473,23 +2764,14 @@ DrawHighlightOnDC(HDC hdc, BOOLEAN on, int x, int y, int pen) } VOID -DrawHighlightsOnDC(HDC hdc) +DrawHighlightsOnDC(HDC hdc, HighlightInfo *h, int pen) { int i; for (i=0; i<2; i++) { - if (highlightInfo.sq[i].x >= 0 && highlightInfo.sq[i].y >= 0) + if (h->sq[i].x >= 0 && h->sq[i].y >= 0) DrawHighlightOnDC(hdc, TRUE, - highlightInfo.sq[i].x, highlightInfo.sq[i].y, - HIGHLIGHT_PEN); - } - for (i=0; i<2; i++) { - if (premoveHighlightInfo.sq[i].x >= 0 && - premoveHighlightInfo.sq[i].y >= 0) { - DrawHighlightOnDC(hdc, TRUE, - premoveHighlightInfo.sq[i].x, - premoveHighlightInfo.sq[i].y, - PREMOVE_PEN); - } + h->sq[i].x, h->sq[i].y, + pen); } } @@ -2506,7 +2788,7 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, if (appData.blindfold) return; /* [AS] Use font-based pieces if needed */ - if( fontBitmapSquareSize >= 0 && squareSize > 32 ) { + if( fontBitmapSquareSize >= 0 && (squareSize > 32 || gameInfo.variant >= VariantShogi)) { /* Create piece bitmaps, or do nothing if piece set is up to date */ CreatePiecesFromFont(); @@ -2515,6 +2797,9 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, SelectObject( tmphdc, hPieceMask[ index ] ); + if(appData.upsideDown ? color==flipView : (flipView && gameInfo.variant == VariantShogi)) + StretchBlt(hdc, x+squareSize, y+squareSize, -squareSize, -squareSize, tmphdc, 0, 0, squareSize, squareSize, SRCAND); + else BitBlt( hdc, x, y, squareSize, squareSize, @@ -2524,6 +2809,9 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, SelectObject( tmphdc, hPieceFace[ index ] ); + if(appData.upsideDown ? color==flipView : (flipView && gameInfo.variant == VariantShogi)) + StretchBlt(hdc, x+squareSize, y+squareSize, -squareSize, -squareSize, tmphdc, 0, 0, squareSize, squareSize, SRCPAINT); + else BitBlt( hdc, x, y, squareSize, squareSize, @@ -2633,7 +2921,13 @@ VOID RebuildTextureSquareInfo() if( (col + row) & 1 ) { /* Lite square */ if( lite_w >= squareSize && lite_h >= squareSize ) { + if( lite_w >= squareSize*BOARD_WIDTH ) + backTextureSquareInfo[row][col].x = (2*col+1)*lite_w/(2*BOARD_WIDTH) - squareSize/2; /* [HGM] cut out of center of virtual square */ + else backTextureSquareInfo[row][col].x = col * (lite_w - squareSize) / (BOARD_WIDTH-1); /* [HGM] divide by size-1 in stead of size! */ + if( lite_h >= squareSize*BOARD_HEIGHT ) + backTextureSquareInfo[row][col].y = (2*(BOARD_HEIGHT-row)-1)*lite_h/(2*BOARD_HEIGHT) - squareSize/2; + else backTextureSquareInfo[row][col].y = (BOARD_HEIGHT-1-row) * (lite_h - squareSize) / (BOARD_HEIGHT-1); backTextureSquareInfo[row][col].mode = GetBackTextureMode(liteBackTextureMode); } @@ -2641,7 +2935,13 @@ VOID RebuildTextureSquareInfo() else { /* Dark square */ if( dark_w >= squareSize && dark_h >= squareSize ) { + if( dark_w >= squareSize*BOARD_WIDTH ) + backTextureSquareInfo[row][col].x = (2*col+1) * dark_w / (2*BOARD_WIDTH) - squareSize/2; + else backTextureSquareInfo[row][col].x = col * (dark_w - squareSize) / (BOARD_WIDTH-1); + if( dark_h >= squareSize*BOARD_HEIGHT ) + backTextureSquareInfo[row][col].y = (2*(BOARD_HEIGHT-row)-1) * dark_h / (2*BOARD_HEIGHT) - squareSize/2; + else backTextureSquareInfo[row][col].y = (BOARD_HEIGHT-1-row) * (dark_h - squareSize) / (BOARD_HEIGHT-1); backTextureSquareInfo[row][col].mode = GetBackTextureMode(darkBackTextureMode); } @@ -3080,13 +3380,69 @@ DrawLogoOnDC(HDC hdc, RECT logoRect, HBITMAP logo) DeleteDC(tmphdc); } +static HDC hdcSeek; + +// [HGM] seekgraph +void DrawSeekAxis( int x, int y, int xTo, int yTo ) +{ + POINT stPt; + HPEN hp = SelectObject( hdcSeek, gridPen ); + MoveToEx( hdcSeek, boardRect.left+x, boardRect.top+y, &stPt ); + LineTo( hdcSeek, boardRect.left+xTo, boardRect.top+yTo ); + SelectObject( hdcSeek, hp ); +} + +// front-end wrapper for drawing functions to do rectangles +void DrawSeekBackground( int left, int top, int right, int bottom ) +{ + HPEN hp; + RECT rc; + + if (hdcSeek == NULL) { + hdcSeek = GetDC(hwndMain); + if (!appData.monoMode) { + SelectPalette(hdcSeek, hPal, FALSE); + RealizePalette(hdcSeek); + } + } + hp = SelectObject( hdcSeek, gridPen ); + rc.top = boardRect.top+top; rc.left = boardRect.left+left; + rc.bottom = boardRect.top+bottom; rc.right = boardRect.left+right; + FillRect( hdcSeek, &rc, lightSquareBrush ); + SelectObject( hdcSeek, hp ); +} + +// front-end wrapper for putting text in graph +void DrawSeekText(char *buf, int x, int y) +{ + SIZE stSize; + SetBkMode( hdcSeek, TRANSPARENT ); + GetTextExtentPoint32( hdcSeek, buf, strlen(buf), &stSize ); + TextOut( hdcSeek, boardRect.left+x-3, boardRect.top+y-stSize.cy/2, buf, strlen(buf) ); +} + +void DrawSeekDot(int x, int y, int color) +{ + int square = color & 0x80; + HBRUSH oldBrush = SelectObject(hdcSeek, + color == 0 ? markerBrush : color == 1 ? darkSquareBrush : explodeBrush); + color &= 0x7F; + if(square) + Rectangle(hdcSeek, boardRect.left+x - squareSize/9, boardRect.top+y - squareSize/9, + boardRect.left+x + squareSize/9, boardRect.top+y + squareSize/9); + else + Ellipse(hdcSeek, boardRect.left+x - squareSize/8, boardRect.top+y - squareSize/8, + boardRect.left+x + squareSize/8, boardRect.top+y + squareSize/8); + SelectObject(hdcSeek, oldBrush); +} + VOID HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) { - static Board lastReq, lastDrawn; + static Board lastReq[2], lastDrawn[2]; static HighlightInfo lastDrawnHighlight, lastDrawnPremove; static int lastDrawnFlipView = 0; - static int lastReqValid = 0, lastDrawnValid = 0; + static int lastReqValid[2] = {0, 0}, lastDrawnValid[2] = {0, 0}; int releaseDC, x, y, x2, y2, row, column, num_clips = 0, i; HDC tmphdc; HDC hdcmem; @@ -3095,6 +3451,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) RECT Rect; HRGN clips[MAX_CLIPS]; ChessSquare dragged_piece = EmptySquare; + int nr = twoBoards*partnerUp; /* I'm undecided on this - this function figures out whether a full * repaint is necessary on its own, so there's no real reason to have the @@ -3106,18 +3463,20 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) */ Boolean fullrepaint = repaint; + if(DrawSeekGraph()) return; // [HG} seekgraph: suppress printing board if seek graph up + if( DrawPositionNeedsFullRepaint() ) { fullrepaint = TRUE; } if (board == NULL) { - if (!lastReqValid) { + if (!lastReqValid[nr]) { return; } - board = lastReq; + board = lastReq[nr]; } else { - CopyBoard(lastReq, board); - lastReqValid = 1; + CopyBoard(lastReq[nr], board); + lastReqValid[nr] = 1; } if (doingSizing) { @@ -3156,23 +3515,24 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) if(--board[dragInfo.from.y][dragInfo.from.x-1] == 0 ) board[dragInfo.from.y][dragInfo.from.x] = EmptySquare; } else - board[dragInfo.from.y][dragInfo.from.x] = EmptySquare; + board[dragInfo.from.y][dragInfo.from.x] = gatingPiece; } /* Figure out which squares need updating by comparing the * newest board with the last drawn board and checking if * flipping has changed. */ - if (!fullrepaint && lastDrawnValid && lastDrawnFlipView == flipView) { + if (!fullrepaint && lastDrawnValid[nr] && (nr == 1 || lastDrawnFlipView == flipView)) { for (row = 0; row < BOARD_HEIGHT; row++) { /* [HGM] true size, not 8 */ for (column = 0; column < BOARD_WIDTH; column++) { - if (lastDrawn[row][column] != board[row][column]) { + if (lastDrawn[nr][row][column] != board[row][column]) { SquareToPos(row, column, &x, &y); clips[num_clips++] = CreateRectRgn(x, y, x + squareSize, y + squareSize); } } } + if(nr == 0) { // [HGM] dual: no highlights on second board for (i=0; i<2; i++) { if (lastDrawnHighlight.sq[i].x != highlightInfo.sq[i].x || lastDrawnHighlight.sq[i].y != highlightInfo.sq[i].y) { @@ -3213,6 +3573,30 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) } } } + } else { // nr == 1 + partnerHighlightInfo.sq[0].y = board[EP_STATUS-4]; + partnerHighlightInfo.sq[0].x = board[EP_STATUS-3]; + partnerHighlightInfo.sq[1].y = board[EP_STATUS-2]; + partnerHighlightInfo.sq[1].x = board[EP_STATUS-1]; + for (i=0; i<2; i++) { + if (partnerHighlightInfo.sq[i].x >= 0 && + partnerHighlightInfo.sq[i].y >= 0) { + SquareToPos(partnerHighlightInfo.sq[i].y, + partnerHighlightInfo.sq[i].x, &x, &y); + clips[num_clips++] = + CreateRectRgn(x - lineGap, y - lineGap, + x + squareSize + lineGap, y + squareSize + lineGap); + } + if (oldPartnerHighlight.sq[i].x >= 0 && + oldPartnerHighlight.sq[i].y >= 0) { + SquareToPos(oldPartnerHighlight.sq[i].y, + oldPartnerHighlight.sq[i].x, &x, &y); + clips[num_clips++] = + CreateRectRgn(x - lineGap, y - lineGap, + x + squareSize + lineGap, y + squareSize + lineGap); + } + } + } } else { fullrepaint = TRUE; } @@ -3272,7 +3656,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) explodes. The old and new positions both had an empty square at the destination, but animation has drawn a piece there and we have to remember to erase it. [HGM] moved until after setting lastDrawn */ - lastDrawn[animInfo.to.y][animInfo.to.x] = animInfo.piece; + lastDrawn[0][animInfo.to.y][animInfo.to.x] = animInfo.piece; } } @@ -3293,6 +3677,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) if(explodeInfo.radius) { // [HGM] atomic HBRUSH oldBrush; int x, y, r=(explodeInfo.radius * squareSize)/100; + ChessSquare piece = board[explodeInfo.fromY][explodeInfo.fromX]; board[explodeInfo.fromY][explodeInfo.fromX] = EmptySquare; // suppress display of capturer SquareToPos(explodeInfo.toY, explodeInfo.toX, &x, &y); x += squareSize/2; @@ -3302,16 +3687,37 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) ExtSelectClipRgn(hdcmem, clips[num_clips++], RGN_OR); } DrawGridOnDC(hdcmem); - DrawHighlightsOnDC(hdcmem); + DrawHighlightsOnDC(hdcmem, &highlightInfo, HIGHLIGHT_PEN); + DrawHighlightsOnDC(hdcmem, &premoveHighlightInfo, PREMOVE_PEN); DrawBoardOnDC(hdcmem, board, tmphdc); + board[explodeInfo.fromY][explodeInfo.fromX] = piece; oldBrush = SelectObject(hdcmem, explodeBrush); Ellipse(hdcmem, x-r, y-r, x+r, y+r); SelectObject(hdcmem, oldBrush); } else { DrawGridOnDC(hdcmem); - DrawHighlightsOnDC(hdcmem); + if(nr == 0) { // [HGM] dual: decide which highlights to draw + DrawHighlightsOnDC(hdcmem, &highlightInfo, HIGHLIGHT_PEN); + DrawHighlightsOnDC(hdcmem, &premoveHighlightInfo, PREMOVE_PEN); + } else { + DrawHighlightsOnDC(hdcmem, &partnerHighlightInfo, HIGHLIGHT_PEN); + oldPartnerHighlight = partnerHighlightInfo; + } DrawBoardOnDC(hdcmem, board, tmphdc); } + if(nr == 0) // [HGM] dual: markers only on left board + for (row = 0; row < BOARD_HEIGHT; row++) { + for (column = 0; column < BOARD_WIDTH; column++) { + if (marker[row][column]) { // marker changes only occur with full repaint! + HBRUSH oldBrush = SelectObject(hdcmem, + marker[row][column] == 2 ? markerBrush : explodeBrush); + SquareToPos(row, column, &x, &y); + Ellipse(hdcmem, x + squareSize/4, y + squareSize/4, + x + 3*squareSize/4, y + 3*squareSize/4); + SelectObject(hdcmem, oldBrush); + } + } + } if(logoHeight) { HBITMAP whiteLogo = (HBITMAP) first.programLogo, blackLogo = (HBITMAP) second.programLogo; if(appData.autoLogo) { @@ -3354,7 +3760,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) DrawCoordsOnDC(hdcmem); - CopyBoard(lastDrawn, board); /* [HGM] Moved to here from end of routine, */ + CopyBoard(lastDrawn[nr], board); /* [HGM] Moved to here from end of routine, */ /* to make sure lastDrawn contains what is actually drawn */ /* Put the dragged piece back into place and draw it (out of place!) */ @@ -3391,6 +3797,13 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) /* Set clipping on the target DC */ if (!fullrepaint) { + if(nr == 1) for (x = 0; x < num_clips; x++) { // [HGM] dual: translate clips + RECT rect; + GetRgnBox(clips[x], &rect); + DeleteObject(clips[x]); + clips[x] = CreateRectRgn(rect.left + wpMain.width/2, rect.top, + rect.right + wpMain.width/2, rect.bottom); + } SelectClipRgn(hdc, clips[0]); for (x = 1; x < num_clips; x++) { if (ExtSelectClipRgn(hdc, clips[x], RGN_OR) == ERROR) @@ -3402,7 +3815,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) * This way we avoid any flickering */ oldBitmap = SelectObject(tmphdc, bufferBitmap); - BitBlt(hdc, boardRect.left, boardRect.top, + BitBlt(hdc, boardRect.left + twoBoards*partnerUp*wpMain.width/2, boardRect.top, // [HGM] dual boardRect.right - boardRect.left, boardRect.bottom - boardRect.top, tmphdc, boardRect.left, boardRect.top, SRCCOPY); @@ -3490,7 +3903,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) if (releaseDC) ReleaseDC(hwndMain, hdc); - if (lastDrawnFlipView != flipView) { + if (lastDrawnFlipView != flipView && nr == 0) { if (flipView) CheckMenuItem(GetMenu(hwndMain),IDM_FlipView, MF_BYCOMMAND|MF_CHECKED); else @@ -3501,7 +3914,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) lastDrawnHighlight = highlightInfo; lastDrawnPremove = premoveHighlightInfo; lastDrawnFlipView = flipView; - lastDrawnValid = 1; + lastDrawnValid[nr] = 1; } /* [HGM] diag: Save the current board display to the given open file and close the file */ @@ -3542,6 +3955,11 @@ PaintProc(HWND hwnd) RealizePalette(hdc); } HDCDrawPosition(hdc, 1, NULL); + if(twoBoards) { // [HGM] dual: also redraw other board in other orientation + flipView = !flipView; partnerUp = !partnerUp; + HDCDrawPosition(hdc, 1, NULL); + flipView = !flipView; partnerUp = !partnerUp; + } oldFont = SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf); ExtTextOut(hdc, messageRect.left, messageRect.top, @@ -3586,11 +4004,11 @@ typedef struct { } DropEnable; DropEnable dropEnables[] = { - { 'P', DP_Pawn, "Pawn" }, - { 'N', DP_Knight, "Knight" }, - { 'B', DP_Bishop, "Bishop" }, - { 'R', DP_Rook, "Rook" }, - { 'Q', DP_Queen, "Queen" }, + { 'P', DP_Pawn, N_("Pawn") }, + { 'N', DP_Knight, N_("Knight") }, + { 'B', DP_Bishop, N_("Bishop") }, + { 'R', DP_Rook, N_("Rook") }, + { 'Q', DP_Queen, N_("Queen") }, }; VOID @@ -3606,7 +4024,7 @@ SetupDropMenu(HMENU hmenu) dropEnables[i].piece); count = 0; while (p && *p++ == dropEnables[i].piece) count++; - sprintf(item, "%s %d", dropEnables[i].name, count); + snprintf(item, MSG_SIZ, "%s %d", T_(dropEnables[i].name), count); enable = count > 0 || !appData.testLegality /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse && !appData.icsActive); @@ -3638,7 +4056,7 @@ void DragPieceEnd(int x, int y) VOID MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { - int x, y; + int x, y, menuNr; POINT pt; static int recursive = 0; HMENU hmenu; @@ -3667,25 +4085,27 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) x = BOARD_WIDTH - 1 - x; } + shiftKey = GetKeyState(VK_SHIFT) < 0; // [HGM] remember last shift status + switch (message) { case WM_LBUTTONDOWN: if (PtInRect((LPRECT) &whiteRect, pt)) { if (gameMode == EditPosition) { SetWhiteToPlayEvent(); + } else if (gameMode == EditGame || GetKeyState(VK_SHIFT) < 0) { + AdjustClock(flipClock, -1); } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) { CallFlagEvent(); - } else if (gameMode == EditGame) { - AdjustClock(flipClock, -1); } } else if (PtInRect((LPRECT) &blackRect, pt)) { if (gameMode == EditPosition) { SetBlackToPlayEvent(); + } else if (gameMode == EditGame || GetKeyState(VK_SHIFT) < 0) { + AdjustClock(!flipClock, -1); } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) { CallFlagEvent(); - } else if (gameMode == EditGame) { - AdjustClock(!flipClock, -1); } } dragInfo.start.x = dragInfo.start.y = -1; @@ -3705,6 +4125,8 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_MOUSEMOVE: + if(SeekGraphClick(Press, pt.x - boardRect.left, pt.y - boardRect.top, 1)) break; + MovePV(pt.x - boardRect.left, pt.y - boardRect.top, boardRect.bottom - boardRect.top); if ((appData.animateDragging || appData.highlightDragging) && (wParam & MK_LBUTTON) && dragInfo.from.x >= 0) @@ -3732,16 +4154,22 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* Mouse Wheel is being rolled forward * Play moves forward */ - if((short)HIWORD(wParam) > 0 && currentMove < forwardMostMove) + if((short)HIWORD(wParam) < 0 && currentMove < forwardMostMove) { if(lastDir == 1) ForwardEvent(); else lastDir = 1; } // [HGM] suppress first event in direction /* Mouse Wheel is being rolled backward * Play moves backward */ - if((short)HIWORD(wParam) < 0 && currentMove > backwardMostMove) + if((short)HIWORD(wParam) > 0 && currentMove > backwardMostMove) { if(lastDir == -1) BackwardEvent(); else lastDir = -1; } } break; + case WM_MBUTTONUP: + case WM_RBUTTONUP: + ReleaseCapture(); + RightClick(Release, pt.x - boardRect.left, pt.y - boardRect.top, &fromX, &fromY); + break; + case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: ErrorPopDown(); @@ -3757,19 +4185,17 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if(y == -2) { /* [HGM] right mouse button in clock area edit-game mode ups clock */ if (PtInRect((LPRECT) &whiteRect, pt)) { - if (gameMode == EditGame) AdjustClock(flipClock, 1); + if (gameMode == EditGame || GetKeyState(VK_SHIFT) < 0) AdjustClock(flipClock, 1); } else if (PtInRect((LPRECT) &blackRect, pt)) { - if (gameMode == EditGame) AdjustClock(!flipClock, 1); + if (gameMode == EditGame || GetKeyState(VK_SHIFT) < 0) AdjustClock(!flipClock, 1); } + break; } DrawPosition(TRUE, NULL); - switch (gameMode) { - case EditPosition: - case IcsExamining: - if (x < 0 || y < 0) break; - fromX = x; - fromY = y; + menuNr = RightClick(Press, pt.x - boardRect.left, pt.y - boardRect.top, &fromX, &fromY); + switch (menuNr) { + case 0: if (message == WM_MBUTTONDOWN) { buttonCount = 3; /* even if system didn't think so */ if (wParam & MK_SHIFT) @@ -3786,21 +4212,13 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) MenuPopup(hwnd, pt, LoadMenu(hInst, "ShogiPieceMenu"), -1); } break; - case IcsPlayingWhite: - case IcsPlayingBlack: - case EditGame: - case MachinePlaysWhite: - case MachinePlaysBlack: - if (appData.testLegality && - gameInfo.variant != VariantBughouse && - gameInfo.variant != VariantCrazyhouse) break; - if (x < 0 || y < 0) break; - fromX = x; - fromY = y; + case 2: + SetCapture(hwndMain); + break; + case 1: hmenu = LoadMenu(hInst, "DropPieceMenu"); SetupDropMenu(hmenu); MenuPopup(hwnd, pt, hmenu, -1); - break; default: break; } @@ -3864,6 +4282,7 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) case WM_INITDIALOG: /* message: initialize dialog box */ /* Center the dialog over the application window */ CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER)); + Translate(hDlg, DLG_PromotionKing); ShowWindow(GetDlgItem(hDlg, PB_King), (!appData.testLegality || gameInfo.variant == VariantSuicide || gameInfo.variant == VariantGiveaway || gameInfo.variant == VariantSuper ) ? @@ -3988,7 +4407,7 @@ LoadGameDialog(HWND hwnd, char* title) if (number == 0) { int error = GameListBuild(f); if (error) { - DisplayError("Cannot build game list", error); + DisplayError(_("Cannot build game list"), error); } else if (!ListEmpty(&gameList) && ((ListGame *) gameList.tailPred)->number > 1) { GameListPopUp(f, fileTitle); @@ -4064,7 +4483,8 @@ ChangedConsoleFont() cfmt.cbSize = sizeof(CHARFORMAT); cfmt.dwMask = CFM_FACE|CFM_SIZE|CFM_CHARSET; - strcpy(cfmt.szFaceName, font[boardSize][CONSOLE_FONT]->mfp.faceName); + safeStrCpy(cfmt.szFaceName, font[boardSize][CONSOLE_FONT]->mfp.faceName, + sizeof(cfmt.szFaceName)/sizeof(cfmt.szFaceName[0]) ); /* yHeight is expressed in twips. A twip is 1/20 of a font's point * size. This was undocumented in the version of MSVC++ that I had * when I wrote the code, but is apparently documented now. @@ -4210,7 +4630,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) break; case IDM_LoadGame: - LoadGameDialog(hwnd, "Load Game from File"); + LoadGameDialog(hwnd, _("Load Game from File")); break; case IDM_LoadNextGame: @@ -4233,7 +4653,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) f = OpenFileDialog(hwnd, "rb", "", appData.oldSaveStyle ? "pos" : "fen", POSITION_FILT, - "Load Position from File", &number, fileTitle, NULL); + _("Load Position from File"), &number, fileTitle, NULL); if (f != NULL) { LoadPosition(f, number, fileTitle); } @@ -4256,7 +4676,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) f = OpenFileDialog(hwnd, "a", defName, appData.oldSaveStyle ? "gam" : "pgn", GAME_FILT, - "Save Game to File", NULL, fileTitle, NULL); + _("Save Game to File"), NULL, fileTitle, NULL); if (f != NULL) { SaveGame(f, 0, ""); } @@ -4267,7 +4687,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) f = OpenFileDialog(hwnd, "a", defName, appData.oldSaveStyle ? "pos" : "fen", POSITION_FILT, - "Save Position to File", NULL, fileTitle, NULL); + _("Save Position to File"), NULL, fileTitle, NULL); if (f != NULL) { SavePosition(f, 0, ""); } @@ -4351,7 +4771,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) break; case IDM_NewChat: - ChatPopUp(); + ChatPopUp(NULL); break; case IDM_CopyPosition: @@ -4407,6 +4827,14 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) SAY("computer starts playing black"); break; + case IDM_Match: // [HGM] match: flows into next case, after setting Match Mode and nr of Games + if(gameMode != BeginningOfGame) { // allow menu item to remain enabled for better mode highligting + DisplayError(_("You can only start a match from the initial position."), 0); break; + } + matchMode = 2;// distinguish from command-line-triggered case (matchMode=1) + appData.matchGames = appData.defaultMatchGames; + matchGame = 1; + case IDM_TwoMachines: TwoMachinesEvent(); /* @@ -4418,19 +4846,19 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) TagsPopUp(tags, CmailMsg()); free(tags); } - SAY("programs start playing each other"); + SAY("computer starts playing both sides"); break; case IDM_AnalysisMode: if (!first.analysisSupport) { - sprintf(buf, "%s does not support analysis", first.tidy); + snprintf(buf, MSG_SIZ, _("%s does not support analysis"), first.tidy); DisplayError(buf, 0); } else { SAY("analyzing current position"); /* [DM] icsEngineAnlyze [HGM] Why is this front-end??? */ if (appData.icsActive) { if (gameMode != IcsObserving) { - sprintf(buf, "You are not observing a game"); + snprintf(buf, MSG_SIZ, "You are not observing a game"); DisplayError(buf, 0); /* secure check */ if (appData.icsEngineAnalyze) { @@ -4460,12 +4888,12 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case IDM_AnalyzeFile: if (!first.analysisSupport) { char buf[MSG_SIZ]; - sprintf(buf, "%s does not support analysis", first.tidy); + snprintf(buf, MSG_SIZ, _("%s does not support analysis"), first.tidy); DisplayError(buf, 0); } else { if (!appData.showThinking) ToggleShowThinking(); AnalyzeFileEvent(); - LoadGameDialog(hwnd, "Analyze Game from File"); + LoadGameDialog(hwnd, _("Analyze Game from File")); AnalysisPeriodicEvent(1); } break; @@ -4481,7 +4909,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case IDM_EditPosition: EditPositionEvent(); - SAY("to set up a position type a FEN"); + SAY("enter a FEN string or setup a position on the board using the control R pop up menu"); break; case IDM_Training: @@ -4548,6 +4976,10 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) StopExaminingEvent(); break; + case IDM_Upload: + UploadGameEvent(); + break; + case IDM_TypeInMove: PopUpMoveDialog('\000'); break; @@ -4579,7 +5011,11 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) break; case IDM_Revert: - RevertEvent(); + RevertEvent(FALSE); + break; + + case IDM_Annotate: // [HGM] vari: revert with annotation + RevertEvent(TRUE); break; case IDM_TruncateGame: @@ -4629,6 +5065,8 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) break; case IDM_Engine2Options: + savedHwnd = hwnd; + if(WaitForSecond(SettingsMenuIfReady)) break; EngineOptionsPopup(hwnd, &second); break; @@ -4706,7 +5144,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (!MyHelp (hwnd, "winboard.hlp", HELP_KEY,(DWORD)(LPSTR)"CONTENTS") && !HtmlHelp(hwnd, "winboard.chm", 0, 0) ) { MessageBox (GetFocus(), - "Unable to activate help", + _("Unable to activate help"), szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND); } break; @@ -4715,7 +5153,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (!MyHelp (hwnd, "winboard.hlp", HELP_PARTIALKEY, (DWORD)(LPSTR)"") && !HtmlHelp(hwnd, "winboard.chm", 0, 0) ) { MessageBox (GetFocus(), - "Unable to activate help", + _("Unable to activate help"), szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND); } break; @@ -4723,7 +5161,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case IDM_HELPHELP: if(!WinHelp(hwnd, (LPSTR)NULL, HELP_HELPONHELP, 0)) { MessageBox (GetFocus(), - "Unable to activate help", + _("Unable to activate help"), szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND); } break; @@ -4737,12 +5175,12 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) break; case IDM_DirectCommand1: - AskQuestionEvent("Direct Command", - "Send to chess program:", "", "1"); + AskQuestionEvent(_("Direct Command"), + _("Send to chess program:"), "", "1"); break; case IDM_DirectCommand2: - AskQuestionEvent("Direct Command", - "Send to second chess program:", "", "2"); + AskQuestionEvent(_("Direct Command"), + _("Send to second chess program:"), "", "2"); break; case EP_WhitePawn: @@ -4920,7 +5358,23 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) fromX = fromY = -1; break; + case IDM_English: + barbaric = 0; + TranslateMenus(0); + CheckMenuItem(GetMenu(hwndMain), lastChecked, MF_BYCOMMAND|MF_UNCHECKED); + CheckMenuItem(GetMenu(hwndMain), IDM_English, MF_BYCOMMAND|MF_CHECKED); + lastChecked = wmId; + break; + default: + if(wmId > IDM_English && wmId < IDM_English+5) { + LoadLanguageFile(languageFile[wmId - IDM_English - 1]); + TranslateMenus(0); + CheckMenuItem(GetMenu(hwndMain), lastChecked, MF_BYCOMMAND|MF_UNCHECKED); + CheckMenuItem(GetMenu(hwndMain), wmId, MF_BYCOMMAND|MF_CHECKED); + lastChecked = wmId; + break; + } return (DefWindowProc(hwnd, message, wParam, lParam)); } break; @@ -5159,7 +5613,7 @@ MyLoadSound(MySound *ms) } if (!ok) { char buf[MSG_SIZ]; - sprintf(buf, "Error loading sound %s", ms->name); + snprintf(buf, MSG_SIZ, _("Error loading sound %s"), ms->name); DisplayError(buf, GetLastError()); } return ok; @@ -5225,6 +5679,7 @@ OldOpenFileHook(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) number = NULL; } CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + Translate(hDlg, 1536); return FALSE; /* Allow for further processing */ case WM_COMMAND: @@ -5244,6 +5699,7 @@ OpenFileHook(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) OFNOTIFY *ofnot; switch (uiMsg) { case WM_INITDIALOG: + Translate(hdlg, DLG_IndexNumber); ofname = (OPENFILENAME *)lParam; number = (UINT *)(ofname->lCustData); break; @@ -5269,12 +5725,12 @@ OpenFileDialog(HWND hwnd, char *write, char *defName, char *defExt, // [HGM] dia if (fileName == NULL) fileName = buf1; if (defName == NULL) { - strcpy(fileName, "*."); + safeStrCpy(fileName, "*.", 3 ); strcat(fileName, defExt); } else { - strcpy(fileName, defName); + safeStrCpy(fileName, defName, MSG_SIZ ); } - if (fileTitle) strcpy(fileTitle, ""); + if (fileTitle) safeStrCpy(fileTitle, "", MSG_SIZ ); if (number) *number = 0; openFileName.lStructSize = sizeof(OPENFILENAME); @@ -5307,13 +5763,13 @@ OpenFileDialog(HWND hwnd, char *write, char *defName, char *defExt, // [HGM] dia /* open the file */ f = fopen(openFileName.lpstrFile, write); if (f == NULL) { - MessageBox(hwnd, "File open failed", NULL, + MessageBox(hwnd, _("File open failed"), NULL, MB_OK|MB_ICONEXCLAMATION); return NULL; } } else { int err = CommDlgExtendedError(); - if (err != 0) DisplayError("Internal error in file dialog box", err); + if (err != 0) DisplayError(_("Internal error in file dialog box"), err); return FALSE; } return f; @@ -5473,7 +5929,7 @@ InitComboStrings(HANDLE hwndCombo, char **cd) SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0); while (*cd != NULL) { - SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) *cd); + SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) T_(*cd)); cd++; } } @@ -5552,10 +6008,10 @@ InitEngineBox(HWND hDlg, HWND hwndCombo, char* nthcp, char* nthd, char* nthdir, InitComboStringsFromOption(hwndCombo, nthnames); q = QuoteForFilename(nthcp); - sprintf(buf, "%s%s%s", q, nthcp, q); + snprintf(buf, MSG_SIZ, "%s%s%s", q, nthcp, q); if (*nthdir != NULLCHAR) { q = QuoteForFilename(nthdir); - sprintf(buf + strlen(buf), " /%s=%s%s%s", nthd, q, nthdir, q); + snprintf(buf + strlen(buf), MSG_SIZ, " /%s=%s%s%s", nthd, q, nthdir, q); } if (*nthcp == NULLCHAR) { SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) 0, (LPARAM) 0); @@ -5576,6 +6032,7 @@ StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) case WM_INITDIALOG: /* Center the dialog */ CenterWindow (hDlg, GetDesktopWindow()); + Translate(hDlg, DLG_Startup); /* Initialize the dialog items */ InitEngineBox(hDlg, GetDlgItem(hDlg, OPT_ChessEngineName), appData.firstChessProgram, "fd", appData.firstDirectory, @@ -5585,7 +6042,7 @@ StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) secondChessProgramNames); hwndCombo = GetDlgItem(hDlg, OPT_ChessServerName); InitComboStringsFromOption(hwndCombo, icsNames); - sprintf(buf, "%s /icsport=%s", appData.icsHost, appData.icsPort); + snprintf(buf, MSG_SIZ, "%s /icsport=%s", appData.icsHost, appData.icsPort); if (*appData.icsHelper != NULLCHAR) { char *q = QuoteForFilename(appData.icsHelper); sprintf(buf + strlen(buf), " /icshelper=%s%s%s", q, appData.icsHelper, q); @@ -5615,23 +6072,23 @@ StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) switch (LOWORD(wParam)) { case IDOK: if (IsDlgButtonChecked(hDlg, OPT_ChessEngine)) { - strcpy(buf, "/fcp="); + safeStrCpy(buf, "/fcp=", sizeof(buf)/sizeof(buf[0]) ); GetDlgItemText(hDlg, OPT_ChessEngineName, buf + strlen(buf), sizeof(buf) - strlen(buf)); p = buf; ParseArgs(StringGet, &p); - strcpy(buf, "/scp="); + safeStrCpy(buf, "/scp=", sizeof(buf)/sizeof(buf[0]) ); GetDlgItemText(hDlg, OPT_SecondChessEngineName, buf + strlen(buf), sizeof(buf) - strlen(buf)); p = buf; ParseArgs(StringGet, &p); appData.noChessProgram = FALSE; appData.icsActive = FALSE; } else if (IsDlgButtonChecked(hDlg, OPT_ChessServer)) { - strcpy(buf, "/ics /icshost="); + safeStrCpy(buf, "/ics /icshost=", sizeof(buf)/sizeof(buf[0]) ); GetDlgItemText(hDlg, OPT_ChessServerName, buf + strlen(buf), sizeof(buf) - strlen(buf)); p = buf; ParseArgs(StringGet, &p); if (appData.zippyPlay) { - strcpy(buf, "/fcp="); + safeStrCpy(buf, "/fcp=", sizeof(buf)/sizeof(buf[0]) ); GetDlgItemText(hDlg, OPT_ChessEngineName, buf + strlen(buf), sizeof(buf) - strlen(buf)); p = buf; ParseArgs(StringGet, &p); @@ -5640,8 +6097,8 @@ StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) appData.noChessProgram = TRUE; appData.icsActive = FALSE; } else { - MessageBox(hDlg, "Choose an option, or cancel to exit", - "Option Error", MB_OK|MB_ICONEXCLAMATION); + MessageBox(hDlg, _("Choose an option, or cancel to exit"), + _("Option Error"), MB_OK|MB_ICONEXCLAMATION); return TRUE; } if (IsDlgButtonChecked(hDlg, OPT_AnyAdditional)) { @@ -5659,7 +6116,7 @@ StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) case IDM_HELPCONTENTS: if (!WinHelp (hDlg, "winboard.hlp", HELP_KEY,(DWORD)(LPSTR)"CONTENTS")) { MessageBox (GetFocus(), - "Unable to activate help", + _("Unable to activate help"), szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND); } break; @@ -5688,6 +6145,7 @@ About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) /* Center the dialog over the application window */ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); SetDlgItemText(hDlg, ABOUTBOX_Version, programVersion); + Translate(hDlg, ABOUTBOX); JAWS_COPYRIGHT return (TRUE); @@ -5721,6 +6179,7 @@ CommentDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) switch (message) { case WM_INITDIALOG: /* message: initialize dialog box */ /* Initialize the dialog items */ + Translate(hDlg, DLG_EditComment); hwndText = GetDlgItem(hDlg, OPT_CommentText); SetDlgItemText(hDlg, OPT_CommentText, commentText); EnableWindow(GetDlgItem(hDlg, OPT_CancelComment), editComment); @@ -5766,6 +6225,7 @@ CommentDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) sizeY = newSizeY; } } + SendDlgItemMessage( hDlg, OPT_CommentText, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS ); return FALSE; case WM_COMMAND: /* message: received a command */ @@ -5810,6 +6270,36 @@ CommentDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) } break; + case WM_NOTIFY: // [HGM] vari: cloned from whistory.c + if( wParam == OPT_CommentText ) { + MSGFILTER * lpMF = (MSGFILTER *) lParam; + + if( lpMF->msg == WM_RBUTTONDOWN && (lpMF->wParam & (MK_CONTROL | MK_SHIFT)) == 0 ) { + POINTL pt; + LRESULT index; + + pt.x = LOWORD( lpMF->lParam ); + pt.y = HIWORD( lpMF->lParam ); + + index = SendDlgItemMessage( hDlg, OPT_CommentText, EM_CHARFROMPOS, 0, (LPARAM) &pt ); + + hwndText = GetDlgItem(hDlg, OPT_CommentText); // cloned from above + len = GetWindowTextLength(hwndText); + str = (char *) malloc(len + 1); + GetWindowText(hwndText, str, len + 1); + ReplaceComment(commentIndex, str); + if(commentIndex != currentMove) ToNrEvent(commentIndex); + LoadVariation( index, str ); // [HGM] also does the actual moving to it, now + free(str); + + /* Zap the message for good: apparently, returning non-zero is not enough */ + lpMF->msg = WM_USER; + + return TRUE; + } + } + break; + case WM_SIZE: newSizeX = LOWORD(lParam); newSizeY = HIWORD(lParam); @@ -5884,6 +6374,7 @@ TypeInMoveDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) move[0] = (char) lParam; move[1] = NULLCHAR; CenterWindowEx(hDlg, GetWindow(hDlg, GW_OWNER), 1 ); + Translate(hDlg, DLG_TypeInMove); hInput = GetDlgItem(hDlg, OPT_Move); SetWindowText(hInput, move); SetFocus(hInput); @@ -5892,7 +6383,8 @@ TypeInMoveDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) case WM_COMMAND: switch (LOWORD(wParam)) { - case IDOK: + case IDOK: + shiftKey = GetKeyState(VK_SHIFT) < 0; // [HGM] remember last shift status GetDlgItemText(hDlg, OPT_Move, move, sizeof(move)); { int n; Board board; // [HGM] FENedit @@ -5910,7 +6402,7 @@ TypeInMoveDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) } if (gameMode != EditGame && currentMove != forwardMostMove && gameMode != Training) { - DisplayMoveError("Displayed move is not current"); + DisplayMoveError(_("Displayed move is not current")); } else { // GetDlgItemText(hDlg, OPT_Move, move, sizeof(move)); // moved upstream int ok = ParseOneMove(move, gameMode == EditPosition ? blackPlaysFirst : currentMove, @@ -5922,7 +6414,7 @@ TypeInMoveDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) forwardMostMove = currentMove; UserMoveEvent(fromX, fromY, toX, toY, promoChar); } else { - DisplayMoveError("Could not parse move"); + DisplayMoveError(_("Could not parse move")); } } EndDialog(hDlg, TRUE); @@ -5976,6 +6468,7 @@ TypeInNameDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) move[0] = (char) lParam; move[1] = NULLCHAR; CenterWindowEx(hDlg, GetWindow(hDlg, GW_OWNER), 1 ); + Translate(hDlg, DLG_TypeInName); hInput = GetDlgItem(hDlg, OPT_Name); SetWindowText(hInput, move); SetFocus(hInput); @@ -5988,6 +6481,12 @@ TypeInNameDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) GetDlgItemText(hDlg, OPT_Name, move, sizeof(move)); appData.userName = strdup(move); SetUserLogo(); + SetGameInfo(); + if(gameMode == MachinePlaysWhite || gameMode == MachinePlaysBlack) { + snprintf(move, MSG_SIZ, "%s vs. %s", gameInfo.white, gameInfo.black); + DisplayTitle(move); + } + EndDialog(hDlg, TRUE); return TRUE; @@ -6092,6 +6591,7 @@ ErrorDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) For now, just give it a default position. */ SetWindowPos(hDlg, NULL, boardRect.left+8, boardRect.top+8, 0, 0, SWP_NOZORDER|SWP_NOSIZE); + Translate(hDlg, DLG_Error); errorDialog = hDlg; SetWindowText(hDlg, errorTitle); @@ -6242,13 +6742,14 @@ LoadIcsTextMenu(IcsTextMenuEntry *e) while (e->item) { if (strcmp(e->item, "-") == 0) { AppendMenu(h, MF_SEPARATOR, 0, 0); - } else { + } else { // [HGM] re-written a bit to use only one AppendMenu call for both cases (| or no |) + int flags = MF_STRING, j = 0; if (e->item[0] == '|') { - AppendMenu(h, MF_STRING|MF_MENUBARBREAK, - IDM_CommandX + i, &e->item[1]); - } else { - AppendMenu(h, MF_STRING, IDM_CommandX + i, e->item); + flags |= MF_MENUBARBREAK; + j++; } + if(!strcmp(e->command, "none")) flags |= MF_GRAYED; // [HGM] chatclick: provide inactive dummy + AppendMenu(h, flags, IDM_CommandX + i, e->item + j); } e++; i++; @@ -6313,11 +6814,13 @@ CommandX(HWND hwnd, char *command, BOOLEAN getname, BOOLEAN immediate) SendMessage(hwnd, EM_GETSELTEXT, 0, (LPARAM) name); } if (immediate) { - sprintf(buf, "%s %s", command, name); + if(strstr(command, "%s")) snprintf(buf, MSG_SIZ, command, name); else + snprintf(buf, MSG_SIZ, "%s %s", command, name); SetWindowText(hInput, buf); SendMessage(hInput, WM_CHAR, '\r', 0); } else { - sprintf(buf, "%s %s ", command, name); /* trailing space */ + if(!strcmp(command, "chat")) { ChatPopUp(name); return; } + snprintf(buf, MSG_SIZ, "%s %s ", command, name); /* trailing space */ SetWindowText(hInput, buf); sel.cpMin = 999999; sel.cpMax = 999999; @@ -6369,11 +6872,20 @@ ConsoleTextSubclass(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } return 0; } // [HGM] navigate: for Ctrl+R, flow into nex case (moved up here) to summon up menu - case WM_RBUTTONUP: - if (GetKeyState(VK_SHIFT) & ~1) { - SendDlgItemMessage(hwndConsole, OPT_ConsoleText, - WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0); - } else { + case WM_RBUTTONDOWN: + if (!(GetKeyState(VK_SHIFT) & ~1)) { + /* Move selection here if it was empty */ + POINT pt; + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); + if (sel.cpMin == sel.cpMax) { + sel.cpMin = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&pt); /*doc is wrong*/ + sel.cpMax = sel.cpMin; + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel); + } + SendMessage(hwnd, EM_HIDESELECTION, FALSE, FALSE); +{ // [HGM] chatclick: code moved here from WM_RBUTTONUP case, to have menu appear on down-click POINT pt; HMENU hmenu = LoadIcsTextMenu(icsTextMenuEntry); SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); @@ -6384,9 +6896,17 @@ ConsoleTextSubclass(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (!IsClipboardFormatAvailable(CF_TEXT)) { EnableMenuItem(hmenu, IDM_Paste, MF_BYCOMMAND|MF_GRAYED); } - pt.x = LOWORD(lParam); - pt.y = HIWORD(lParam); + pt.x = LOWORD(lParam)-30; // [HGM] chatclick: make menu pop up with pointer above upper-right item + pt.y = HIWORD(lParam)-10; // make it appear as if mouse moved there, so it will be selected on up-click + PostMessage(hwnd, WM_MOUSEMOVE, wParam, lParam+5); MenuPopup(hwnd, pt, hmenu, -1); +} + } + return 0; + case WM_RBUTTONUP: + if (GetKeyState(VK_SHIFT) & ~1) { + SendDlgItemMessage(hwndConsole, OPT_ConsoleText, + WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0); } return 0; case WM_PASTE: @@ -6395,21 +6915,6 @@ ConsoleTextSubclass(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) return SendMessage(hInput, message, wParam, lParam); case WM_MBUTTONDOWN: return SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0); - case WM_RBUTTONDOWN: - if (!(GetKeyState(VK_SHIFT) & ~1)) { - /* Move selection here if it was empty */ - POINT pt; - pt.x = LOWORD(lParam); - pt.y = HIWORD(lParam); - SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); - if (sel.cpMin == sel.cpMax) { - sel.cpMin = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&pt); /*doc is wrong*/ - sel.cpMax = sel.cpMin; - SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel); - } - SendMessage(hwnd, EM_HIDESELECTION, FALSE, FALSE); - } - return 0; case WM_COMMAND: switch (LOWORD(wParam)) { case IDM_QuickPaste: @@ -6881,7 +7386,8 @@ DisplayHoldingsCount(HDC hdc, int x, int y, int rightAlign, int copyNumber) HFONT oldFont; RECT rect; - if(copyNumber > 1) sprintf(buf, "%d", copyNumber); else buf[0] = 0; + if(copyNumber > 1) + snprintf(buf, sizeof(buf)/sizeof(buf[0]),"%d", copyNumber); else buf[0] = 0; oldFg = SetTextColor(hdc, RGB(255, 255, 255)); /* white */ oldBg = SetBkColor(hdc, RGB(0, 0, 0)); /* black */ @@ -6914,9 +7420,9 @@ DisplayAClock(HDC hdc, int timeRemaining, int highlight, if (appData.clockMode) { if (tinyLayout) - sprintf(buf, "%c %s %s", color[0], TimeString(timeRemaining), flagFell); + snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%c %s %s", color[0], TimeString(timeRemaining), flagFell); else - sprintf(buf, "%s:%c%s %s", color, (logoHeight>0 ? 0 : ' '), TimeString(timeRemaining), flagFell); + snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s:%c%s %s", color, (logoHeight>0 ? 0 : ' '), TimeString(timeRemaining), flagFell); str = buf; } else { str = color; @@ -6938,7 +7444,7 @@ DisplayAClock(HDC hdc, int timeRemaining, int highlight, rect, str, strlen(str), NULL); if(logoHeight > 0 && appData.clockMode) { RECT r; - sprintf(buf, "%s %s", buf+7, flagFell); + snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s %s", buf+7, flagFell); r.top = rect->top + logoHeight/2; r.left = rect->left; r.right = rect->right; @@ -7217,6 +7723,7 @@ GreyRevert(Boolean grey) { // [HGM] vari: for retracting variations in local mode HMENU hmenu = GetMenu(hwndMain); EnableMenuItem(hmenu, IDM_Revert, MF_BYCOMMAND|(grey ? MF_GRAYED : MF_ENABLED)); + EnableMenuItem(hmenu, IDM_Annotate, MF_BYCOMMAND|(grey ? MF_GRAYED : MF_ENABLED)); } VOID @@ -7238,7 +7745,9 @@ Enables gnuEnables[] = { { IDM_Adjourn, MF_BYCOMMAND|MF_GRAYED }, { IDM_StopExamining, MF_BYCOMMAND|MF_GRAYED }, { IDM_StopObserving, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Upload, MF_BYCOMMAND|MF_GRAYED }, { IDM_Revert, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Annotate, MF_BYCOMMAND|MF_GRAYED }, { IDM_NewChat, MF_BYCOMMAND|MF_GRAYED }, { -1, -1 } }; @@ -7249,6 +7758,7 @@ Enables icsEnables[] = { { IDM_MachineWhite, MF_BYCOMMAND|MF_GRAYED }, { IDM_MachineBlack, MF_BYCOMMAND|MF_GRAYED }, { IDM_TwoMachines, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Match, MF_BYCOMMAND|MF_GRAYED }, { IDM_MachineBoth, MF_BYCOMMAND|MF_GRAYED }, { IDM_AnalysisMode, MF_BYCOMMAND|MF_ENABLED }, { IDM_AnalyzeFile, MF_BYCOMMAND|MF_GRAYED }, @@ -7259,10 +7769,11 @@ Enables icsEnables[] = { { IDM_IcsOptions, MF_BYCOMMAND|MF_ENABLED }, { IDM_Engine1Options, MF_BYCOMMAND|MF_GRAYED }, { IDM_Engine2Options, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Annotate, MF_BYCOMMAND|MF_GRAYED }, { -1, -1 } }; -#ifdef ZIPPY +#if ZIPPY Enables zippyEnables[] = { { IDM_MoveNow, MF_BYCOMMAND|MF_ENABLED }, { IDM_Hint, MF_BYCOMMAND|MF_ENABLED }, @@ -7278,11 +7789,13 @@ Enables ncpEnables[] = { { IDM_MachineWhite, MF_BYCOMMAND|MF_GRAYED }, { IDM_MachineBlack, MF_BYCOMMAND|MF_GRAYED }, { IDM_TwoMachines, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Match, MF_BYCOMMAND|MF_GRAYED }, { IDM_AnalysisMode, MF_BYCOMMAND|MF_GRAYED }, { IDM_AnalyzeFile, MF_BYCOMMAND|MF_GRAYED }, { IDM_IcsClient, MF_BYCOMMAND|MF_GRAYED }, { ACTION_POS, MF_BYPOSITION|MF_GRAYED }, { IDM_Revert, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Annotate, MF_BYCOMMAND|MF_GRAYED }, { IDM_MoveNow, MF_BYCOMMAND|MF_GRAYED }, { IDM_RetractMove, MF_BYCOMMAND|MF_GRAYED }, { IDM_TimeControl, MF_BYCOMMAND|MF_GRAYED }, @@ -7345,6 +7858,7 @@ Enables machineThinkingEnables[] = { { IDM_MachineWhite, MF_BYCOMMAND|MF_GRAYED }, { IDM_MachineBlack, MF_BYCOMMAND|MF_GRAYED }, { IDM_TwoMachines, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Match, MF_BYCOMMAND|MF_GRAYED }, { IDM_TypeInMove, MF_BYCOMMAND|MF_GRAYED }, { IDM_RetractMove, MF_BYCOMMAND|MF_GRAYED }, { -1, -1 } @@ -7364,6 +7878,7 @@ Enables userThinkingEnables[] = { { IDM_MachineWhite, MF_BYCOMMAND|MF_ENABLED }, { IDM_MachineBlack, MF_BYCOMMAND|MF_ENABLED }, { IDM_TwoMachines, MF_BYCOMMAND|MF_ENABLED }, + { IDM_Match, MF_BYCOMMAND|MF_ENABLED }, { IDM_TypeInMove, MF_BYCOMMAND|MF_ENABLED }, { IDM_RetractMove, MF_BYCOMMAND|MF_ENABLED }, { -1, -1 } @@ -7405,7 +7920,7 @@ ModeHighlight() nowChecked = IDM_MachineWhite; break; case TwoMachinesPlay: - nowChecked = IDM_TwoMachines; + nowChecked = matchMode ? IDM_Match : IDM_TwoMachines; // [HGM] match break; case AnalyzeMode: nowChecked = IDM_AnalysisMode; @@ -7472,7 +7987,7 @@ SetICSMode() SetMenuEnables(hmenu, icsEnables); EnableMenuItem(GetSubMenu(hmenu, OPTIONS_POS), ICS_POS, MF_BYPOSITION|MF_ENABLED); -#ifdef ZIPPY +#if ZIPPY if (appData.zippyPlay) { SetMenuEnables(hmenu, zippyEnables); if (!appData.noChessProgram) /* [DM] icsEngineAnalyze */ @@ -7546,7 +8061,7 @@ SetMachineThinkingEnables() } else if (gameMode == MachinePlaysWhite) { (void)EnableMenuItem(hMenu, IDM_MachineWhite, flags); } else if (gameMode == TwoMachinesPlay) { - (void)EnableMenuItem(hMenu, IDM_TwoMachines, flags); + (void)EnableMenuItem(hMenu, matchMode ? IDM_Match : IDM_TwoMachines, flags); // [HGM] match } } @@ -7556,17 +8071,17 @@ DisplayTitle(char *str) { char title[MSG_SIZ], *host; if (str[0] != NULLCHAR) { - strcpy(title, str); + safeStrCpy(title, str, sizeof(title)/sizeof(title[0]) ); } else if (appData.icsActive) { if (appData.icsCommPort[0] != NULLCHAR) host = "ICS"; else host = appData.icsHost; - sprintf(title, "%s: %s", szTitle, host); + snprintf(title, MSG_SIZ, "%s: %s", szTitle, host); } else if (appData.noChessProgram) { - strcpy(title, szTitle); + safeStrCpy(title, szTitle, sizeof(title)/sizeof(title[0]) ); } else { - strcpy(title, szTitle); + safeStrCpy(title, szTitle, sizeof(title)/sizeof(title[0]) ); strcat(title, ": "); strcat(title, first.tidy); } @@ -7621,25 +8136,25 @@ DisplayError(char *str, int error) int len; if (error == 0) { - strcpy(buf, str); + safeStrCpy(buf, str, sizeof(buf)/sizeof(buf[0]) ); } else { len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, LANG_NEUTRAL, (LPSTR) buf2, MSG_SIZ, NULL); if (len > 0) { - sprintf(buf, "%s:\n%s", str, buf2); + snprintf(buf, 2*MSG_SIZ, "%s:\n%s", str, buf2); } else { ErrorMap *em = errmap; while (em->err != 0 && em->err != error) em++; if (em->err != 0) { - sprintf(buf, "%s:\n%s", str, em->msg); + snprintf(buf, 2*MSG_SIZ, "%s:\n%s", str, em->msg); } else { - sprintf(buf, "%s:\nError code %d", str, error); + snprintf(buf, 2*MSG_SIZ, "%s:\nError code %d", str, error); } } } - ErrorPopUp("Error", buf); + ErrorPopUp(_("Error"), buf); } @@ -7650,7 +8165,7 @@ DisplayMoveError(char *str) ClearHighlights(); DrawPosition(FALSE, NULL); if (appData.popupMoveErrors) { - ErrorPopUp("Error", str); + ErrorPopUp(_("Error"), str); } else { DisplayMessage(str, ""); moveErrorMessageUp = TRUE; @@ -7662,21 +8177,21 @@ DisplayFatalError(char *str, int error, int exitStatus) { char buf[2*MSG_SIZ], buf2[MSG_SIZ]; int len; - char *label = exitStatus ? "Fatal Error" : "Exiting"; + char *label = exitStatus ? _("Fatal Error") : _("Exiting"); if (error != 0) { len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, LANG_NEUTRAL, (LPSTR) buf2, MSG_SIZ, NULL); if (len > 0) { - sprintf(buf, "%s:\n%s", str, buf2); + snprintf(buf, 2*MSG_SIZ, "%s:\n%s", str, buf2); } else { ErrorMap *em = errmap; while (em->err != 0 && em->err != error) em++; if (em->err != 0) { - sprintf(buf, "%s:\n%s", str, em->msg); + snprintf(buf, 2*MSG_SIZ, "%s:\n%s", str, em->msg); } else { - sprintf(buf, "%s:\nError code %d", str, error); + snprintf(buf, 2*MSG_SIZ, "%s:\nError code %d", str, error); } } str = buf; @@ -7695,14 +8210,14 @@ DisplayFatalError(char *str, int error, int exitStatus) VOID DisplayInformation(char *str) { - (void) MessageBox(hwndMain, str, "Information", MB_OK|MB_ICONINFORMATION); + (void) MessageBox(hwndMain, str, _("Information"), MB_OK|MB_ICONINFORMATION); } VOID DisplayNote(char *str) { - ErrorPopUp("Note", str); + ErrorPopUp(_("Note"), str); } @@ -7722,6 +8237,7 @@ QuestionDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) case WM_INITDIALOG: qp = (QuestionParams *) lParam; CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER)); + Translate(hDlg, DLG_Question); SetWindowText(hDlg, qp->title); SetDlgItemText(hDlg, OPT_QuestionText, qp->question); SetFocus(GetDlgItem(hDlg, OPT_QuestionInput)); @@ -7730,14 +8246,14 @@ QuestionDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: - strcpy(reply, qp->replyPrefix); + safeStrCpy(reply, qp->replyPrefix, sizeof(reply)/sizeof(reply[0]) ); if (*reply) strcat(reply, " "); len = strlen(reply); GetDlgItemText(hDlg, OPT_QuestionInput, reply + len, sizeof(reply) - len); strcat(reply, "\n"); OutputToProcess(qp->pr, reply, strlen(reply), &err); EndDialog(hDlg, TRUE); - if (err) DisplayFatalError("Error writing to chess program", err, 1); + if (err) DisplayFatalError(_("Error writing to chess program"), err, 1); return TRUE; case IDCANCEL: EndDialog(hDlg, FALSE); @@ -7779,6 +8295,7 @@ LRESULT CALLBACK NewGameFRC_Proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lpIndexFRC = (int *) lParam; CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER)); + Translate(hDlg, DLG_NewGameFRC); SendDlgItemMessage( hDlg, IDC_NFG_Edit, EM_SETLIMITTEXT, sizeof(buf)-1, 0 ); SetDlgItemInt( hDlg, IDC_NFG_Edit, *lpIndexFRC, TRUE ); @@ -7805,7 +8322,7 @@ LRESULT CALLBACK NewGameFRC_Proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM } return TRUE; case IDC_NFG_Random: - sprintf( buf, "%d", myrandom() ); /* [HGM] shuffle: no longer limit to 960 */ + snprintf( buf, sizeof(buf)/sizeof(buf[0]), "%d", myrandom() ); /* [HGM] shuffle: no longer limit to 960 */ SetDlgItemText(hDlg, IDC_NFG_Edit, buf ); return TRUE; } @@ -7831,104 +8348,42 @@ int NewGameFRC() return result; } -/* [AS] Game list options */ -typedef struct { - char id; - char * name; -} GLT_Item; - -static GLT_Item GLT_ItemInfo[] = { - { GLT_EVENT, "Event" }, - { GLT_SITE, "Site" }, - { GLT_DATE, "Date" }, - { GLT_ROUND, "Round" }, - { GLT_PLAYERS, "Players" }, - { GLT_RESULT, "Result" }, - { GLT_WHITE_ELO, "White Rating" }, - { GLT_BLACK_ELO, "Black Rating" }, - { GLT_TIME_CONTROL,"Time Control" }, - { GLT_VARIANT, "Variant" }, - { GLT_OUT_OF_BOOK,PGN_OUT_OF_BOOK }, - { GLT_RESULT_COMMENT, "Result Comment" }, // [HGM] rescom - { 0, 0 } -}; - -const char * GLT_FindItem( char id ) -{ - const char * result = 0; - - GLT_Item * list = GLT_ItemInfo; +/* [AS] Game list options. Refactored by HGM */ - while( list->id != 0 ) { - if( list->id == id ) { - result = list->name; - break; - } +HWND gameListOptionsDialog; - list++; - } - - return result; +// low-level front-end: clear text edit / list widget +void +GLT_ClearList() +{ + SendDlgItemMessage( gameListOptionsDialog, IDC_GameListTags, LB_RESETCONTENT, 0, 0 ); } -void GLT_AddToList( HWND hDlg, int iDlgItem, char id, int index ) +// low-level front-end: clear text edit / list widget +void +GLT_DeSelectList() { - const char * name = GLT_FindItem( id ); - - if( name != 0 ) { - if( index >= 0 ) { - SendDlgItemMessage( hDlg, iDlgItem, LB_INSERTSTRING, index, (LPARAM) name ); - } - else { - SendDlgItemMessage( hDlg, iDlgItem, LB_ADDSTRING, 0, (LPARAM) name ); - } - } + SendDlgItemMessage( gameListOptionsDialog, IDC_GameListTags, LB_SETCURSEL, 0, 0 ); } -void GLT_TagsToList( HWND hDlg, char * tags ) +// low-level front-end: append line to text edit / list widget +void +GLT_AddToList( char *name ) { - char * pc = tags; - - SendDlgItemMessage( hDlg, IDC_GameListTags, LB_RESETCONTENT, 0, 0 ); - - while( *pc ) { - GLT_AddToList( hDlg, IDC_GameListTags, *pc, -1 ); - pc++; - } - - SendDlgItemMessage( hDlg, IDC_GameListTags, LB_ADDSTRING, 0, (LPARAM) "\t --- Hidden tags ---" ); - - pc = GLT_ALL_TAGS; - - while( *pc ) { - if( strchr( tags, *pc ) == 0 ) { - GLT_AddToList( hDlg, IDC_GameListTags, *pc, -1 ); - } - pc++; + if( name != 0 ) { + SendDlgItemMessage( gameListOptionsDialog, IDC_GameListTags, LB_ADDSTRING, 0, (LPARAM) name ); } - - SendDlgItemMessage( hDlg, IDC_GameListTags, LB_SETCURSEL, 0, 0 ); } -char GLT_ListItemToTag( HWND hDlg, int index ) +// low-level front-end: get line from text edit / list widget +Boolean +GLT_GetFromList( int index, char *name ) { - char result = '\0'; - char name[128]; - - GLT_Item * list = GLT_ItemInfo; - - if( SendDlgItemMessage( hDlg, IDC_GameListTags, LB_GETTEXT, index, (LPARAM) name ) != LB_ERR ) { - while( list->id != 0 ) { - if( strcmp( list->name, name ) == 0 ) { - result = list->id; - break; - } - - list++; - } + if( name != 0 ) { + if( SendDlgItemMessage( gameListOptionsDialog, IDC_GameListTags, LB_GETTEXT, index, (LPARAM) name ) != LB_ERR ) + return TRUE; } - - return result; + return FALSE; } void GLT_MoveSelection( HWND hDlg, int delta ) @@ -7949,20 +8404,16 @@ void GLT_MoveSelection( HWND hDlg, int delta ) LRESULT CALLBACK GameListOptions_Proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { - static char glt[64]; - static char * lpUserGLT; - switch( message ) { case WM_INITDIALOG: - lpUserGLT = (char *) lParam; + gameListOptionsDialog = hDlg; // [HGM] pass through global to keep out off back-end - strcpy( glt, lpUserGLT ); - CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER)); + Translate(hDlg, DLG_GameListOptions); /* Initialize list */ - GLT_TagsToList( hDlg, glt ); + GLT_TagsToList( lpUserGLT ); SetFocus( GetDlgItem(hDlg, IDC_GameListTags) ); @@ -7971,19 +8422,7 @@ LRESULT CALLBACK GameListOptions_Proc(HWND hDlg, UINT message, WPARAM wParam, LP case WM_COMMAND: switch( LOWORD(wParam) ) { case IDOK: - { - char * pc = lpUserGLT; - int idx = 0; -// int cnt = (int) SendDlgItemMessage( hDlg, IDC_GameListTags, LB_GETCOUNT, 0, 0 ); - char id; - - do { - id = GLT_ListItemToTag( hDlg, idx ); - - *pc++ = id; - idx++; - } while( id != '\0' ); - } + GLT_ParseList(); EndDialog( hDlg, 0 ); return TRUE; case IDCANCEL: @@ -7991,13 +8430,11 @@ LRESULT CALLBACK GameListOptions_Proc(HWND hDlg, UINT message, WPARAM wParam, LP return TRUE; case IDC_GLT_Default: - strcpy( glt, GLT_DEFAULT_TAGS ); - GLT_TagsToList( hDlg, glt ); + GLT_TagsToList( GLT_DEFAULT_TAGS ); return TRUE; case IDC_GLT_Restore: - strcpy( glt, lpUserGLT ); - GLT_TagsToList( hDlg, glt ); + GLT_TagsToList( appData.gameListTags ); return TRUE; case IDC_GLT_Up: @@ -8017,29 +8454,27 @@ LRESULT CALLBACK GameListOptions_Proc(HWND hDlg, UINT message, WPARAM wParam, LP int GameListOptions() { - char glt[64]; int result; FARPROC lpProc = MakeProcInstance( (FARPROC) GameListOptions_Proc, hInst ); - strcpy( glt, appData.gameListTags ); + safeStrCpy( lpUserGLT, appData.gameListTags ,LPUSERGLT_SIZE ); - result = DialogBoxParam( hInst, MAKEINTRESOURCE(DLG_GameListOptions), hwndMain, (DLGPROC)lpProc, (LPARAM)glt ); + result = DialogBoxParam( hInst, MAKEINTRESOURCE(DLG_GameListOptions), hwndMain, (DLGPROC)lpProc, (LPARAM)lpUserGLT ); if( result == 0 ) { /* [AS] Memory leak here! */ - appData.gameListTags = strdup( glt ); + appData.gameListTags = strdup( lpUserGLT ); } return result; } - VOID DisplayIcsInteractionTitle(char *str) { char consoleTitle[MSG_SIZ]; - sprintf(consoleTitle, "%s: %s", szConsoleTitle, str); + snprintf(consoleTitle, MSG_SIZ, "%s: %s", szConsoleTitle, str); SetWindowText(hwndConsole, consoleTitle); } @@ -8068,6 +8503,7 @@ ResetFrontEnd() ReleaseCapture(); DrawPosition(TRUE, NULL); } + TagsPopDown(); } @@ -8075,7 +8511,7 @@ VOID CommentPopUp(char *title, char *str) { HWND hwnd = GetActiveWindow(); - EitherCommentPopUp(0, title, str, FALSE); + EitherCommentPopUp(currentMove, title, str, FALSE); // [HGM] vari: fake move index, rather than 0 SAY(str); SetActiveWindow(hwnd); } @@ -8177,7 +8613,7 @@ UserName() } if (!GetUserName(buf, &bufsiz)) { /*DisplayError("Error getting user name", GetLastError());*/ - strcpy(buf, "User"); + safeStrCpy(buf, _("User"), sizeof(buf)/sizeof(buf[0]) ); } return buf; } @@ -8190,7 +8626,7 @@ HostName() if (!GetComputerName(buf, &bufsiz)) { /*DisplayError("Error getting host name", GetLastError());*/ - strcpy(buf, "Unknown"); + safeStrCpy(buf, _("Unknown"), sizeof(buf)/sizeof(buf[0]) ); } return buf; } @@ -8228,7 +8664,7 @@ DisplayWhiteClock(long timeRemaining, int highlight) hdc = GetDC(hwndMain); if (!IsIconic(hwndMain)) { DisplayAClock(hdc, timeRemaining, highlight, - flipClock ? &blackRect : &whiteRect, "White", flag); + flipClock ? &blackRect : &whiteRect, _("White"), flag); } if (highlight && iconCurrent == iconBlack) { iconCurrent = iconWhite; @@ -8252,7 +8688,7 @@ DisplayBlackClock(long timeRemaining, int highlight) hdc = GetDC(hwndMain); if (!IsIconic(hwndMain)) { DisplayAClock(hdc, timeRemaining, highlight, - flipClock ? &whiteRect : &blackRect, "Black", flag); + flipClock ? &whiteRect : &blackRect, _("Black"), flag); } if (highlight && iconCurrent == iconWhite) { iconCurrent = iconBlack; @@ -8300,7 +8736,7 @@ AutoSaveGame() f = OpenFileDialog(hwndMain, "a", defName, appData.oldSaveStyle ? "gam" : "pgn", GAME_FILT, - "Save Game to File", NULL, fileTitle, NULL); + _("Save Game to File"), NULL, fileTitle, NULL); if (f != NULL) { SaveGame(f, 0, ""); fclose(f); @@ -8604,9 +9040,9 @@ OpenTelnet(char *host, char *port, ProcRef *pr) char cmdLine[MSG_SIZ]; if (port[0] == NULLCHAR) { - sprintf(cmdLine, "%s %s", appData.telnetProgram, host); + snprintf(cmdLine, MSG_SIZ, "%s %s", appData.telnetProgram, host); } else { - sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port); + snprintf(cmdLine, MSG_SIZ, "%s %s %s", appData.telnetProgram, host, port); } return StartChildProcess(cmdLine, "", pr); } @@ -8705,9 +9141,9 @@ OpenCommPort(char *name, ProcRef *pr) char fullname[MSG_SIZ]; if (*name != '\\') - sprintf(fullname, "\\\\.\\%s", name); + snprintf(fullname, MSG_SIZ, "\\\\.\\%s", name); else - strcpy(fullname, name); + safeStrCpy(fullname, name, sizeof(fullname)/sizeof(fullname[0]) ); h = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); @@ -8739,7 +9175,7 @@ OpenCommPort(char *name, ProcRef *pr) int OpenLoopback(ProcRef *pr) { - DisplayFatalError("Not implemented", 0, 1); + DisplayFatalError(_("Not implemented"), 0, 1); return NO_ERROR; } @@ -8877,7 +9313,7 @@ OpenRcmd(char* host, char* user, char* cmd, ProcRef* pr) break; } prevStderrPort = fromPort; // remember port used - sprintf(stderrPortStr, "%d", fromPort); + snprintf(stderrPortStr, MSG_SIZ, "%d", fromPort); if (send(s, stderrPortStr, strlen(stderrPortStr) + 1, 0) == SOCKET_ERROR) { err = WSAGetLastError(); @@ -9109,7 +9545,7 @@ void CmailSigHandlerCallBack(InputSourceRef isr, VOIDSTAR closure, char *buf, int count, int error) { - DisplayFatalError("Not implemented", 0, 1); + DisplayFatalError(_("Not implemented"), 0, 1); } /* see wgamelist.c for Game List functions */ @@ -9197,26 +9633,26 @@ static void Tween( POINT * start, POINT * mid, POINT * finish, int factor, POINT frames[], int * nFrames); +#define kFactor 4 + void -AnimateAtomicCapture(int fromX, int fromY, int toX, int toY, int nFrames) +AnimateAtomicCapture(Board board, int fromX, int fromY, int toX, int toY) { // [HGM] atomic: animate blast wave int i; -if(appData.debugMode) fprintf(debugFP, "exploding (%d,%d)\n", toX, toY); + explodeInfo.fromX = fromX; explodeInfo.fromY = fromY; explodeInfo.toX = toX; explodeInfo.toY = toY; - for(i=1; i