+++ /dev/null
-/*\r
- * WinBoard.c -- Windows NT front end to XBoard\r
- *\r
- * Copyright 1991 by Digital Equipment Corporation, Maynard,\r
- * Massachusetts.\r
- *\r
- * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,\r
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Free\r
- * Software Foundation, Inc.\r
- *\r
- * Enhancements Copyright 2005 Alessandro Scotti\r
- *\r
- * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,\r
- * which was written and is copyrighted by Wayne Christopher.\r
- *\r
- * The following terms apply to Digital Equipment Corporation's copyright\r
- * interest in XBoard:\r
- * ------------------------------------------------------------------------\r
- * All Rights Reserved\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose and without fee is hereby granted,\r
- * provided that the above copyright notice appear in all copies and that\r
- * both that copyright notice and this permission notice appear in\r
- * supporting documentation, and that the name of Digital not be\r
- * used in advertising or publicity pertaining to distribution of the\r
- * software without specific, written prior permission.\r
- *\r
- * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\r
- * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\r
- * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\r
- * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\r
- * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\r
- * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\r
- * SOFTWARE.\r
- * ------------------------------------------------------------------------\r
- *\r
- * The following terms apply to the enhanced version of XBoard\r
- * distributed by the Free Software Foundation:\r
- * ------------------------------------------------------------------------\r
- *\r
- * GNU XBoard is free software: you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation, either version 3 of the License, or (at\r
- * your option) any later version.\r
- *\r
- * GNU XBoard is distributed in the hope that it will be useful, but\r
- * WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
- * General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program. If not, see http://www.gnu.org/licenses/. *\r
- *\r
- *------------------------------------------------------------------------\r
- ** See the file ChangeLog for a revision history. */\r
-\r
-#include "config.h"\r
-\r
-#include <windows.h>\r
-#include <winuser.h>\r
-#include <winsock.h>\r
-#include <commctrl.h>\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <time.h>\r
-#include <malloc.h>\r
-#include <sys/stat.h>\r
-#include <fcntl.h>\r
-#include <math.h>\r
-#include <commdlg.h>\r
-#include <dlgs.h>\r
-#include <richedit.h>\r
-#include <mmsystem.h>\r
-#include <ctype.h>\r
-#include <io.h>\r
-\r
-#if __GNUC__\r
-#include <errno.h>\r
-#include <string.h>\r
-#endif\r
-\r
-#include "common.h"\r
-#include "frontend.h"\r
-#include "backend.h"\r
-#include "winboard.h"\r
-#include "moves.h"\r
-#include "wclipbrd.h"\r
-#include "woptions.h"\r
-#include "wsockerr.h"\r
-#include "defaults.h"\r
-#include "help.h"\r
-#include "wsnap.h"\r
-\r
-#define SLASH '/'\r
-#define DATADIR "~~"\r
-\r
-//void InitEngineUCI( const char * iniDir, ChessProgramState * cps );\r
-\r
- int myrandom(void);\r
- void mysrandom(unsigned int seed);\r
-\r
-extern int whiteFlag, blackFlag;\r
-Boolean flipClock = FALSE;\r
-extern HANDLE chatHandle[];\r
-extern enum ICS_TYPE ics_type;\r
-\r
-int MySearchPath P((char *installDir, char *name, char *fullname));\r
-int MyGetFullPathName P((char *name, char *fullname));\r
-void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);\r
-VOID NewVariantPopup(HWND hwnd);\r
-int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,\r
- /*char*/int promoChar));\r
-void DisplayMove P((int moveNumber));\r
-void ChatPopUp P((char *s));\r
-typedef struct {\r
- ChessSquare piece; \r
- POINT pos; /* window coordinates of current pos */\r
- POINT lastpos; /* window coordinates of last pos - used for clipping */\r
- POINT from; /* board coordinates of the piece's orig pos */\r
- POINT to; /* board coordinates of the piece's new pos */\r
-} AnimInfo;\r
-\r
-static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };\r
-\r
-typedef struct {\r
- POINT start; /* window coordinates of start pos */\r
- POINT pos; /* window coordinates of current pos */\r
- POINT lastpos; /* window coordinates of last pos - used for clipping */\r
- POINT from; /* board coordinates of the piece's orig pos */\r
- ChessSquare piece;\r
-} DragInfo;\r
-\r
-static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, EmptySquare };\r
-\r
-typedef struct {\r
- POINT sq[2]; /* board coordinates of from, to squares */\r
-} HighlightInfo;\r
-\r
-static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} };\r
-static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };\r
-static HighlightInfo partnerHighlightInfo = { {{-1, -1}, {-1, -1}} };\r
-static HighlightInfo oldPartnerHighlight = { {{-1, -1}, {-1, -1}} };\r
-\r
-typedef struct { // [HGM] atomic\r
- int fromX, fromY, toX, toY, radius;\r
-} ExplodeInfo;\r
-\r
-static ExplodeInfo explodeInfo;\r
-\r
-/* Window class names */\r
-char szAppName[] = "WinBoard";\r
-char szConsoleName[] = "WBConsole";\r
-\r
-/* Title bar text */\r
-char szTitle[] = "WinBoard";\r
-char szConsoleTitle[] = "I C S Interaction";\r
-\r
-char *programName;\r
-char *settingsFileName;\r
-Boolean saveSettingsOnExit;\r
-char installDir[MSG_SIZ];\r
-int errorExitStatus;\r
-\r
-BoardSize boardSize;\r
-Boolean chessProgram;\r
-//static int boardX, boardY;\r
-int minX, minY; // [HGM] placement: volatile limits on upper-left corner\r
-int squareSize, lineGap, minorSize;\r
-static int winW, winH;\r
-static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo\r
-static int logoHeight = 0;\r
-static char messageText[MESSAGE_TEXT_MAX];\r
-static int clockTimerEvent = 0;\r
-static int loadGameTimerEvent = 0;\r
-static int analysisTimerEvent = 0;\r
-static DelayedEventCallback delayedTimerCallback;\r
-static int delayedTimerEvent = 0;\r
-static int buttonCount = 2;\r
-char *icsTextMenuString;\r
-char *icsNames;\r
-char *firstChessProgramNames;\r
-char *secondChessProgramNames;\r
-\r
-#define PALETTESIZE 256\r
-\r
-HINSTANCE hInst; /* current instance */\r
-Boolean alwaysOnTop = FALSE;\r
-RECT boardRect;\r
-COLORREF lightSquareColor, darkSquareColor, whitePieceColor, \r
- blackPieceColor, highlightSquareColor, premoveHighlightColor;\r
-COLORREF markerColor[8] = { 0x00FFFF, 0x0000FF, 0x00FF00, 0xFF0000, 0xFFFF00, 0xFF00FF, 0xFFFFFF, 0x000000 };\r
-HPALETTE hPal;\r
-ColorClass currentColorClass;\r
-\r
-static HWND savedHwnd;\r
-HWND hCommPort = NULL; /* currently open comm port */\r
-static HWND hwndPause; /* pause button */\r
-static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */\r
-static HBRUSH lightSquareBrush, darkSquareBrush,\r
- blackSquareBrush, /* [HGM] for band between board and holdings */\r
- explodeBrush, /* [HGM] atomic */\r
- markerBrush[8], /* [HGM] markers */\r
- whitePieceBrush, blackPieceBrush, iconBkgndBrush /*, outlineBrush*/;\r
-static POINT gridEndpoints[(BOARD_RANKS + BOARD_FILES + 2) * 2];\r
-static DWORD gridVertexCounts[BOARD_RANKS + BOARD_FILES + 2];\r
-static HPEN gridPen = NULL;\r
-static HPEN highlightPen = NULL;\r
-static HPEN premovePen = NULL;\r
-static NPLOGPALETTE pLogPal;\r
-static BOOL paletteChanged = FALSE;\r
-static HICON iconWhite, iconBlack, iconCurrent;\r
-static int doingSizing = FALSE;\r
-static int lastSizing = 0;\r
-static int prevStderrPort;\r
-static HBITMAP userLogo;\r
-\r
-static HBITMAP liteBackTexture = NULL;\r
-static HBITMAP darkBackTexture = NULL;\r
-static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;\r
-static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;\r
-static int backTextureSquareSize = 0;\r
-static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_RANKS][BOARD_FILES];\r
-\r
-#if __GNUC__ && !defined(_winmajor)\r
-#define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */\r
-#else\r
-\r
-#if defined(_winmajor)\r
-#define oldDialog (_winmajor < 4)\r
-#else\r
-#define oldDialog 0\r
-#endif\r
-#endif\r
-\r
-#define INTERNATIONAL\r
-\r
-#ifdef INTERNATIONAL\r
-# define _(s) T_(s)\r
-# define N_(s) s\r
-#else\r
-# define _(s) s\r
-# define N_(s) s\r
-# define T_(s) s\r
-# define Translate(x, y)\r
-# define LoadLanguageFile(s)\r
-#endif\r
-\r
-#ifdef INTERNATIONAL\r
-\r
-Boolean barbaric; // flag indicating if translation is needed\r
-\r
-// list of item numbers used in each dialog (used to alter language at run time)\r
-\r
-#define ABOUTBOX -1 /* not sure why these are needed */\r
-#define ABOUTBOX2 -1\r
-\r
-int dialogItems[][42] = {\r
-{ ABOUTBOX, IDOK, OPT_MESS, 400 }, \r
-{ DLG_TimeControl, IDC_Babble, OPT_TCUseMoves, OPT_TCUseInc, OPT_TCUseFixed, \r
- OPT_TCtext1, OPT_TCtext2, OPT_TCitext1, OPT_TCitext2, OPT_TCftext, GPB_Factors, IDC_Factor1, IDC_Factor2, IDOK, IDCANCEL }, \r
-{ DLG_LoadOptions, OPT_Autostep, OPT_AStext1, OPT_Exact, OPT_Subset, OPT_Struct, OPT_Material, OPT_Range, OPT_Difference,\r
- OPT_elo1t, OPT_elo2t, OPT_datet, OPT_Stretch, OPT_Stretcht, OPT_Reversed, OPT_SearchMode, OPT_Mirror, OPT_thresholds,\r
- OPT_Ranget, IDOK, IDCANCEL }, \r
-{ DLG_SaveOptions, OPT_Autosave, OPT_AVPrompt, OPT_AVToFile, OPT_AVBrowse,\r
- 801, OPT_PGN, OPT_Old, OPT_OutOfBookInfo, IDOK, IDCANCEL }, \r
-{ 1536, 1090, IDC_Directories, 1089, 1091, IDOK, IDCANCEL, 1038, IDC_IndexNr, 1037 }, \r
-{ DLG_CommPort, IDOK, IDCANCEL, IDC_Port, IDC_Rate, IDC_Bits, IDC_Parity,\r
- IDC_Stop, IDC_Flow, OPT_SerialHelp }, \r
-{ DLG_EditComment, IDOK, OPT_CancelComment, OPT_ClearComment, OPT_EditComment }, \r
-{ DLG_PromotionKing, PB_Chancellor, PB_Archbishop, PB_Queen, PB_Rook, \r
- PB_Bishop, PB_Knight, PB_King, IDCANCEL, IDC_Yes, IDC_No, IDC_Centaur }, \r
-{ ABOUTBOX2, IDC_ChessBoard }, \r
-{ DLG_GameList, OPT_GameListLoad, OPT_GameListPrev, OPT_GameListNext, \r
- OPT_GameListClose, IDC_GameListDoFilter }, \r
-{ DLG_EditTags, IDOK, OPT_TagsCancel, OPT_EditTags }, \r
-{ DLG_Error, IDOK }, \r
-{ DLG_Colorize, IDOK, IDCANCEL, OPT_ChooseColor, OPT_Bold, OPT_Italic,\r
- OPT_Underline, OPT_Strikeout, OPT_Sample }, \r
-{ DLG_Question, IDOK, IDCANCEL, OPT_QuestionText }, \r
-{ DLG_Startup, IDC_Welcome, OPT_ChessEngine, OPT_ChessServer, OPT_View,\r
- IDC_SPECIFY_ENG_STATIC, IDC_SPECIFY_SERVER_STATIC, OPT_AnyAdditional,\r
- IDOK, IDCANCEL, IDM_HELPCONTENTS }, \r
-{ DLG_IndexNumber, IDC_Index }, \r
-{ DLG_TypeInMove, IDOK, IDCANCEL }, \r
-{ DLG_TypeInName, IDOK, IDCANCEL }, \r
-{ DLG_Sound, IDC_Event, OPT_NoSound, OPT_DefaultBeep, OPT_BuiltInSound,\r
- OPT_WavFile, OPT_BrowseSound, OPT_DefaultSounds, IDOK, IDCANCEL, OPT_PlaySound }, \r
-{ DLG_GeneralOptions, IDOK, IDCANCEL, OPT_AlwaysOnTop, OPT_HighlightLastMove,\r
- OPT_AlwaysQueen, OPT_PeriodicUpdates, OPT_AnimateDragging, OPT_PonderNextMove,\r
- OPT_AnimateMoving, OPT_PopupExitMessage, OPT_AutoFlag, OPT_PopupMoveErrors,\r
- OPT_AutoFlipView, OPT_ShowButtonBar, OPT_AutoRaiseBoard, OPT_ShowCoordinates,\r
- OPT_Blindfold, OPT_ShowThinking, OPT_HighlightDragging, OPT_TestLegality,\r
- OPT_SaveExtPGN, OPT_HideThinkFromHuman, OPT_ExtraInfoInMoveHistory,\r
- OPT_HighlightMoveArrow, OPT_AutoLogo ,OPT_SmartMove }, \r
-{ DLG_IcsOptions, IDOK, IDCANCEL, OPT_AutoComment, OPT_AutoKibitz, OPT_AutoObserve,\r
- OPT_GetMoveList, OPT_LocalLineEditing, OPT_QuietPlay, OPT_SeekGraph, OPT_AutoRefresh,\r
- OPT_BgObserve, OPT_DualBoard, OPT_Premove, OPT_PremoveWhite, OPT_PremoveBlack,\r
- OPT_SmartMove, OPT_IcsAlarm, IDC_Sec, OPT_ChooseShoutColor, OPT_ChooseSShoutColor,\r
- OPT_ChooseChannel1Color, OPT_ChooseChannelColor, OPT_ChooseKibitzColor,\r
- OPT_ChooseTellColor, OPT_ChooseChallengeColor, OPT_ChooseRequestColor,\r
- OPT_ChooseSeekColor, OPT_ChooseNormalColor, OPT_ChooseBackgroundColor,\r
- OPT_DefaultColors, OPT_DontColorize, IDC_Boxes, GPB_Colors, GPB_Premove,\r
- GPB_General, GPB_Alarm, OPT_AutoCreate }, \r
-{ DLG_BoardOptions, IDOK, IDCANCEL, OPT_SizeTiny, OPT_SizeTeeny, OPT_SizeDinky,\r
- OPT_SizePetite, OPT_SizeSlim, OPT_SizeSmall, OPT_SizeMediocre, OPT_SizeMiddling,\r
- OPT_SizeAverage, OPT_SizeModerate, OPT_SizeMedium, OPT_SizeBulky, OPT_SizeLarge,\r
- OPT_SizeBig, OPT_SizeHuge, OPT_SizeGiant, OPT_SizeColossal, OPT_SizeTitanic,\r
- OPT_ChooseLightSquareColor, OPT_ChooseDarkSquareColor, OPT_ChooseWhitePieceColor,\r
- OPT_ChooseBlackPieceColor, OPT_ChooseHighlightSquareColor, OPT_ChoosePremoveHighlightColor,\r
- OPT_Monochrome, OPT_AllWhite, OPT_UpsideDown, OPT_DefaultBoardColors, GPB_Colors,\r
- IDC_Light, IDC_Dark, IDC_White, IDC_Black, IDC_High, IDC_PreHigh, GPB_Size, OPT_Bitmaps, OPT_PieceFont, OPT_Grid }, \r
-{ DLG_NewVariant, IDOK, IDCANCEL, OPT_VariantNormal, OPT_VariantFRC, OPT_VariantWildcastle,\r
- OPT_VariantNocastle, OPT_VariantLosers, OPT_VariantGiveaway, OPT_VariantSuicide,\r
- OPT_Variant3Check, OPT_VariantTwoKings, OPT_VariantAtomic, OPT_VariantCrazyhouse,\r
- OPT_VariantBughouse, OPT_VariantTwilight, OPT_VariantShogi, OPT_VariantSuper,\r
- OPT_VariantKnightmate, OPT_VariantBerolina, OPT_VariantCylinder, OPT_VariantFairy,\r
- OPT_VariantMakruk, OPT_VariantGothic, OPT_VariantCapablanca, OPT_VariantJanus,\r
- OPT_VariantCRC, OPT_VariantFalcon, OPT_VariantCourier, OPT_VariantGreat, OPT_VariantSChess,\r
- OPT_VariantShatranj, OPT_VariantXiangqi, GPB_Variant, GPB_Board, IDC_Height,\r
- IDC_Width, IDC_Hand, IDC_Pieces, IDC_Def }, \r
-{ DLG_Fonts, IDOK, IDCANCEL, OPT_ChooseClockFont, OPT_ChooseMessageFont,\r
- OPT_ChooseCoordFont, OPT_ChooseTagFont, OPT_ChooseCommentsFont, OPT_ChooseConsoleFont, OPT_ChooseMoveHistoryFont, OPT_DefaultFonts,\r
- OPT_ClockFont, OPT_MessageFont, OPT_CoordFont, OPT_EditTagsFont, OPT_ChoosePieceFont, OPT_MessageFont8,\r
- OPT_SampleGameListFont, OPT_ChooseGameListFont, OPT_MessageFont7, \r
- OPT_CommentsFont, OPT_MessageFont5, GPB_Current, GPB_All, OPT_MessageFont6 }, \r
-{ DLG_NewGameFRC, IDC_NFG_Label, IDC_NFG_Random, IDOK, IDCANCEL }, \r
-{ DLG_GameListOptions, IDC_GLT, IDC_GLT_Up, IDC_GLT_Down, IDC_GLT_Restore,\r
- IDC_GLT_Default, IDOK, IDCANCEL, IDC_GLT_RestoreTo }, \r
-{ DLG_MoveHistory }, \r
-{ DLG_EvalGraph }, \r
-{ DLG_EngineOutput, IDC_EngineLabel1, IDC_Engine1_NPS, IDC_EngineLabel2, IDC_Engine2_NPS }, \r
-{ DLG_Chat, IDC_Partner, IDC_Clear, IDC_Send, }, \r
-{ DLG_EnginePlayOptions, IDC_EpPonder, IDC_EpShowThinking, IDC_EpHideThinkingHuman,\r
- IDC_EpPeriodicUpdates, GPB_Adjudications, IDC_Draw, IDC_Moves, IDC_Threshold,\r
- IDC_Centi, IDC_TestClaims, IDC_DetectMates, IDC_MaterialDraws, IDC_TrivialDraws,\r
- GPB_Apply, IDC_Rule, IDC_Repeats, IDC_ScoreAbs1, IDC_ScoreAbs2, IDOK, IDCANCEL }, \r
-{ DLG_OptionsUCI, IDC_PolyDir, IDC_BrowseForPolyglotDir, IDC_Hash, IDC_Path,\r
- IDC_BrowseForEGTB, IDC_Cache, IDC_UseBook, IDC_BrowseForBook, IDC_CPU, IDC_OwnBook1,\r
- IDC_OwnBook2, IDC_Depth, IDC_Variation, IDC_DefGames, IDOK, IDCANCEL },\r
-{ 0 }\r
-};\r
-\r
-static char languageBuf[70000], *foreign[1000], *english[1000], *languageFile[MSG_SIZ];\r
-static int lastChecked;\r
-static char oldLanguage[MSG_SIZ], *menuText[10][30];\r
-extern int tinyLayout;\r
-extern char * menuBarText[][10];\r
-\r
-void\r
-LoadLanguageFile(char *name)\r
-{ //load the file with translations, and make a list of the strings to be translated, and their translations\r
- FILE *f;\r
- int i=0, j=0, n=0, k;\r
- char buf[MSG_SIZ];\r
-\r
- if(!name || name[0] == NULLCHAR) return;\r
- snprintf(buf, MSG_SIZ, "%s%s", name, strchr(name, '.') ? "" : ".lng"); // auto-append lng extension\r
- appData.language = oldLanguage;\r
- if(!strcmp(buf, oldLanguage)) { barbaric = 1; return; } // this language already loaded; just switch on\r
- if((f = fopen(buf, "r")) == NULL) return;\r
- while((k = fgetc(f)) != EOF) {\r
- if(i >= sizeof(languageBuf)) { DisplayError("Language file too big", 0); return; }\r
- languageBuf[i] = k;\r
- if(k == '\n') {\r
- if(languageBuf[n] == '"' && languageBuf[i-1] == '"') {\r
- char *p;\r
- if(p = strstr(languageBuf + n + 1, "\" === \"")) {\r
- if(p > languageBuf+n+2 && p+8 < languageBuf+i) {\r
- if(j >= sizeof(english)) { DisplayError("Too many translated strings", 0); return; }\r
- english[j] = languageBuf + n + 1; *p = 0;\r
- foreign[j++] = p + 7; languageBuf[i-1] = 0;\r
-//if(appData.debugMode) fprintf(debugFP, "translation: replace '%s' by '%s'\n", english[j-1], foreign[j-1]);\r
- }\r
- }\r
- }\r
- n = i + 1;\r
- } else if(i > 0 && languageBuf[i-1] == '\\') {\r
- switch(k) {\r
- case 'n': k = '\n'; break;\r
- case 'r': k = '\r'; break;\r
- case 't': k = '\t'; break;\r
- }\r
- languageBuf[--i] = k;\r
- }\r
- i++;\r
- }\r
- fclose(f);\r
- barbaric = (j != 0);\r
- safeStrCpy(oldLanguage, buf, sizeof(oldLanguage)/sizeof(oldLanguage[0]) );\r
-}\r
-\r
-char *\r
-T_(char *s)\r
-{ // return the translation of the given string\r
- // efficiency can be improved a lot...\r
- int i=0;\r
- static char buf[MSG_SIZ];\r
-//if(appData.debugMode) fprintf(debugFP, "T_(%s)\n", s);\r
- if(!barbaric) return s;\r
- if(!s) return ""; // sanity\r
- while(english[i]) {\r
- if(!strcmp(s, english[i])) return foreign[i];\r
- if(english[i][0] == '%' && strstr(s, english[i]+1) == s) { // allow translation of strings with variable ending\r
- snprintf(buf, MSG_SIZ, "%s%s", foreign[i], s + strlen(english[i]+1)); // keep unmatched portion\r
- return buf;\r
- }\r
- i++;\r
- }\r
- return s;\r
-}\r
-\r
-void\r
-Translate(HWND hDlg, int dialogID)\r
-{ // translate all text items in the given dialog\r
- int i=0, j, k;\r
- char buf[MSG_SIZ], *s;\r
- if(!barbaric) return;\r
- while(dialogItems[i][0] && dialogItems[i][0] != dialogID) i++; // find the dialog description\r
- if(dialogItems[i][0] != dialogID) return; // unknown dialog, should not happen\r
- GetWindowText( hDlg, buf, MSG_SIZ );\r
- s = T_(buf);\r
- if(strcmp(buf, s)) SetWindowText(hDlg, s); // replace by translated string (if different)\r
- for(j=1; k=dialogItems[i][j]; j++) { // translate all listed dialog items\r
- GetDlgItemText(hDlg, k, buf, MSG_SIZ);\r
- if(strlen(buf) == 0) continue;\r
- s = T_(buf);\r
- if(strcmp(buf, s)) SetDlgItemText(hDlg, k, s); // replace by translated string (if different)\r
- }\r
-}\r
-\r
-HMENU\r
-TranslateOneMenu(int i, HMENU subMenu)\r
-{\r
- int j;\r
- static MENUITEMINFO info;\r
-\r
- info.cbSize = sizeof(MENUITEMINFO);\r
- info.fMask = MIIM_STATE | MIIM_TYPE;\r
- for(j=GetMenuItemCount(subMenu)-1; j>=0; j--){\r
- char buf[MSG_SIZ];\r
- info.dwTypeData = buf;\r
- info.cch = sizeof(buf);\r
- GetMenuItemInfo(subMenu, j, TRUE, &info);\r
- if(i < 10) {\r
- if(menuText[i][j]) safeStrCpy(buf, menuText[i][j], sizeof(buf)/sizeof(buf[0]) );\r
- else menuText[i][j] = strdup(buf); // remember original on first change\r
- }\r
- if(buf[0] == NULLCHAR) continue;\r
- info.dwTypeData = T_(buf);\r
- info.cch = strlen(buf)+1;\r
- SetMenuItemInfo(subMenu, j, TRUE, &info);\r
- }\r
- return subMenu;\r
-}\r
-\r
-void\r
-TranslateMenus(int addLanguage)\r
-{\r
- int i;\r
- WIN32_FIND_DATA fileData;\r
- HANDLE hFind;\r
-#define IDM_English 1970\r
- if(1) {\r
- HMENU mainMenu = GetMenu(hwndMain);\r
- for (i=GetMenuItemCount(mainMenu)-1; i>=0; i--) {\r
- HMENU subMenu = GetSubMenu(mainMenu, i);\r
- ModifyMenu(mainMenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP|EnableMenuItem(mainMenu, i, MF_BYPOSITION),\r
- (UINT) subMenu, T_(menuBarText[tinyLayout][i]));\r
- TranslateOneMenu(i, subMenu);\r
- }\r
- DrawMenuBar(hwndMain);\r
- }\r
-\r
- if(!addLanguage) return;\r
- if((hFind = FindFirstFile("*.LNG", &fileData)) != INVALID_HANDLE_VALUE) {\r
- HMENU mainMenu = GetMenu(hwndMain);\r
- HMENU subMenu = GetSubMenu(mainMenu, GetMenuItemCount(mainMenu)-1);\r
- AppendMenu(subMenu, MF_SEPARATOR, (UINT_PTR) 0, NULL);\r
- AppendMenu(subMenu, MF_ENABLED|MF_STRING|(barbaric?MF_UNCHECKED:MF_CHECKED), (UINT_PTR) IDM_English, (LPCTSTR) "English");\r
- i = 0; lastChecked = IDM_English;\r
- do {\r
- char *p, *q = fileData.cFileName;\r
- int checkFlag = MF_UNCHECKED;\r
- languageFile[i] = strdup(q);\r
- if(barbaric && !strcmp(oldLanguage, q)) {\r
- checkFlag = MF_CHECKED;\r
- lastChecked = IDM_English + i + 1;\r
- CheckMenuItem(mainMenu, IDM_English, MF_BYCOMMAND|MF_UNCHECKED);\r
- }\r
- *q = ToUpper(*q); while(*++q) *q = ToLower(*q);\r
- p = strstr(fileData.cFileName, ".lng");\r
- if(p) *p = 0;\r
- AppendMenu(subMenu, MF_ENABLED|MF_STRING|checkFlag, (UINT_PTR) IDM_English + ++i, (LPCTSTR) fileData.cFileName);\r
- } while(FindNextFile(hFind, &fileData));\r
- FindClose(hFind);\r
- }\r
-}\r
-\r
-#endif\r
-\r
-#define IDM_RecentEngines 3000\r
-\r
-void\r
-RecentEngineMenu (char *s)\r
-{\r
- if(appData.icsActive) return;\r
- if(appData.recentEngines > 0 && *s) { // feature is on, and list non-empty\r
- HMENU mainMenu = GetMenu(hwndMain);\r
- HMENU subMenu = GetSubMenu(mainMenu, 5); // Engine menu\r
- int i=IDM_RecentEngines;\r
- recentEngines = strdup(appData.recentEngineList); // remember them as they are in menu\r
- AppendMenu(subMenu, MF_SEPARATOR, (UINT_PTR) 0, NULL);\r
- while(*s) {\r
- char *p = strchr(s, '\n');\r
- if(p == NULL) return; // malformed!\r
- *p = NULLCHAR;\r
- AppendMenu(subMenu, MF_ENABLED|MF_STRING|MF_UNCHECKED, (UINT_PTR) i++, (LPCTSTR) s);\r
- *p = '\n';\r
- s = p+1;\r
- }\r
- }\r
-}\r
-\r
-\r
-typedef struct {\r
- char *name;\r
- int squareSize;\r
- int lineGap;\r
- int smallLayout;\r
- int tinyLayout;\r
- int cliWidth, cliHeight;\r
-} SizeInfo;\r
-\r
-SizeInfo sizeInfo[] = \r
-{\r
- { "tiny", 21, 0, 1, 2, 0, 0 },\r
- { "teeny", 25, 1, 1, 2, 0, 0 },\r
- { "dinky", 29, 1, 1, 2, 0, 0 },\r
- { "petite", 33, 1, 1, 2, 0, 0 },\r
- { "slim", 37, 2, 1, 1, 0, 0 },\r
- { "small", 40, 2, 1, 1, 0, 0 },\r
- { "mediocre", 45, 2, 1, 0, 0, 0 },\r
- { "middling", 49, 2, 0, 0, 0, 0 },\r
- { "average", 54, 2, 0, 0, 0, 0 },\r
- { "moderate", 58, 3, 0, 0, 0, 0 },\r
- { "medium", 64, 3, 0, 0, 0, 0 },\r
- { "bulky", 72, 3, 0, 0, 0, 0 },\r
- { "large", 80, 3, 0, 0, 0, 0 },\r
- { "big", 87, 3, 0, 0, 0, 0 },\r
- { "huge", 95, 3, 0, 0, 0, 0 },\r
- { "giant", 108, 3, 0, 0, 0, 0 },\r
- { "colossal", 116, 4, 0, 0, 0, 0 },\r
- { "titanic", 129, 4, 0, 0, 0, 0 },\r
- { NULL, 0, 0, 0, 0, 0, 0 }\r
-};\r
-\r
-#define MF(x) {x, {{0,}, 0. }, {0, }, 0}\r
-MyFont fontRec[NUM_SIZES][NUM_FONTS] =\r
-{\r
- { MF(CLOCK_FONT_TINY), MF(MESSAGE_FONT_TINY), MF(COORD_FONT_TINY), MF(CONSOLE_FONT_TINY), MF(COMMENT_FONT_TINY), MF(EDITTAGS_FONT_TINY), MF(MOVEHISTORY_FONT_ALL), MF(GAMELIST_FONT_ALL) },\r
- { MF(CLOCK_FONT_TEENY), MF(MESSAGE_FONT_TEENY), MF(COORD_FONT_TEENY), MF(CONSOLE_FONT_TEENY), MF(COMMENT_FONT_TEENY), MF(EDITTAGS_FONT_TEENY), MF(MOVEHISTORY_FONT_ALL), MF(GAMELIST_FONT_ALL) },\r
- { MF(CLOCK_FONT_DINKY), MF(MESSAGE_FONT_DINKY), MF(COORD_FONT_DINKY), MF(CONSOLE_FONT_DINKY), MF(COMMENT_FONT_DINKY), MF(EDITTAGS_FONT_DINKY), MF(MOVEHISTORY_FONT_ALL), MF(GAMELIST_FONT_ALL) },\r
- { MF(CLOCK_FONT_PETITE), MF(MESSAGE_FONT_PETITE), MF(COORD_FONT_PETITE), MF(CONSOLE_FONT_PETITE), MF(COMMENT_FONT_PETITE), MF(EDITTAGS_FONT_PETITE), MF(MOVEHISTORY_FONT_ALL), MF(GAMELIST_FONT_ALL) },\r
- { MF(CLOCK_FONT_SLIM), MF(MESSAGE_FONT_SLIM), MF(COORD_FONT_SLIM), MF(CONSOLE_FONT_SLIM), MF(COMMENT_FONT_SLIM), MF(EDITTAGS_FONT_SLIM), MF(MOVEHISTORY_FONT_ALL), MF(GAMELIST_FONT_ALL) },\r
- { MF(CLOCK_FONT_SMALL), MF(MESSAGE_FONT_SMALL), MF(COORD_FONT_SMALL), MF(CONSOLE_FONT_SMALL), MF(COMMENT_FONT_SMALL), MF(EDITTAGS_FONT_SMALL), MF(MOVEHISTORY_FONT_ALL), MF(GAMELIST_FONT_ALL) },\r
- { MF(CLOCK_FONT_MEDIOCRE), MF(MESSAGE_FONT_MEDIOCRE), MF(COORD_FONT_MEDIOCRE), MF(CONSOLE_FONT_MEDIOCRE), MF(COMMENT_FONT_MEDIOCRE), MF(EDITTAGS_FONT_MEDIOCRE), MF(MOVEHISTORY_FONT_ALL), MF(GAMELIST_FONT_ALL) },\r
- { MF(CLOCK_FONT_MIDDLING), MF(MESSAGE_FONT_MIDDLING), MF(COORD_FONT_MIDDLING), MF(CONSOLE_FONT_MIDDLING), MF(COMMENT_FONT_MIDDLING), MF(EDITTAGS_FONT_MIDDLING), MF(MOVEHISTORY_FONT_ALL), MF(GAMELIST_FONT_ALL) },\r
- { MF(CLOCK_FONT_AVERAGE), MF(MESSAGE_FONT_AVERAGE), MF(COORD_FONT_AVERAGE), MF(CONSOLE_FONT_AVERAGE), MF(COMMENT_FONT_AVERAGE), MF(EDITTAGS_FONT_AVERAGE), MF(MOVEHISTORY_FONT_ALL), MF(GAMELIST_FONT_ALL) },\r
- { MF(CLOCK_FONT_MODERATE), MF(MESSAGE_FONT_MODERATE), MF(COORD_FONT_MODERATE), MF(CONSOLE_FONT_MODERATE), MF(COMMENT_FONT_MODERATE), MF(EDITTAGS_FONT_MODERATE), MF(MOVEHISTORY_FONT_ALL), MF(GAMELIST_FONT_ALL) },\r
- { MF(CLOCK_FONT_MEDIUM), MF(MESSAGE_FONT_MEDIUM), MF(COORD_FONT_MEDIUM), MF(CONSOLE_FONT_MEDIUM), MF(COMMENT_FONT_MEDIUM), MF(EDITTAGS_FONT_MEDIUM), MF(MOVEHISTORY_FONT_ALL), MF(GAMELIST_FONT_ALL) },\r
- { MF(CLOCK_FONT_BULKY), MF(MESSAGE_FONT_BULKY), MF(COORD_FONT_BULKY), MF(CONSOLE_FONT_BULKY), MF(COMMENT_FONT_BULKY), MF(EDITTAGS_FONT_BULKY), MF(MOVEHISTORY_FONT_ALL), MF(GAMELIST_FONT_ALL) },\r
- { MF(CLOCK_FONT_LARGE), MF(MESSAGE_FONT_LARGE), MF(COORD_FONT_LARGE), MF(CONSOLE_FONT_LARGE), MF(COMMENT_FONT_LARGE), MF(EDITTAGS_FONT_LARGE), MF(MOVEHISTORY_FONT_ALL), MF(GAMELIST_FONT_ALL) },\r
- { MF(CLOCK_FONT_BIG), MF(MESSAGE_FONT_BIG), MF(COORD_FONT_BIG), MF(CONSOLE_FONT_BIG), MF(COMMENT_FONT_BIG), MF(EDITTAGS_FONT_BIG), MF(MOVEHISTORY_FONT_ALL), MF(GAMELIST_FONT_ALL) },\r
- { MF(CLOCK_FONT_HUGE), MF(MESSAGE_FONT_HUGE), MF(COORD_FONT_HUGE), MF(CONSOLE_FONT_HUGE), MF(COMMENT_FONT_HUGE), MF(EDITTAGS_FONT_HUGE), MF(MOVEHISTORY_FONT_ALL), MF(GAMELIST_FONT_ALL) },\r
- { MF(CLOCK_FONT_GIANT), MF(MESSAGE_FONT_GIANT), MF(COORD_FONT_GIANT), MF(CONSOLE_FONT_GIANT), MF(COMMENT_FONT_GIANT), MF(EDITTAGS_FONT_GIANT), MF(MOVEHISTORY_FONT_ALL), MF(GAMELIST_FONT_ALL) },\r
- { MF(CLOCK_FONT_COLOSSAL), MF(MESSAGE_FONT_COLOSSAL), MF(COORD_FONT_COLOSSAL), MF(CONSOLE_FONT_COLOSSAL), MF(COMMENT_FONT_COLOSSAL), MF(EDITTAGS_FONT_COLOSSAL), MF(MOVEHISTORY_FONT_ALL), MF (GAMELIST_FONT_ALL) },\r
- { MF(CLOCK_FONT_TITANIC), MF(MESSAGE_FONT_TITANIC), MF(COORD_FONT_TITANIC), MF(CONSOLE_FONT_TITANIC), MF(COMMENT_FONT_TITANIC), MF(EDITTAGS_FONT_TITANIC), MF(MOVEHISTORY_FONT_ALL), MF(GAMELIST_FONT_ALL) },\r
-};\r
-\r
-MyFont *font[NUM_SIZES][NUM_FONTS];\r
-\r
-typedef struct {\r
- char *label;\r
- int id;\r
- HWND hwnd;\r
- WNDPROC wndproc;\r
-} MyButtonDesc;\r
-\r
-#define BUTTON_WIDTH (tinyLayout == 2 ? 16 : 32)\r
-#define N_BUTTONS 5\r
-\r
-MyButtonDesc buttonDesc[N_BUTTONS] =\r
-{\r
- {"<<", IDM_ToStart, NULL, NULL},\r
- {"<", IDM_Backward, NULL, NULL},\r
- {"P", IDM_Pause, NULL, NULL},\r
- {">", IDM_Forward, NULL, NULL},\r
- {">>", IDM_ToEnd, NULL, NULL},\r
-};\r
-\r
-int tinyLayout = 0, smallLayout = 0;\r
-#define MENU_BAR_ITEMS 9\r
-char *menuBarText[3][MENU_BAR_ITEMS+1] = {\r
- { N_("&File"), N_("&Edit"), N_("&View"), N_("&Mode"), N_("&Action"), N_("E&ngine"), N_("&Options"), N_("&Help"), NULL },\r
- { N_("&Fil"), N_("&Ed"), N_("&Vw"), N_("&Mod"), N_("&Act"), N_("E&ng"), N_("&Opt"), N_("&Hlp"), NULL },\r
- { N_("&F"), N_("&E"), N_("&V"), N_("&M"), N_("&A"), N_("&N"), N_("&O"), N_("&H"), NULL },\r
-};\r
-\r
-\r
-MySound sounds[(int)NSoundClasses];\r
-MyTextAttribs textAttribs[(int)NColorClasses];\r
-\r
-MyColorizeAttribs colorizeAttribs[] = {\r
- { (COLORREF)0, 0, N_("Shout Text") },\r
- { (COLORREF)0, 0, N_("SShout/CShout") },\r
- { (COLORREF)0, 0, N_("Channel 1 Text") },\r
- { (COLORREF)0, 0, N_("Channel Text") },\r
- { (COLORREF)0, 0, N_("Kibitz Text") },\r
- { (COLORREF)0, 0, N_("Tell Text") },\r
- { (COLORREF)0, 0, N_("Challenge Text") },\r
- { (COLORREF)0, 0, N_("Request Text") },\r
- { (COLORREF)0, 0, N_("Seek Text") },\r
- { (COLORREF)0, 0, N_("Normal Text") },\r
- { (COLORREF)0, 0, N_("None") }\r
-};\r
-\r
-\r
-\r
-static char *commentTitle;\r
-static char *commentText;\r
-static int commentIndex;\r
-static Boolean editComment = FALSE;\r
-\r
-\r
-char errorTitle[MSG_SIZ];\r
-char errorMessage[2*MSG_SIZ];\r
-HWND errorDialog = NULL;\r
-BOOLEAN moveErrorMessageUp = FALSE;\r
-BOOLEAN consoleEcho = TRUE;\r
-CHARFORMAT consoleCF;\r
-COLORREF consoleBackgroundColor;\r
-\r
-char *programVersion;\r
-\r
-#define CPReal 1\r
-#define CPComm 2\r
-#define CPSock 3\r
-#define CPRcmd 4\r
-typedef int CPKind;\r
-\r
-typedef struct {\r
- CPKind kind;\r
- HANDLE hProcess;\r
- DWORD pid;\r
- HANDLE hTo;\r
- HANDLE hFrom;\r
- SOCKET sock;\r
- SOCKET sock2; /* stderr socket for OpenRcmd */\r
-} ChildProc;\r
-\r
-#define INPUT_SOURCE_BUF_SIZE 4096\r
-\r
-typedef struct _InputSource {\r
- CPKind kind;\r
- HANDLE hFile;\r
- SOCKET sock;\r
- int lineByLine;\r
- HANDLE hThread;\r
- DWORD id;\r
- char buf[INPUT_SOURCE_BUF_SIZE];\r
- char *next;\r
- DWORD count;\r
- int error;\r
- InputCallback func;\r
- struct _InputSource *second; /* for stderr thread on CPRcmd */\r
- VOIDSTAR closure;\r
-} InputSource;\r
-\r
-InputSource *consoleInputSource;\r
-\r
-DCB dcb;\r
-\r
-/* forward */\r
-VOID ConsoleOutput(char* data, int length, int forceVisible);\r
-VOID ConsoleCreate();\r
-LRESULT CALLBACK\r
- ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);\r
-VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);\r
-VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);\r
-VOID ParseCommSettings(char *arg, DCB *dcb);\r
-LRESULT CALLBACK\r
- StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);\r
-VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);\r
-void ParseIcsTextMenu(char *icsTextMenuString);\r
-VOID PopUpNameDialog(char firstchar);\r
-VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);\r
-\r
-/* [AS] */\r
-int NewGameFRC();\r
-int GameListOptions();\r
-\r
-int dummy; // [HGM] for obsolete args\r
-\r
-HWND hwndMain = NULL; /* root window*/\r
-HWND hwndConsole = NULL;\r
-HWND commentDialog = NULL;\r
-HWND moveHistoryDialog = NULL;\r
-HWND evalGraphDialog = NULL;\r
-HWND engineOutputDialog = NULL;\r
-HWND gameListDialog = NULL;\r
-HWND editTagsDialog = NULL;\r
-\r
-int commentUp = FALSE;\r
-\r
-WindowPlacement wpMain;\r
-WindowPlacement wpConsole;\r
-WindowPlacement wpComment;\r
-WindowPlacement wpMoveHistory;\r
-WindowPlacement wpEvalGraph;\r
-WindowPlacement wpEngineOutput;\r
-WindowPlacement wpGameList;\r
-WindowPlacement wpTags;\r
-\r
-VOID EngineOptionsPopup(); // [HGM] settings\r
-\r
-VOID GothicPopUp(char *title, VariantClass variant);\r
-/*\r
- * Setting "frozen" should disable all user input other than deleting\r
- * the window. We do this while engines are initializing themselves.\r
- */\r
-static int frozen = 0;\r
-static int oldMenuItemState[MENU_BAR_ITEMS];\r
-void FreezeUI()\r
-{\r
- HMENU hmenu;\r
- int i;\r
-\r
- if (frozen) return;\r
- frozen = 1;\r
- hmenu = GetMenu(hwndMain);\r
- for (i=0; i<MENU_BAR_ITEMS; i++) {\r
- oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);\r
- }\r
- DrawMenuBar(hwndMain);\r
-}\r
-\r
-/* Undo a FreezeUI */\r
-void ThawUI()\r
-{\r
- HMENU hmenu;\r
- int i;\r
-\r
- if (!frozen) return;\r
- frozen = 0;\r
- hmenu = GetMenu(hwndMain);\r
- for (i=0; i<MENU_BAR_ITEMS; i++) {\r
- EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);\r
- }\r
- DrawMenuBar(hwndMain);\r
-}\r
-\r
-/*static*/ int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them\r
-\r
-/* JAWS preparation patch (WinBoard for the sight impaired). Define required insertions as empty */\r
-#ifdef JAWS\r
-#include "jaws.c"\r
-#else\r
-#define JAWS_INIT\r
-#define JAWS_ARGS\r
-#define JAWS_ALT_INTERCEPT\r
-#define JAWS_KBUP_NAVIGATION\r
-#define JAWS_KBDOWN_NAVIGATION\r
-#define JAWS_MENU_ITEMS\r
-#define JAWS_SILENCE\r
-#define JAWS_REPLAY\r
-#define JAWS_ACCEL\r
-#define JAWS_COPYRIGHT\r
-#define JAWS_DELETE(X) X\r
-#define SAYMACHINEMOVE()\r
-#define SAY(X)\r
-#endif\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * WinMain\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-static void HandleMessage P((MSG *message));\r
-static HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;\r
-\r
-int APIENTRY\r
-WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,\r
- LPSTR lpCmdLine, int nCmdShow)\r
-{\r
- MSG msg;\r
-// INITCOMMONCONTROLSEX ex;\r
-\r
- debugFP = stderr;\r
-\r
- LoadLibrary("RICHED32.DLL");\r
- consoleCF.cbSize = sizeof(CHARFORMAT);\r
-\r
- if (!InitApplication(hInstance)) {\r
- return (FALSE);\r
- }\r
- if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {\r
- return (FALSE);\r
- }\r
-\r
- JAWS_INIT\r
- TranslateMenus(1);\r
-\r
-// InitCommonControlsEx(&ex);\r
- InitCommonControls();\r
-\r
- hAccelMain = LoadAccelerators (hInstance, szAppName);\r
- hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");\r
- hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */\r
-\r
- /* Acquire and dispatch messages until a WM_QUIT message is received. */\r
-\r
- while (GetMessage(&msg, /* message structure */\r
- NULL, /* handle of window receiving the message */\r
- 0, /* lowest message to examine */\r
- 0)) /* highest message to examine */\r
- {\r
- HandleMessage(&msg);\r
- }\r
-\r
-\r
- return (msg.wParam); /* Returns the value from PostQuitMessage */\r
-}\r
-\r
-static void\r
-HandleMessage (MSG *message)\r
-{\r
- MSG msg = *message;\r
-\r
- if(msg.message == WM_CHAR && msg.wParam == '\t') {\r
- // [HGM] navigate: switch between all windows with tab\r
- HWND e1 = NULL, e2 = NULL, mh = NULL, hInput = NULL, hText = NULL;\r
- int i, currentElement = 0;\r
-\r
- // first determine what element of the chain we come from (if any)\r
- if(appData.icsActive) {\r
- hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- hText = GetDlgItem(hwndConsole, OPT_ConsoleText);\r
- }\r
- if(engineOutputDialog && EngineOutputIsUp()) {\r
- e1 = GetDlgItem(engineOutputDialog, IDC_EngineMemo1);\r
- e2 = GetDlgItem(engineOutputDialog, IDC_EngineMemo2);\r
- }\r
- if(moveHistoryDialog && MoveHistoryIsUp()) {\r
- mh = GetDlgItem(moveHistoryDialog, IDC_MoveHistory);\r
- }\r
- if(msg.hwnd == hwndMain) currentElement = 7 ; else\r
- if(msg.hwnd == engineOutputDialog) currentElement = 2; else\r
- if(msg.hwnd == e1) currentElement = 2; else\r
- if(msg.hwnd == e2) currentElement = 3; else\r
- if(msg.hwnd == moveHistoryDialog) currentElement = 4; else\r
- if(msg.hwnd == mh) currentElement = 4; else\r
- if(msg.hwnd == evalGraphDialog) currentElement = 6; else\r
- if(msg.hwnd == hText) currentElement = 5; else\r
- if(msg.hwnd == hInput) currentElement = 6; else\r
- for (i = 0; i < N_BUTTONS; i++) {\r
- if (buttonDesc[i].hwnd == msg.hwnd) { currentElement = 1; break; }\r
- }\r
-\r
- // determine where to go to\r
- if(currentElement) { HWND h = NULL; int direction = GetKeyState(VK_SHIFT) < 0 ? -1 : 1;\r
- do {\r
- currentElement = (currentElement + direction) % 7;\r
- switch(currentElement) {\r
- case 0:\r
- h = hwndMain; break; // passing this case always makes the loop exit\r
- case 1:\r
- h = buttonDesc[0].hwnd; break; // could be NULL\r
- case 2:\r
- if(!EngineOutputIsUp()) continue; // skip closed auxiliary windows\r
- h = e1; break;\r
- case 3:\r
- if(!EngineOutputIsUp()) continue;\r
- h = e2; break;\r
- case 4:\r
- if(!MoveHistoryIsUp()) continue;\r
- h = mh; break;\r
-// case 6: // input to eval graph does not seem to get here!\r
-// if(!EvalGraphIsUp()) continue;\r
-// h = evalGraphDialog; break;\r
- case 5:\r
- if(!appData.icsActive) continue;\r
- SAY("display");\r
- h = hText; break;\r
- case 6:\r
- if(!appData.icsActive) continue;\r
- SAY("input");\r
- h = hInput; break;\r
- }\r
- } while(h == 0);\r
-\r
- if(currentElement > 4 && IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
- if(currentElement < 5 && IsIconic(hwndMain)) ShowWindow(hwndMain, SW_RESTORE); // all open together\r
- SetFocus(h);\r
-\r
- return; // this message now has been processed\r
- }\r
- }\r
-\r
- if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&\r
- !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&\r
- !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&\r
- !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&\r
- !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&\r
- !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&\r
- !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&\r
- !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) && JAWS_ACCEL\r
- !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&\r
- !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {\r
- int done = 0, i; // [HGM] chat: dispatch cat-box messages\r
- for(i=0; i<MAX_CHAT; i++) \r
- if(chatHandle[i] && IsDialogMessage(chatHandle[i], &msg)) {\r
- done = 1; break;\r
- }\r
- if(done) return; // [HGM] chat: end patch\r
- TranslateMessage(&msg); /* Translates virtual key codes */\r
- DispatchMessage(&msg); /* Dispatches message to window */\r
- }\r
-}\r
-\r
-void\r
-DoEvents ()\r
-{ /* Dispatch pending messages */\r
- MSG msg;\r
- while (PeekMessage(&msg, /* message structure */\r
- NULL, /* handle of window receiving the message */\r
- 0, /* lowest message to examine */\r
- 0, /* highest message to examine */\r
- PM_REMOVE))\r
- {\r
- HandleMessage(&msg);\r
- }\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Initialization functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-void\r
-SetUserLogo()\r
-{ // update user logo if necessary\r
- static char oldUserName[MSG_SIZ], dir[MSG_SIZ], *curName;\r
-\r
- if(appData.autoLogo) {\r
- curName = UserName();\r
- if(strcmp(curName, oldUserName)) {\r
- GetCurrentDirectory(MSG_SIZ, dir);\r
- SetCurrentDirectory(installDir);\r
- snprintf(oldUserName, MSG_SIZ, "logos\\%s.bmp", curName);\r
- userLogo = LoadImage( 0, oldUserName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); \r
- safeStrCpy(oldUserName, curName, sizeof(oldUserName)/sizeof(oldUserName[0]) );\r
- if(userLogo == NULL)\r
- userLogo = LoadImage( 0, "logos\\dummy.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); \r
- SetCurrentDirectory(dir); /* return to prev directory */\r
- }\r
- }\r
-}\r
-\r
-BOOL\r
-InitApplication(HINSTANCE hInstance)\r
-{\r
- WNDCLASS wc;\r
-\r
- /* Fill in window class structure with parameters that describe the */\r
- /* main window. */\r
-\r
- wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */\r
- wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */\r
- wc.cbClsExtra = 0; /* No per-class extra data. */\r
- wc.cbWndExtra = 0; /* No per-window extra data. */\r
- wc.hInstance = hInstance; /* Owner of this class */\r
- wc.hIcon = LoadIcon(hInstance, "icon_white");\r
- wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */\r
- wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */\r
- wc.lpszMenuName = szAppName; /* Menu name from .RC */\r
- wc.lpszClassName = szAppName; /* Name to register as */\r
-\r
- /* Register the window class and return success/failure code. */\r
- if (!RegisterClass(&wc)) return FALSE;\r
-\r
- wc.style = CS_HREDRAW | CS_VREDRAW;\r
- wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;\r
- wc.cbClsExtra = 0;\r
- wc.cbWndExtra = DLGWINDOWEXTRA;\r
- wc.hInstance = hInstance;\r
- wc.hIcon = LoadIcon(hInstance, "icon_white");\r
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);\r
- wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);\r
- wc.lpszMenuName = NULL;\r
- wc.lpszClassName = szConsoleName;\r
-\r
- if (!RegisterClass(&wc)) return FALSE;\r
- return TRUE;\r
-}\r
-\r
-\r
-/* Set by InitInstance, used by EnsureOnScreen */\r
-int screenHeight, screenWidth;\r
-RECT screenGeometry;\r
-\r
-void\r
-EnsureOnScreen(int *x, int *y, int minX, int minY)\r
-{\r
-// int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);\r
- /* Be sure window at (x,y) is not off screen (or even mostly off screen) */\r
- if (*x > screenGeometry.right - 32) *x = screenGeometry.left;\r
- if (*y > screenGeometry.bottom - 32) *y = screenGeometry.top;\r
- if (*x < screenGeometry.left + minX) *x = screenGeometry.left + minX;\r
- if (*y < screenGeometry.top + minY) *y = screenGeometry.top + minY;\r
-}\r
-\r
-VOID\r
-LoadLogo(ChessProgramState *cps, int n, Boolean ics)\r
-{\r
- char buf[MSG_SIZ], dir[MSG_SIZ];\r
- GetCurrentDirectory(MSG_SIZ, dir);\r
- SetCurrentDirectory(installDir);\r
- if( appData.logo[n] && appData.logo[n][0] != NULLCHAR) {\r
- cps->programLogo = LoadImage( 0, appData.logo[n], IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
-\r
- if (cps->programLogo == NULL && appData.debugMode) {\r
- fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.logo[n] );\r
- }\r
- } else if(appData.autoLogo) {\r
- if(ics) { // [HGM] logo: in ICS mode second can be used for ICS\r
- char *opponent = "";\r
- if(gameMode == IcsPlayingWhite) opponent = gameInfo.black;\r
- if(gameMode == IcsPlayingBlack) opponent = gameInfo.white;\r
- sprintf(buf, "logos\\%s\\%s.bmp", appData.icsHost, opponent);\r
- if(!*opponent || !(cps->programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ))) {\r
- sprintf(buf, "logos\\%s.bmp", appData.icsHost);\r
- cps->programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
- }\r
- } else\r
- if(appData.directory[n] && appData.directory[n][0]) {\r
- SetCurrentDirectory(appData.directory[n]);\r
- cps->programLogo = LoadImage( 0, "logo.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); \r
- }\r
- }\r
- SetCurrentDirectory(dir); /* return to prev directory */\r
-}\r
-\r
-VOID\r
-InitTextures()\r
-{\r
- ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );\r
- backTextureSquareSize = 0; // kludge to force recalculation of texturemode\r
- \r
- if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {\r
- if(liteBackTexture) DeleteObject(liteBackTexture);\r
- liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
- liteBackTextureMode = appData.liteBackTextureMode;\r
-\r
- if (liteBackTexture == NULL && appData.debugMode) {\r
- fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );\r
- }\r
- }\r
- \r
- if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {\r
- if(darkBackTexture) DeleteObject(darkBackTexture);\r
- darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
- darkBackTextureMode = appData.darkBackTextureMode;\r
-\r
- if (darkBackTexture == NULL && appData.debugMode) {\r
- fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );\r
- }\r
- }\r
-}\r
-\r
-#ifndef SM_CXVIRTUALSCREEN\r
-#define SM_CXVIRTUALSCREEN 78\r
-#endif\r
-#ifndef SM_CYVIRTUALSCREEN\r
-#define SM_CYVIRTUALSCREEN 79\r
-#endif\r
-#ifndef SM_XVIRTUALSCREEN \r
-#define SM_XVIRTUALSCREEN 76\r
-#endif\r
-#ifndef SM_YVIRTUALSCREEN \r
-#define SM_YVIRTUALSCREEN 77\r
-#endif\r
-\r
-VOID\r
-InitGeometry()\r
-{\r
- screenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);\r
- if( !screenHeight ) screenHeight = GetSystemMetrics(SM_CYSCREEN);\r
- screenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);\r
- if( !screenWidth ) screenWidth = GetSystemMetrics(SM_CXSCREEN);\r
- screenGeometry.left = GetSystemMetrics(SM_XVIRTUALSCREEN);\r
- screenGeometry.top = GetSystemMetrics(SM_YVIRTUALSCREEN);\r
- screenGeometry.right = screenGeometry.left + screenWidth;\r
- screenGeometry.bottom = screenGeometry.top + screenHeight;\r
-}\r
-\r
-ChessProgramState broadcast;\r
-\r
-BOOL\r
-InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)\r
-{\r
- HWND hwnd; /* Main window handle. */\r
- int ibs;\r
- WINDOWPLACEMENT wp;\r
- char *filepart;\r
-\r
- hInst = hInstance; /* Store instance handle in our global variable */\r
- programName = szAppName;\r
-\r
- if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {\r
- *filepart = NULLCHAR;\r
- SetCurrentDirectory(installDir);\r
- } else {\r
- GetCurrentDirectory(MSG_SIZ, installDir);\r
- }\r
- gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise\r
- InitGeometry();\r
- InitAppData(lpCmdLine); /* Get run-time parameters */\r
- /* xboard, and older WinBoards, controlled the move sound with the\r
- appData.ringBellAfterMoves option. In the current WinBoard, we\r
- always turn the option on (so that the backend will call us),\r
- then let the user turn the sound off by setting it to silence if\r
- desired. To accommodate old winboard.ini files saved by old\r
- versions of WinBoard, we also turn off the sound if the option\r
- was initially set to false. [HGM] taken out of InitAppData */\r
- if (!appData.ringBellAfterMoves) {\r
- sounds[(int)SoundMove].name = strdup("");\r
- appData.ringBellAfterMoves = TRUE;\r
- }\r
- if (appData.debugMode) {\r
- char *c = appData.nameOfDebugFile;\r
- if(strstr(c, "///") == c) {\r
- broadcast.which = "broadcaster";\r
- broadcast.pr = NoProc;\r
- broadcast.isr = NULL;\r
- broadcast.program = c + 3;\r
- broadcast.dir = ".";\r
- broadcast.host = "localhost";\r
- StartChessProgram(&broadcast);\r
- debugFP = (FILE*) _fdopen(_open_osfhandle((long)(((ChildProc*)(broadcast.pr))->hTo), _O_WRONLY), "w");\r
- } else\r
- debugFP = fopen(c, "w");\r
- setbuf(debugFP, NULL);\r
- }\r
-\r
- LoadLanguageFile(appData.language);\r
-\r
- InitBackEnd1();\r
-\r
-// InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()\r
-// InitEngineUCI( installDir, &second );\r
-\r
- /* Create a main window for this application instance. */\r
- hwnd = CreateWindow(szAppName, szTitle,\r
- (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),\r
- CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,\r
- NULL, NULL, hInstance, NULL);\r
- hwndMain = hwnd;\r
-\r
- /* If window could not be created, return "failure" */\r
- if (!hwnd) {\r
- return (FALSE);\r
- }\r
-\r
- /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */\r
- LoadLogo(&first, 0, FALSE);\r
- LoadLogo(&second, 1, appData.icsActive);\r
-\r
- SetUserLogo();\r
-\r
- iconWhite = LoadIcon(hInstance, "icon_white");\r
- iconBlack = LoadIcon(hInstance, "icon_black");\r
- iconCurrent = iconWhite;\r
- InitDrawingColors();\r
-\r
- InitPosition(0); // to set nr of ranks and files, which might be non-default through command-line args\r
- for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {\r
- /* Compute window size for each board size, and use the largest\r
- size that fits on this screen as the default. */\r
- InitDrawingSizes((BoardSize)(ibs+1000), 0);\r
- if (boardSize == (BoardSize)-1 &&\r
- winH <= screenHeight\r
- - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10\r
- && winW <= screenWidth) {\r
- boardSize = (BoardSize)ibs;\r
- }\r
- }\r
-\r
- InitDrawingSizes(boardSize, 0);\r
- RecentEngineMenu(appData.recentEngineList);\r
- InitMenuChecks();\r
- buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);\r
-\r
- /* [AS] Load textures if specified */\r
- InitTextures();\r
-\r
- mysrandom( (unsigned) time(NULL) );\r
-\r
- /* [AS] Restore layout */\r
- if( wpMoveHistory.visible ) {\r
- MoveHistoryPopUp();\r
- }\r
-\r
- if( wpEvalGraph.visible ) {\r
- EvalGraphPopUp();\r
- }\r
-\r
- if( wpEngineOutput.visible ) {\r
- EngineOutputPopUp();\r
- }\r
-\r
- /* Make the window visible; update its client area; and return "success" */\r
- EnsureOnScreen(&wpMain.x, &wpMain.y, minX, minY);\r
- wp.length = sizeof(WINDOWPLACEMENT);\r
- wp.flags = 0;\r
- wp.showCmd = nCmdShow;\r
- wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;\r
- wp.rcNormalPosition.left = wpMain.x;\r
- wp.rcNormalPosition.right = wpMain.x + wpMain.width;\r
- wp.rcNormalPosition.top = wpMain.y;\r
- wp.rcNormalPosition.bottom = wpMain.y + wpMain.height;\r
- SetWindowPlacement(hwndMain, &wp);\r
-\r
- InitBackEnd2(); // [HGM] moved until after all windows placed, to save correct position if fatal error on engine start\r
-\r
- if(!appData.noGUI) SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
- 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);\r
-\r
- if (hwndConsole) {\r
-#if AOT_CONSOLE\r
- SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
- 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);\r
-#endif\r
- ShowWindow(hwndConsole, nCmdShow);\r
- SetActiveWindow(hwndConsole);\r
- }\r
- if(!appData.noGUI) UpdateWindow(hwnd); else ShowWindow(hwnd, SW_MINIMIZE);\r
- if(gameListDialog) SetFocus(gameListDialog); // [HGM] jaws: for if we clicked multi-game game file\r
-\r
- return TRUE;\r
-\r
-}\r
-\r
-VOID\r
-InitMenuChecks()\r
-{\r
- HMENU hmenu = GetMenu(hwndMain);\r
-\r
- (void) EnableMenuItem(hmenu, IDM_CommPort,\r
- MF_BYCOMMAND|((appData.icsActive &&\r
- *appData.icsCommPort != NULLCHAR) ?\r
- MF_ENABLED : MF_GRAYED));\r
- (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,\r
- MF_BYCOMMAND|(saveSettingsOnExit ?\r
- MF_CHECKED : MF_UNCHECKED));\r
- EnableMenuItem(hmenu, IDM_SaveSelected, MF_GRAYED);\r
-}\r
-\r
-//---------------------------------------------------------------------------------------------------------\r
-\r
-#define ICS_TEXT_MENU_SIZE (IDM_CommandXLast - IDM_CommandX + 1)\r
-#define XBOARD FALSE\r
-\r
-#define OPTCHAR "/"\r
-#define SEPCHAR "="\r
-#define TOPLEVEL 0\r
-\r
-#include "args.h"\r
-\r
-// front-end part of option handling\r
-\r
-VOID\r
-LFfromMFP(LOGFONT* lf, MyFontParams *mfp)\r
-{\r
- HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);\r
- lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);\r
- DeleteDC(hdc);\r
- lf->lfWidth = 0;\r
- lf->lfEscapement = 0;\r
- lf->lfOrientation = 0;\r
- lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;\r
- lf->lfItalic = mfp->italic;\r
- lf->lfUnderline = mfp->underline;\r
- lf->lfStrikeOut = mfp->strikeout;\r
- lf->lfCharSet = mfp->charset;\r
- lf->lfOutPrecision = OUT_DEFAULT_PRECIS;\r
-\r
-\r
-\r
- lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;\r
- lf->lfQuality = DEFAULT_QUALITY;\r
- lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;\r
- safeStrCpy(lf->lfFaceName, mfp->faceName, sizeof(lf->lfFaceName)/sizeof(lf->lfFaceName[0]) );\r
-}\r
-\r
-void\r
-CreateFontInMF(MyFont *mf)\r
-{ \r
- LFfromMFP(&mf->lf, &mf->mfp);\r
- if (mf->hf) DeleteObject(mf->hf);\r
- mf->hf = CreateFontIndirect(&mf->lf);\r
-}\r
-\r
-// [HGM] This platform-dependent table provides the location for storing the color info\r
-void *\r
-colorVariable[] = {\r
- &whitePieceColor, \r
- &blackPieceColor, \r
- &lightSquareColor,\r
- &darkSquareColor, \r
- &highlightSquareColor,\r
- &premoveHighlightColor,\r
- NULL,\r
- &consoleBackgroundColor,\r
- &appData.fontForeColorWhite,\r
- &appData.fontBackColorWhite,\r
- &appData.fontForeColorBlack,\r
- &appData.fontBackColorBlack,\r
- &appData.evalHistColorWhite,\r
- &appData.evalHistColorBlack,\r
- &appData.highlightArrowColor,\r
-};\r
-\r
-/* Command line font name parser. NULL name means do nothing.\r
- Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"\r
- For backward compatibility, syntax without the colon is also\r
- accepted, but font names with digits in them won't work in that case.\r
-*/\r
-VOID\r
-ParseFontName(char *name, MyFontParams *mfp)\r
-{\r
- char *p, *q;\r
- if (name == NULL) return;\r
- p = name;\r
- q = strchr(p, ':');\r
- if (q) {\r
- if (q - p >= sizeof(mfp->faceName))\r
- ExitArgError(_("Font name too long:"), name, TRUE);\r
- memcpy(mfp->faceName, p, q - p);\r
- mfp->faceName[q - p] = NULLCHAR;\r
- p = q + 1;\r
- } else {\r
- q = mfp->faceName;\r
-\r
- while (*p && !isdigit(*p)) {\r
- *q++ = *p++;\r
- if (q - mfp->faceName >= sizeof(mfp->faceName))\r
- ExitArgError(_("Font name too long:"), name, TRUE);\r
- }\r
- while (q > mfp->faceName && q[-1] == ' ') q--;\r
- *q = NULLCHAR;\r
- }\r
- if (!*p) ExitArgError(_("Font point size missing:"), name, TRUE);\r
- mfp->pointSize = (float) atof(p);\r
- mfp->bold = (strchr(p, 'b') != NULL);\r
- mfp->italic = (strchr(p, 'i') != NULL);\r
- mfp->underline = (strchr(p, 'u') != NULL);\r
- mfp->strikeout = (strchr(p, 's') != NULL);\r
- mfp->charset = DEFAULT_CHARSET;\r
- q = strchr(p, 'c');\r
- if (q)\r
- mfp->charset = (BYTE) atoi(q+1);\r
-}\r
-\r
-void\r
-ParseFont(char *name, int number)\r
-{ // wrapper to shield back-end from 'font'\r
- ParseFontName(name, &font[boardSize][number]->mfp);\r
-}\r
-\r
-void\r
-SetFontDefaults()\r
-{ // in WB we have a 2D array of fonts; this initializes their description\r
- int i, j;\r
- /* Point font array elements to structures and\r
- parse default font names */\r
- for (i=0; i<NUM_FONTS; i++) {\r
- for (j=0; j<NUM_SIZES; j++) {\r
- font[j][i] = &fontRec[j][i];\r
- ParseFontName(font[j][i]->def, &font[j][i]->mfp);\r
- }\r
- }\r
-}\r
-\r
-void\r
-CreateFonts()\r
-{ // here we create the actual fonts from the selected descriptions\r
- int i, j;\r
- for (i=0; i<NUM_FONTS; i++) {\r
- for (j=0; j<NUM_SIZES; j++) {\r
- CreateFontInMF(font[j][i]);\r
- }\r
- }\r
-}\r
-/* Color name parser.\r
- X version accepts X color names, but this one\r
- handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */\r
-COLORREF\r
-ParseColorName(char *name)\r
-{\r
- int red, green, blue, count;\r
- char buf[MSG_SIZ];\r
-\r
- count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);\r
- if (count != 3) {\r
- count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d", \r
- &red, &green, &blue);\r
- }\r
- if (count != 3) {\r
- snprintf(buf, MSG_SIZ, _("Can't parse color name %s"), name);\r
- DisplayError(buf, 0);\r
- return RGB(0, 0, 0);\r
- }\r
- return PALETTERGB(red, green, blue);\r
-}\r
-\r
-void\r
-ParseColor(int n, char *name)\r
-{ // for WinBoard the color is an int, which needs to be derived from the string\r
- if(colorVariable[n]) *(int*)colorVariable[n] = ParseColorName(name);\r
-}\r
-\r
-void\r
-ParseAttribs(COLORREF *color, int *effects, char* argValue)\r
-{\r
- char *e = argValue;\r
- int eff = 0;\r
-\r
- while (*e) {\r
- if (*e == 'b') eff |= CFE_BOLD;\r
- else if (*e == 'i') eff |= CFE_ITALIC;\r
- else if (*e == 'u') eff |= CFE_UNDERLINE;\r
- else if (*e == 's') eff |= CFE_STRIKEOUT;\r
- else if (*e == '#' || isdigit(*e)) break;\r
- e++;\r
- }\r
- *effects = eff;\r
- *color = ParseColorName(e);\r
-}\r
-\r
-void\r
-ParseTextAttribs(ColorClass cc, char *s)\r
-{ // [HGM] front-end wrapper that does the platform-dependent call\r
- // for XBoard we would set (&appData.colorShout)[cc] = strdup(s);\r
- ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, s);\r
-}\r
-\r
-void\r
-ParseBoardSize(void *addr, char *name)\r
-{ // [HGM] rewritten with return-value ptr to shield back-end from BoardSize\r
- BoardSize bs = SizeTiny;\r
- while (sizeInfo[bs].name != NULL) {\r
- if (StrCaseCmp(name, sizeInfo[bs].name) == 0) {\r
- *(BoardSize *)addr = bs;\r
- return;\r
- }\r
- bs++;\r
- }\r
- ExitArgError(_("Unrecognized board size value"), name, TRUE);\r
-}\r
-\r
-void\r
-LoadAllSounds()\r
-{ // [HGM] import name from appData first\r
- ColorClass cc;\r
- SoundClass sc;\r
- for (cc = (ColorClass)0; cc < ColorNormal; cc++) {\r
- textAttribs[cc].sound.name = strdup((&appData.soundShout)[cc]);\r
- textAttribs[cc].sound.data = NULL;\r
- MyLoadSound(&textAttribs[cc].sound);\r
- }\r
- for (cc = ColorNormal; cc < NColorClasses; cc++) {\r
- textAttribs[cc].sound.name = strdup("");\r
- textAttribs[cc].sound.data = NULL;\r
- }\r
- for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {\r
- sounds[sc].name = strdup((&appData.soundMove)[sc]);\r
- sounds[sc].data = NULL;\r
- MyLoadSound(&sounds[sc]);\r
- }\r
-}\r
-\r
-void\r
-SetCommPortDefaults()\r
-{\r
- memset(&dcb, 0, sizeof(DCB)); // required by VS 2002 +\r
- dcb.DCBlength = sizeof(DCB);\r
- dcb.BaudRate = 9600;\r
- dcb.fBinary = TRUE;\r
- dcb.fParity = FALSE;\r
- dcb.fOutxCtsFlow = FALSE;\r
- dcb.fOutxDsrFlow = FALSE;\r
- dcb.fDtrControl = DTR_CONTROL_ENABLE;\r
- dcb.fDsrSensitivity = FALSE;\r
- dcb.fTXContinueOnXoff = TRUE;\r
- dcb.fOutX = FALSE;\r
- dcb.fInX = FALSE;\r
- dcb.fNull = FALSE;\r
- dcb.fRtsControl = RTS_CONTROL_ENABLE;\r
- dcb.fAbortOnError = FALSE;\r
- dcb.ByteSize = 7;\r
- dcb.Parity = SPACEPARITY;\r
- dcb.StopBits = ONESTOPBIT;\r
-}\r
-\r
-// [HGM] args: these three cases taken out to stay in front-end\r
-void\r
-SaveFontArg(FILE *f, ArgDescriptor *ad)\r
-{ // in WinBoard every board size has its own font, and the "argLoc" identifies the table,\r
- // while the curent board size determines the element. This system should be ported to XBoard.\r
- // What the table contains pointers to, and how to print the font description, remains platform-dependent\r
- int bs;\r
- for (bs=0; bs<NUM_SIZES; bs++) {\r
- MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;\r
- fprintf(f, "/size=%s ", sizeInfo[bs].name);\r
- fprintf(f, "/%s=\"%s:%g%s%s%s%s%sc%d\"\n",\r
- ad->argName, mfp->faceName, mfp->pointSize,\r
- mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",\r
- mfp->bold ? "b" : "",\r
- mfp->italic ? "i" : "",\r
- mfp->underline ? "u" : "",\r
- mfp->strikeout ? "s" : "",\r
- (int)mfp->charset);\r
- }\r
- }\r
-\r
-void\r
-ExportSounds()\r
-{ // [HGM] copy the names from the internal WB variables to appData\r
- ColorClass cc;\r
- SoundClass sc;\r
- for (cc = (ColorClass)0; cc < ColorNormal; cc++)\r
- (&appData.soundShout)[cc] = textAttribs[cc].sound.name;\r
- for (sc = (SoundClass)0; sc < NSoundClasses; sc++)\r
- (&appData.soundMove)[sc] = sounds[sc].name;\r
-}\r
-\r
-void\r
-SaveAttribsArg(FILE *f, ArgDescriptor *ad)\r
-{ // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though\r
- MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];\r
- fprintf(f, "/%s=\"%s%s%s%s%s#%02lx%02lx%02lx\"\n", ad->argName,\r
- (ta->effects & CFE_BOLD) ? "b" : "",\r
- (ta->effects & CFE_ITALIC) ? "i" : "",\r
- (ta->effects & CFE_UNDERLINE) ? "u" : "",\r
- (ta->effects & CFE_STRIKEOUT) ? "s" : "",\r
- (ta->effects) ? " " : "",\r
- ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);\r
- }\r
-\r
-void\r
-SaveColor(FILE *f, ArgDescriptor *ad)\r
-{ // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?\r
- COLORREF color = *(COLORREF *)colorVariable[(int)ad->argLoc];\r
- fprintf(f, "/%s=#%02lx%02lx%02lx\n", ad->argName, \r
- color&0xff, (color>>8)&0xff, (color>>16)&0xff);\r
-}\r
-\r
-void\r
-SaveBoardSize(FILE *f, char *name, void *addr)\r
-{ // wrapper to shield back-end from BoardSize & sizeInfo\r
- fprintf(f, "/%s=%s\n", name, sizeInfo[*(BoardSize *)addr].name);\r
-}\r
-\r
-void\r
-ParseCommPortSettings(char *s)\r
-{ // wrapper to keep dcb from back-end\r
- ParseCommSettings(s, &dcb);\r
-}\r
-\r
-void\r
-GetWindowCoords()\r
-{ // wrapper to shield use of window handles from back-end (make addressible by number?)\r
- GetActualPlacement(hwndMain, &wpMain);\r
- GetActualPlacement(hwndConsole, &wpConsole);\r
- GetActualPlacement(commentDialog, &wpComment);\r
- GetActualPlacement(editTagsDialog, &wpTags);\r
- GetActualPlacement(gameListDialog, &wpGameList);\r
- GetActualPlacement(moveHistoryDialog, &wpMoveHistory);\r
- GetActualPlacement(evalGraphDialog, &wpEvalGraph);\r
- GetActualPlacement(engineOutputDialog, &wpEngineOutput);\r
-}\r
-\r
-void\r
-PrintCommPortSettings(FILE *f, char *name)\r
-{ // wrapper to shield back-end from DCB\r
- PrintCommSettings(f, name, &dcb);\r
-}\r
-\r
-int\r
-MySearchPath(char *installDir, char *name, char *fullname)\r
-{\r
- char *dummy, buf[MSG_SIZ], *p = name, *q;\r
- if(name[0]== '%') {\r
- fullname[0] = 0; // [HGM] first expand any environment variables in the given name\r
- while(*p == '%' && (q = strchr(p+1, '%'))) { // [HGM] recognize %*% as environment variable\r
- safeStrCpy(buf, p+1, sizeof(buf)/sizeof(buf[0]) );\r
- *strchr(buf, '%') = 0;\r
- strcat(fullname, getenv(buf));\r
- p = q+1; while(*p == '\\') { strcat(fullname, "\\"); p++; }\r
- }\r
- strcat(fullname, p); // after environment variables (if any), take the remainder of the given name\r
- if(appData.debugMode) fprintf(debugFP, "name = '%s', expanded name = '%s'\n", name, fullname);\r
- return (int) strlen(fullname);\r
- }\r
- return (int) SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy);\r
-}\r
-\r
-int\r
-MyGetFullPathName(char *name, char *fullname)\r
-{\r
- char *dummy;\r
- return (int) GetFullPathName(name, MSG_SIZ, fullname, &dummy);\r
-}\r
-\r
-int\r
-MainWindowUp()\r
-{ // [HGM] args: allows testing if main window is realized from back-end\r
- return hwndMain != NULL;\r
-}\r
-\r
-void\r
-PopUpStartupDialog()\r
-{\r
- FARPROC lpProc;\r
- \r
- LoadLanguageFile(appData.language);\r
- lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);\r
- DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);\r
- FreeProcInstance(lpProc);\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * GDI board drawing routines\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/* [AS] Draw square using background texture */\r
-static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )\r
-{\r
- XFORM x;\r
-\r
- if( mode == 0 ) {\r
- return; /* Should never happen! */\r
- }\r
-\r
- SetGraphicsMode( dst, GM_ADVANCED );\r
-\r
- switch( mode ) {\r
- case 1:\r
- /* Identity */\r
- break;\r
- case 2:\r
- /* X reflection */\r
- x.eM11 = -1.0;\r
- x.eM12 = 0;\r
- x.eM21 = 0;\r
- x.eM22 = 1.0;\r
- x.eDx = (FLOAT) dw + dx - 1;\r
- x.eDy = 0;\r
- dx = 0;\r
- SetWorldTransform( dst, &x );\r
- break;\r
- case 3:\r
- /* Y reflection */\r
- x.eM11 = 1.0;\r
- x.eM12 = 0;\r
- x.eM21 = 0;\r
- x.eM22 = -1.0;\r
- x.eDx = 0;\r
- x.eDy = (FLOAT) dh + dy - 1;\r
- dy = 0;\r
- SetWorldTransform( dst, &x );\r
- break;\r
- case 4:\r
- /* X/Y flip */\r
- x.eM11 = 0;\r
- x.eM12 = 1.0;\r
- x.eM21 = 1.0;\r
- x.eM22 = 0;\r
- x.eDx = (FLOAT) dx;\r
- x.eDy = (FLOAT) dy;\r
- dx = 0;\r
- dy = 0;\r
- SetWorldTransform( dst, &x );\r
- break;\r
- }\r
-\r
- BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );\r
-\r
- x.eM11 = 1.0;\r
- x.eM12 = 0;\r
- x.eM21 = 0;\r
- x.eM22 = 1.0;\r
- x.eDx = 0;\r
- x.eDy = 0;\r
- SetWorldTransform( dst, &x );\r
-\r
- ModifyWorldTransform( dst, 0, MWT_IDENTITY );\r
-}\r
-\r
-/* [AS] [HGM] Make room for more piece types, so all pieces can be different */\r
-enum {\r
- PM_WP = (int) WhitePawn, \r
- PM_WN = (int) WhiteKnight, \r
- PM_WB = (int) WhiteBishop, \r
- PM_WR = (int) WhiteRook, \r
- PM_WQ = (int) WhiteQueen, \r
- PM_WF = (int) WhiteFerz, \r
- PM_WW = (int) WhiteWazir, \r
- PM_WE = (int) WhiteAlfil, \r
- PM_WM = (int) WhiteMan, \r
- PM_WO = (int) WhiteCannon, \r
- PM_WU = (int) WhiteUnicorn, \r
- PM_WH = (int) WhiteNightrider, \r
- PM_WA = (int) WhiteAngel, \r
- PM_WC = (int) WhiteMarshall, \r
- PM_WAB = (int) WhiteCardinal, \r
- PM_WD = (int) WhiteDragon, \r
- PM_WL = (int) WhiteLance, \r
- PM_WS = (int) WhiteCobra, \r
- PM_WV = (int) WhiteFalcon, \r
- PM_WSG = (int) WhiteSilver, \r
- PM_WG = (int) WhiteGrasshopper, \r
- PM_WK = (int) WhiteKing,\r
- PM_BP = (int) BlackPawn, \r
- PM_BN = (int) BlackKnight, \r
- PM_BB = (int) BlackBishop, \r
- PM_BR = (int) BlackRook, \r
- PM_BQ = (int) BlackQueen, \r
- PM_BF = (int) BlackFerz, \r
- PM_BW = (int) BlackWazir, \r
- PM_BE = (int) BlackAlfil, \r
- PM_BM = (int) BlackMan,\r
- PM_BO = (int) BlackCannon, \r
- PM_BU = (int) BlackUnicorn, \r
- PM_BH = (int) BlackNightrider, \r
- PM_BA = (int) BlackAngel, \r
- PM_BC = (int) BlackMarshall, \r
- PM_BG = (int) BlackGrasshopper, \r
- PM_BAB = (int) BlackCardinal,\r
- PM_BD = (int) BlackDragon,\r
- PM_BL = (int) BlackLance,\r
- PM_BS = (int) BlackCobra,\r
- PM_BV = (int) BlackFalcon,\r
- PM_BSG = (int) BlackSilver,\r
- PM_BK = (int) BlackKing\r
-};\r
-\r
-static HFONT hPieceFont = NULL;\r
-static HBITMAP hPieceMask[(int) EmptySquare];\r
-static HBITMAP hPieceFace[(int) EmptySquare];\r
-static int fontBitmapSquareSize = 0;\r
-static char pieceToFontChar[(int) EmptySquare] =\r
- { 'p', 'n', 'b', 'r', 'q', \r
- 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',\r
- 'k', 'o', 'm', 'v', 't', 'w', \r
- 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',\r
- 'l' };\r
-\r
-extern BOOL SetCharTable( char *table, const char * map );\r
-/* [HGM] moved to backend.c */\r
-\r
-static void SetPieceBackground( HDC hdc, COLORREF color, int mode )\r
-{\r
- HBRUSH hbrush;\r
- BYTE r1 = GetRValue( color );\r
- BYTE g1 = GetGValue( color );\r
- BYTE b1 = GetBValue( color );\r
- BYTE r2 = r1 / 2;\r
- BYTE g2 = g1 / 2;\r
- BYTE b2 = b1 / 2;\r
- RECT rc;\r
-\r
- /* Create a uniform background first */\r
- hbrush = CreateSolidBrush( color );\r
- SetRect( &rc, 0, 0, squareSize, squareSize );\r
- FillRect( hdc, &rc, hbrush );\r
- DeleteObject( hbrush );\r
- \r
- if( mode == 1 ) {\r
- /* Vertical gradient, good for pawn, knight and rook, less for queen and king */\r
- int steps = squareSize / 2;\r
- int i;\r
-\r
- for( i=0; i<steps; i++ ) {\r
- BYTE r = r1 - (r1-r2) * i / steps;\r
- BYTE g = g1 - (g1-g2) * i / steps;\r
- BYTE b = b1 - (b1-b2) * i / steps;\r
-\r
- hbrush = CreateSolidBrush( RGB(r,g,b) );\r
- SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );\r
- FillRect( hdc, &rc, hbrush );\r
- DeleteObject(hbrush);\r
- }\r
- }\r
- else if( mode == 2 ) {\r
- /* Diagonal gradient, good more or less for every piece */\r
- POINT triangle[3];\r
- HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );\r
- HBRUSH hbrush_old;\r
- int steps = squareSize;\r
- int i;\r
-\r
- triangle[0].x = squareSize - steps;\r
- triangle[0].y = squareSize;\r
- triangle[1].x = squareSize;\r
- triangle[1].y = squareSize;\r
- triangle[2].x = squareSize;\r
- triangle[2].y = squareSize - steps;\r
-\r
- for( i=0; i<steps; i++ ) {\r
- BYTE r = r1 - (r1-r2) * i / steps;\r
- BYTE g = g1 - (g1-g2) * i / steps;\r
- BYTE b = b1 - (b1-b2) * i / steps;\r
-\r
- hbrush = CreateSolidBrush( RGB(r,g,b) );\r
- hbrush_old = SelectObject( hdc, hbrush );\r
- Polygon( hdc, triangle, 3 );\r
- SelectObject( hdc, hbrush_old );\r
- DeleteObject(hbrush);\r
- triangle[0].x++;\r
- triangle[2].y++;\r
- }\r
-\r
- SelectObject( hdc, hpen );\r
- }\r
-}\r
-\r
-/*\r
- [AS] The method I use to create the bitmaps it a bit tricky, but it\r
- seems to work ok. The main problem here is to find the "inside" of a chess\r
- piece: follow the steps as explained below.\r
-*/\r
-static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )\r
-{\r
- HBITMAP hbm;\r
- HBITMAP hbm_old;\r
- COLORREF chroma = RGB(0xFF,0x00,0xFF);\r
- RECT rc;\r
- SIZE sz;\r
-\r
-\r
- POINT pt;\r
- int backColor = whitePieceColor; \r
- int foreColor = blackPieceColor;\r
- \r
- if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {\r
- backColor = appData.fontBackColorWhite;\r
- foreColor = appData.fontForeColorWhite;\r
- }\r
- else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {\r
- backColor = appData.fontBackColorBlack;\r
- foreColor = appData.fontForeColorBlack;\r
- }\r
-\r
- /* Mask */\r
- hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );\r
-\r
- hbm_old = SelectObject( hdc, hbm );\r
-\r
- rc.left = 0;\r
- rc.top = 0;\r
- rc.right = squareSize;\r
- rc.bottom = squareSize;\r
-\r
- /* Step 1: background is now black */\r
- FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );\r
-\r
- GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );\r
-\r
- pt.x = (squareSize - sz.cx) / 2;\r
- pt.y = (squareSize - sz.cy) / 2;\r
-\r
- SetBkMode( hdc, TRANSPARENT );\r
- SetTextColor( hdc, chroma );\r
- /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */\r
- TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );\r
-\r
- SelectObject( hdc, GetStockObject(WHITE_BRUSH) );\r
- /* Step 3: the area outside the piece is filled with white */\r
-// FloodFill( hdc, 0, 0, chroma );\r
- ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );\r
- ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big\r
- ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );\r
- ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );\r
- SelectObject( hdc, GetStockObject(BLACK_BRUSH) );\r
- /* \r
- Step 4: this is the tricky part, the area inside the piece is filled with black,\r
- but if the start point is not inside the piece we're lost!\r
- There should be a better way to do this... if we could create a region or path\r
- from the fill operation we would be fine for example.\r
- */\r
-// FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );\r
- ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );\r
-\r
- { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */\r
- HDC dc2 = CreateCompatibleDC( hdc_window );\r
- HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );\r
-\r
- SelectObject( dc2, bm2 );\r
- BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy\r
- BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );\r
- BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );\r
- BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );\r
- BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );\r
-\r
- DeleteDC( dc2 );\r
- DeleteObject( bm2 );\r
- }\r
-\r
- SetTextColor( hdc, 0 );\r
- /* \r
- Step 5: some fonts have "disconnected" areas that are skipped by the fill:\r
- draw the piece again in black for safety.\r
- */\r
- TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );\r
-\r
- SelectObject( hdc, hbm_old );\r
-\r
- if( hPieceMask[index] != NULL ) {\r
- DeleteObject( hPieceMask[index] );\r
- }\r
-\r
- hPieceMask[index] = hbm;\r
-\r
- /* Face */\r
- hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );\r
-\r
- SelectObject( hdc, hbm );\r
-\r
- {\r
- HDC dc1 = CreateCompatibleDC( hdc_window );\r
- HDC dc2 = CreateCompatibleDC( hdc_window );\r
- HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );\r
-\r
- SelectObject( dc1, hPieceMask[index] );\r
- SelectObject( dc2, bm2 );\r
- FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );\r
- BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );\r
- \r
- /* \r
- Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves\r
- the piece background and deletes (makes transparent) the rest.\r
- Thanks to that mask, we are free to paint the background with the greates\r
- freedom, as we'll be able to mask off the unwanted parts when finished.\r
- We use this, to make gradients and give the pieces a "roundish" look.\r
- */\r
- SetPieceBackground( hdc, backColor, 2 );\r
- BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );\r
-\r
- DeleteDC( dc2 );\r
- DeleteDC( dc1 );\r
- DeleteObject( bm2 );\r
- }\r
-\r
- SetTextColor( hdc, foreColor );\r
- TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );\r
-\r
- SelectObject( hdc, hbm_old );\r
-\r
- if( hPieceFace[index] != NULL ) {\r
- DeleteObject( hPieceFace[index] );\r
- }\r
-\r
- hPieceFace[index] = hbm;\r
-}\r
-\r
-static int TranslatePieceToFontPiece( int piece )\r
-{\r
- switch( piece ) {\r
- case BlackPawn:\r
- return PM_BP;\r
- case BlackKnight:\r
- return PM_BN;\r
- case BlackBishop:\r
- return PM_BB;\r
- case BlackRook:\r
- return PM_BR;\r
- case BlackQueen:\r
- return PM_BQ;\r
- case BlackKing:\r
- return PM_BK;\r
- case WhitePawn:\r
- return PM_WP;\r
- case WhiteKnight:\r
- return PM_WN;\r
- case WhiteBishop:\r
- return PM_WB;\r
- case WhiteRook:\r
- return PM_WR;\r
- case WhiteQueen:\r
- return PM_WQ;\r
- case WhiteKing:\r
- return PM_WK;\r
-\r
- case BlackAngel:\r
- return PM_BA;\r
- case BlackMarshall:\r
- return PM_BC;\r
- case BlackFerz:\r
- return PM_BF;\r
- case BlackNightrider:\r
- return PM_BH;\r
- case BlackAlfil:\r
- return PM_BE;\r
- case BlackWazir:\r
- return PM_BW;\r
- case BlackUnicorn:\r
- return PM_BU;\r
- case BlackCannon:\r
- return PM_BO;\r
- case BlackGrasshopper:\r
- return PM_BG;\r
- case BlackMan:\r
- return PM_BM;\r
- case BlackSilver:\r
- return PM_BSG;\r
- case BlackLance:\r
- return PM_BL;\r
- case BlackFalcon:\r
- return PM_BV;\r
- case BlackCobra:\r
- return PM_BS;\r
- case BlackCardinal:\r
- return PM_BAB;\r
- case BlackDragon:\r
- return PM_BD;\r
-\r
- case WhiteAngel:\r
- return PM_WA;\r
- case WhiteMarshall:\r
- return PM_WC;\r
- case WhiteFerz:\r
- return PM_WF;\r
- case WhiteNightrider:\r
- return PM_WH;\r
- case WhiteAlfil:\r
- return PM_WE;\r
- case WhiteWazir:\r
- return PM_WW;\r
- case WhiteUnicorn:\r
- return PM_WU;\r
- case WhiteCannon:\r
- return PM_WO;\r
- case WhiteGrasshopper:\r
- return PM_WG;\r
- case WhiteMan:\r
- return PM_WM;\r
- case WhiteSilver:\r
- return PM_WSG;\r
- case WhiteLance:\r
- return PM_WL;\r
- case WhiteFalcon:\r
- return PM_WV;\r
- case WhiteCobra:\r
- return PM_WS;\r
- case WhiteCardinal:\r
- return PM_WAB;\r
- case WhiteDragon:\r
- return PM_WD;\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-void CreatePiecesFromFont()\r
-{\r
- LOGFONT lf;\r
- HDC hdc_window = NULL;\r
- HDC hdc = NULL;\r
- HFONT hfont_old;\r
- int fontHeight;\r
- int i;\r
-\r
- if( fontBitmapSquareSize < 0 ) {\r
- /* Something went seriously wrong in the past: do not try to recreate fonts! */\r
- return;\r
- }\r
-\r
- if( !appData.useFont || appData.renderPiecesWithFont == NULL ||\r
- appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {\r
- fontBitmapSquareSize = -1;\r
- return;\r
- }\r
-\r
- if( fontBitmapSquareSize != squareSize ) {\r
- hdc_window = GetDC( hwndMain );\r
- hdc = CreateCompatibleDC( hdc_window );\r
-\r
- if( hPieceFont != NULL ) {\r
- DeleteObject( hPieceFont );\r
- }\r
- else {\r
- for( i=0; i<=(int)BlackKing; i++ ) {\r
- hPieceMask[i] = NULL;\r
- hPieceFace[i] = NULL;\r
- }\r
- }\r
-\r
- fontHeight = 75;\r
-\r
- if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {\r
- fontHeight = appData.fontPieceSize;\r
- }\r
-\r
- fontHeight = (fontHeight * squareSize) / 100;\r
-\r
- lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );\r
- lf.lfWidth = 0;\r
- lf.lfEscapement = 0;\r
- lf.lfOrientation = 0;\r
- lf.lfWeight = FW_NORMAL;\r
- lf.lfItalic = 0;\r
- lf.lfUnderline = 0;\r
- lf.lfStrikeOut = 0;\r
- lf.lfCharSet = DEFAULT_CHARSET;\r
- lf.lfOutPrecision = OUT_DEFAULT_PRECIS;\r
- lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;\r
- lf.lfQuality = PROOF_QUALITY;\r
- lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;\r
- strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );\r
- lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';\r
-\r
- hPieceFont = CreateFontIndirect( &lf );\r
-\r
- if( hPieceFont == NULL ) {\r
- fontBitmapSquareSize = -2;\r
- }\r
- else {\r
- /* Setup font-to-piece character table */\r
- if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {\r
- /* No (or wrong) global settings, try to detect the font */\r
- if( strstr(lf.lfFaceName,"Alpha") != NULL ) {\r
- /* Alpha */\r
- SetCharTable(pieceToFontChar, "phbrqkojntwl");\r
- }\r
- else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {\r
- /* DiagramTT* family */\r
- SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");\r
- }\r
- else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {\r
- /* Fairy symbols */\r
- SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");\r
- }\r
- else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {\r
- /* Good Companion (Some characters get warped as literal :-( */\r
- char s[] = "1cmWG0??S??oYI23wgQU";\r
- s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;\r
- SetCharTable(pieceToFontChar, s);\r
- }\r
- else {\r
- /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */\r
- SetCharTable(pieceToFontChar, "pnbrqkomvtwl");\r
- }\r
- }\r
-\r
- /* Create bitmaps */\r
- hfont_old = SelectObject( hdc, hPieceFont );\r
- for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */\r
- if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */\r
- CreatePieceMaskFromFont( hdc_window, hdc, i );\r
-\r
- SelectObject( hdc, hfont_old );\r
-\r
- fontBitmapSquareSize = squareSize;\r
- }\r
- }\r
-\r
- if( hdc != NULL ) {\r
- DeleteDC( hdc );\r
- }\r
-\r
- if( hdc_window != NULL ) {\r
- ReleaseDC( hwndMain, hdc_window );\r
- }\r
-}\r
-\r
-HBITMAP\r
-DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)\r
-{\r
- char name[128], buf[MSG_SIZ];\r
-\r
- snprintf(name, sizeof(name)/sizeof(name[0]), "%s%d%s", piece, squareSize, suffix);\r
- if(appData.pieceDirectory[0]) {\r
- HBITMAP res;\r
- snprintf(buf, MSG_SIZ, "%s\\%s.bmp", appData.pieceDirectory, name);\r
- res = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
- if(res) return res;\r
- }\r
- if (gameInfo.event &&\r
- strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&\r
- strcmp(name, "k80s") == 0) {\r
- safeStrCpy(name, "tim", sizeof(name)/sizeof(name[0]) );\r
- }\r
- return LoadBitmap(hinst, name);\r
-}\r
-\r
-\r
-/* Insert a color into the program's logical palette\r
- structure. This code assumes the given color is\r
- the result of the RGB or PALETTERGB macro, and it\r
- knows how those macros work (which is documented).\r
-*/\r
-VOID\r
-InsertInPalette(COLORREF color)\r
-{\r
- LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);\r
-\r
- if (pLogPal->palNumEntries++ >= PALETTESIZE) {\r
- DisplayFatalError(_("Too many colors"), 0, 1);\r
- pLogPal->palNumEntries--;\r
- return;\r
- }\r
-\r
- pe->peFlags = (char) 0;\r
- pe->peRed = (char) (0xFF & color);\r
- pe->peGreen = (char) (0xFF & (color >> 8));\r
- pe->peBlue = (char) (0xFF & (color >> 16));\r
- return;\r
-}\r
-\r
-\r
-VOID\r
-InitDrawingColors()\r
-{\r
- int i;\r
- if (pLogPal == NULL) {\r
- /* Allocate enough memory for a logical palette with\r
- * PALETTESIZE entries and set the size and version fields\r
- * of the logical palette structure.\r
- */\r
- pLogPal = (NPLOGPALETTE)\r
- LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +\r
- (sizeof(PALETTEENTRY) * (PALETTESIZE))));\r
- pLogPal->palVersion = 0x300;\r
- }\r
- pLogPal->palNumEntries = 0;\r
-\r
- InsertInPalette(lightSquareColor);\r
- InsertInPalette(darkSquareColor);\r
- InsertInPalette(whitePieceColor);\r
- InsertInPalette(blackPieceColor);\r
- InsertInPalette(highlightSquareColor);\r
- InsertInPalette(premoveHighlightColor);\r
-\r
- /* create a logical color palette according the information\r
- * in the LOGPALETTE structure.\r
- */\r
- hPal = CreatePalette((LPLOGPALETTE) pLogPal);\r
-\r
- lightSquareBrush = CreateSolidBrush(lightSquareColor);\r
- blackSquareBrush = CreateSolidBrush(blackPieceColor);\r
- darkSquareBrush = CreateSolidBrush(darkSquareColor);\r
- whitePieceBrush = CreateSolidBrush(whitePieceColor);\r
- blackPieceBrush = CreateSolidBrush(blackPieceColor);\r
- iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));\r
- explodeBrush = CreateSolidBrush(highlightSquareColor); // [HGM] atomic\r
- for(i=0; i<8;i++) markerBrush[i] = CreateSolidBrush(markerColor[i]); // [HGM] markers\r
-\r
- /* [AS] Force rendering of the font-based pieces */\r
- if( fontBitmapSquareSize > 0 ) {\r
- fontBitmapSquareSize = 0;\r
- }\r
-}\r
-\r
-\r
-int\r
-BoardWidth(int boardSize, int n)\r
-{ /* [HGM] argument n added to allow different width and height */\r
- int lineGap = sizeInfo[boardSize].lineGap;\r
-\r
- if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {\r
- lineGap = appData.overrideLineGap;\r
- }\r
-\r
- return (n + 1) * lineGap +\r
- n * sizeInfo[boardSize].squareSize;\r
-}\r
-\r
-/* Respond to board resize by dragging edge */\r
-VOID\r
-ResizeBoard(int newSizeX, int newSizeY, int flags)\r
-{\r
- BoardSize newSize = NUM_SIZES - 1;\r
- static int recurse = 0;\r
- if (IsIconic(hwndMain)) return;\r
- if (recurse > 0) return;\r
- recurse++;\r
- while (newSize > 0) {\r
- InitDrawingSizes(newSize+1000, 0); // [HGM] kludge to update sizeInfo without visible effects\r
- if(newSizeX >= sizeInfo[newSize].cliWidth &&\r
- newSizeY >= sizeInfo[newSize].cliHeight) break;\r
- newSize--;\r
- } \r
- boardSize = newSize;\r
- InitDrawingSizes(boardSize, flags);\r
- recurse--;\r
-}\r
-\r
-\r
-extern Boolean twoBoards, partnerUp; // [HGM] dual\r
-\r
-VOID\r
-InitDrawingSizes(BoardSize boardSize, int flags)\r
-{\r
- int i, boardWidth, boardHeight; /* [HGM] height treated separately */\r
- ChessSquare piece;\r
- static int oldBoardSize = -1, oldTinyLayout = 0;\r
- HDC hdc;\r
- SIZE clockSize, messageSize;\r
- HFONT oldFont;\r
- char buf[MSG_SIZ];\r
- char *str;\r
- HMENU hmenu = GetMenu(hwndMain);\r
- RECT crect, wrect, oldRect;\r
- int offby;\r
- LOGBRUSH logbrush;\r
- VariantClass v = gameInfo.variant;\r
-\r
- int suppressVisibleEffects = 0; // [HGM] kludge to request updating sizeInfo only\r
- if((int)boardSize >= 1000 ) { boardSize -= 1000; suppressVisibleEffects = 1; }\r
-\r
- /* [HGM] call with -2 uses old size (for if nr of files, ranks changes) */\r
- if(boardSize == (BoardSize)(-2) ) boardSize = oldBoardSize;\r
- if(boardSize == -1) return; // no size defined yet; abort (to allow early call of InitPosition)\r
- oldBoardSize = boardSize;\r
-\r
- if(boardSize != SizeMiddling && boardSize != SizePetite && boardSize != SizeBulky && !appData.useFont)\r
- { // correct board size to one where built-in pieces exist\r
- if((v == VariantCapablanca || v == VariantGothic || v == VariantGrand || v == VariantCapaRandom || v == VariantJanus || v == VariantSuper)\r
- && (boardSize < SizePetite || boardSize > SizeBulky) // Archbishop and Chancellor available in entire middle range\r
-\r
- || (v == VariantShogi && boardSize != SizeModerate) // Japanese-style Shogi\r
- || v == VariantKnightmate || v == VariantSChess || v == VariantXiangqi || v == VariantSpartan\r
- || v == VariantShatranj || v == VariantMakruk || v == VariantGreat || v == VariantFairy || v == VariantLion ) {\r
- if(boardSize < SizeMediocre) boardSize = SizePetite; else\r
- if(boardSize > SizeModerate) boardSize = SizeBulky; else\r
- boardSize = SizeMiddling;\r
- }\r
- }\r
- if(!appData.useFont && boardSize == SizePetite && (v == VariantKnightmate)) boardSize = SizeMiddling; // no Unicorn in Petite\r
-\r
- oldRect.left = wpMain.x; //[HGM] placement: remember previous window params\r
- oldRect.top = wpMain.y;\r
- oldRect.right = wpMain.x + wpMain.width;\r
- oldRect.bottom = wpMain.y + wpMain.height;\r
-\r
- tinyLayout = sizeInfo[boardSize].tinyLayout;\r
- smallLayout = sizeInfo[boardSize].smallLayout;\r
- squareSize = sizeInfo[boardSize].squareSize;\r
- lineGap = sizeInfo[boardSize].lineGap;\r
- minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted */\r
- border = appData.useBorder && appData.border[0] ? squareSize/2 : 0;\r
-\r
- // [HGM] decide on tininess based on total board width rather than square size\r
- tinyLayout = squareSize * (BOARD_WIDTH);\r
- tinyLayout = tinyLayout < 35*8 ? 2 : tinyLayout < 43*8 ? 1 : 0;\r
-\r
- if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {\r
- lineGap = appData.overrideLineGap;\r
- }\r
-\r
- if (tinyLayout != oldTinyLayout) {\r
- long style = GetWindowLongPtr(hwndMain, GWL_STYLE);\r
- if (tinyLayout == 2) {\r
- style &= ~WS_SYSMENU;\r
- InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize,\r
- "&Minimize\tCtrl+F4");\r
- } else {\r
- style |= WS_SYSMENU;\r
- RemoveMenu(hmenu, IDM_Minimize, MF_BYCOMMAND);\r
- }\r
- SetWindowLongPtr(hwndMain, GWL_STYLE, style);\r
-\r
- for (i=0; menuBarText[tinyLayout][i]; i++) {\r
- ModifyMenu(hmenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP, \r
- (UINT)GetSubMenu(hmenu, i), T_(menuBarText[tinyLayout][i]));\r
- }\r
- DrawMenuBar(hwndMain);\r
- }\r
-\r
- boardWidth = BoardWidth(boardSize, BOARD_WIDTH) + 2*border;\r
- boardHeight = BoardWidth(boardSize, BOARD_HEIGHT) + 2*border;\r
-\r
- /* Get text area sizes */\r
- hdc = GetDC(hwndMain);\r
- if (appData.clockMode) {\r
- snprintf(buf, MSG_SIZ, _("White: %s"), TimeString(23*60*60*1000L));\r
- } else {\r
- snprintf(buf, MSG_SIZ, _("White"));\r
- }\r
- oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);\r
- GetTextExtentPoint(hdc, buf, strlen(buf), &clockSize);\r
- SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);\r
- str = _("We only care about the height here");\r
- GetTextExtentPoint(hdc, str, strlen(str), &messageSize);\r
- SelectObject(hdc, oldFont);\r
- ReleaseDC(hwndMain, hdc);\r
-\r
- /* Compute where everything goes */\r
- if((first.programLogo || second.programLogo) && tinyLayout != 2) {\r
- /* [HGM] logo: if either logo is on, reserve space for it */\r
- logoHeight = 2*clockSize.cy;\r
- leftLogoRect.left = OUTER_MARGIN;\r
- leftLogoRect.right = leftLogoRect.left + 4*clockSize.cy;\r
- leftLogoRect.top = OUTER_MARGIN;\r
- leftLogoRect.bottom = OUTER_MARGIN + logoHeight;\r
-\r
- rightLogoRect.right = OUTER_MARGIN + boardWidth;\r
- rightLogoRect.left = rightLogoRect.right - 4*clockSize.cy;\r
- rightLogoRect.top = OUTER_MARGIN;\r
- rightLogoRect.bottom = OUTER_MARGIN + logoHeight;\r
-\r
-\r
- whiteRect.left = leftLogoRect.right;\r
- whiteRect.right = OUTER_MARGIN + boardWidth/2 - INNER_MARGIN/2;\r
- whiteRect.top = OUTER_MARGIN;\r
- whiteRect.bottom = whiteRect.top + logoHeight;\r
-\r
- blackRect.right = rightLogoRect.left;\r
- blackRect.left = whiteRect.right + INNER_MARGIN;\r
- blackRect.top = whiteRect.top;\r
- blackRect.bottom = whiteRect.bottom;\r
- } else {\r
- whiteRect.left = OUTER_MARGIN;\r
- whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2;\r
- whiteRect.top = OUTER_MARGIN;\r
- whiteRect.bottom = whiteRect.top + clockSize.cy;\r
-\r
- blackRect.left = whiteRect.right + INNER_MARGIN;\r
- blackRect.right = blackRect.left + boardWidth/2 - 1;\r
- blackRect.top = whiteRect.top;\r
- blackRect.bottom = whiteRect.bottom;\r
-\r
- logoHeight = 0; // [HGM] logo: suppress logo after change to tiny layout!\r
- }\r
-\r
- messageRect.left = OUTER_MARGIN + MESSAGE_LINE_LEFTMARGIN;\r
- if (appData.showButtonBar) {\r
- messageRect.right = OUTER_MARGIN + boardWidth // [HGM] logo: expressed independent of clock placement\r
- - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN;\r
- } else {\r
- messageRect.right = OUTER_MARGIN + boardWidth;\r
- }\r
- messageRect.top = whiteRect.bottom + INNER_MARGIN;\r
- messageRect.bottom = messageRect.top + messageSize.cy;\r
-\r
- boardRect.left = OUTER_MARGIN;\r
- boardRect.right = boardRect.left + boardWidth;\r
- boardRect.top = messageRect.bottom + INNER_MARGIN;\r
- boardRect.bottom = boardRect.top + boardHeight;\r
-\r
- sizeInfo[boardSize].cliWidth = boardRect.right + OUTER_MARGIN;\r
- sizeInfo[boardSize].cliHeight = boardRect.bottom + OUTER_MARGIN;\r
- oldTinyLayout = tinyLayout;\r
- winW = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN;\r
- winH = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) +\r
- GetSystemMetrics(SM_CYCAPTION) + boardRect.bottom + OUTER_MARGIN;\r
- winW *= 1 + twoBoards;\r
- if(suppressVisibleEffects) return; // [HGM] when called for filling sizeInfo only\r
- wpMain.width = winW; // [HGM] placement: set through temporary which can used by initial sizing choice\r
- wpMain.height = winH; // without disturbing window attachments\r
- GetWindowRect(hwndMain, &wrect);\r
- SetWindowPos(hwndMain, NULL, 0, 0, wpMain.width, wpMain.height,\r
- SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);\r
-\r
- // [HGM] placement: let attached windows follow size change.\r
- ReattachAfterSize( &oldRect, wpMain.width, wpMain.height, moveHistoryDialog, &wpMoveHistory );\r
- ReattachAfterSize( &oldRect, wpMain.width, wpMain.height, evalGraphDialog, &wpEvalGraph );\r
- ReattachAfterSize( &oldRect, wpMain.width, wpMain.height, engineOutputDialog, &wpEngineOutput );\r
- ReattachAfterSize( &oldRect, wpMain.width, wpMain.height, gameListDialog, &wpGameList );\r
- ReattachAfterSize( &oldRect, wpMain.width, wpMain.height, hwndConsole, &wpConsole );\r
-\r
- /* compensate if menu bar wrapped */\r
- GetClientRect(hwndMain, &crect);\r
- offby = boardRect.bottom + OUTER_MARGIN - crect.bottom;\r
- wpMain.height += offby;\r
- switch (flags) {\r
- case WMSZ_TOPLEFT:\r
- SetWindowPos(hwndMain, NULL, \r
- wrect.right - wpMain.width, wrect.bottom - wpMain.height, \r
- wpMain.width, wpMain.height, SWP_NOCOPYBITS|SWP_NOZORDER);\r
- break;\r
-\r
- case WMSZ_TOPRIGHT:\r
- case WMSZ_TOP:\r
- SetWindowPos(hwndMain, NULL, \r
- wrect.left, wrect.bottom - wpMain.height, \r
- wpMain.width, wpMain.height, SWP_NOCOPYBITS|SWP_NOZORDER);\r
- break;\r
-\r
- case WMSZ_BOTTOMLEFT:\r
- case WMSZ_LEFT:\r
- SetWindowPos(hwndMain, NULL, \r
- wrect.right - wpMain.width, wrect.top, \r
- wpMain.width, wpMain.height, SWP_NOCOPYBITS|SWP_NOZORDER);\r
- break;\r
-\r
- case WMSZ_BOTTOMRIGHT:\r
- case WMSZ_BOTTOM:\r
- case WMSZ_RIGHT:\r
- default:\r
- SetWindowPos(hwndMain, NULL, 0, 0, wpMain.width, wpMain.height,\r
- SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);\r
- break;\r
- }\r
-\r
- hwndPause = NULL;\r
- for (i = 0; i < N_BUTTONS; i++) {\r
- if (buttonDesc[i].hwnd != NULL) {\r
- DestroyWindow(buttonDesc[i].hwnd);\r
- buttonDesc[i].hwnd = NULL;\r
- }\r
- if (appData.showButtonBar) {\r
- buttonDesc[i].hwnd =\r
- CreateWindow("BUTTON", buttonDesc[i].label,\r
- WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,\r
- boardRect.right - BUTTON_WIDTH*(N_BUTTONS-i),\r
- messageRect.top, BUTTON_WIDTH, messageSize.cy, hwndMain,\r
- (HMENU) buttonDesc[i].id,\r
- (HINSTANCE) GetWindowLongPtr(hwndMain, GWLP_HINSTANCE), NULL);\r
- if (tinyLayout == 2) {\r
- SendMessage(buttonDesc[i].hwnd, WM_SETFONT, \r
- (WPARAM)font[boardSize][MESSAGE_FONT]->hf,\r
- MAKELPARAM(FALSE, 0));\r
- }\r
- if (buttonDesc[i].id == IDM_Pause)\r
- hwndPause = buttonDesc[i].hwnd;\r
- buttonDesc[i].wndproc = (WNDPROC)\r
- SetWindowLongPtr(buttonDesc[i].hwnd, GWLP_WNDPROC, (LONG_PTR) ButtonProc);\r
- }\r
- }\r
- if (gridPen != NULL) DeleteObject(gridPen);\r
- if (highlightPen != NULL) DeleteObject(highlightPen);\r
- if (premovePen != NULL) DeleteObject(premovePen);\r
- if (lineGap != 0) {\r
- logbrush.lbStyle = BS_SOLID;\r
- logbrush.lbColor = RGB(0, 0, 0); /* grid pen color = black */\r
- gridPen =\r
- ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,\r
- lineGap, &logbrush, 0, NULL);\r
- logbrush.lbColor = highlightSquareColor;\r
- highlightPen =\r
- ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,\r
- lineGap, &logbrush, 0, NULL);\r
-\r
- logbrush.lbColor = premoveHighlightColor; \r
- premovePen =\r
- ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,\r
- lineGap, &logbrush, 0, NULL);\r
-\r
- /* [HGM] Loop had to be split in part for vert. and hor. lines */\r
- for (i = 0; i < BOARD_HEIGHT + 1; i++) {\r
- gridEndpoints[i*2].x = boardRect.left + lineGap / 2 + border;\r
- gridEndpoints[i*2].y = gridEndpoints[i*2 + 1].y =\r
- boardRect.top + lineGap / 2 + (i * (squareSize + lineGap)) + border;\r
- gridEndpoints[i*2 + 1].x = boardRect.left + lineGap / 2 +\r
- BOARD_WIDTH * (squareSize + lineGap) + border;\r
- gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;\r
- }\r
- for (i = 0; i < BOARD_WIDTH + 1; i++) {\r
- gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].y = boardRect.top + lineGap / 2 + border;\r
- gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].x =\r
- gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].x = boardRect.left +\r
- lineGap / 2 + (i * (squareSize + lineGap)) + border;\r
- gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].y =\r
- boardRect.top + BOARD_HEIGHT * (squareSize + lineGap) + border;\r
- gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;\r
- }\r
- }\r
-\r
- /* [HGM] Licensing requirement */\r
-#ifdef GOTHIC\r
- if(gameInfo.variant == VariantGothic) GothicPopUp( GOTHIC, VariantGothic); else\r
-#endif\r
-#ifdef FALCON\r
- if(gameInfo.variant == VariantFalcon) GothicPopUp( FALCON, VariantFalcon); else\r
-#endif\r
- GothicPopUp( "", VariantNormal);\r
-\r
-\r
-/* if (boardSize == oldBoardSize) return; [HGM] variant might have changed */\r
-\r
- /* Load piece bitmaps for this board size */\r
- for (i=0; i<=2; i++) {\r
- for (piece = WhitePawn;\r
- (int) piece < (int) BlackPawn;\r
- piece = (ChessSquare) ((int) piece + 1)) {\r
- if (pieceBitmap[i][piece] != NULL)\r
- DeleteObject(pieceBitmap[i][piece]);\r
- pieceBitmap[i][piece] = NULL;\r
- }\r
- }\r
-\r
- fontBitmapSquareSize = 0; /* [HGM] render: make sure pieces will be recreated, as we might need others now */\r
-\r
- // Orthodox Chess pieces\r
- pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s");\r
- pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s");\r
- pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "s");\r
- pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "s");\r
- pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "s");\r
- pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "o");\r
- pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "o");\r
- pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "o");\r
- pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "o");\r
- pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "o");\r
- pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "w");\r
- pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "w");\r
- pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "w");\r
- pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w");\r
- pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w");\r
- if( gameInfo.variant == VariantShogi && squareSize <= 72 && squareSize >= 33) {\r
- // in Shogi, Hijack the unused Queen for Lance\r
- pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "s");\r
- pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "o");\r
- pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "w");\r
- } else {\r
- pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s");\r
- pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o");\r
- pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w");\r
- }\r
-\r
- if(squareSize <= 72 && squareSize >= 33) { \r
- /* A & C are available in most sizes now */\r
- if(squareSize != 49 && squareSize != 72 && squareSize != 33) { // Vortex-like\r
- pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "s");\r
- pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "o");\r
- pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "w");\r
- pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");\r
- pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");\r
- pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");\r
- pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "s");\r
- pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "o");\r
- pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "w");\r
- pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");\r
- pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");\r
- pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");\r
- } else { // Smirf-like\r
- if(gameInfo.variant == VariantSChess) {\r
- pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "v", squareSize, "s");\r
- pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "v", squareSize, "o");\r
- pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "v", squareSize, "w");\r
- } else {\r
- pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "s");\r
- pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "o");\r
- pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "w");\r
- }\r
- }\r
- if(gameInfo.variant == VariantGothic) { // Vortex-like\r
- pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "s");\r
- pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "o");\r
- pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "w");\r
- } else if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {\r
- pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "e", squareSize, "s");\r
- pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "e", squareSize, "o");\r
- pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "e", squareSize, "w");\r
- } else { // WinBoard standard\r
- pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s");\r
- pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o");\r
- pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "w");\r
- }\r
- }\r
-\r
-\r
- if(squareSize==72 || squareSize==49 || squareSize==33) { /* experiment with some home-made bitmaps */\r
- pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "s");\r
- pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "o");\r
- pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "w");\r
- pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "s");\r
- pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "o");\r
- pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
- pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "s");\r
- pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "o");\r
- pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "w");\r
- pieceBitmap[0][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "s");\r
- pieceBitmap[1][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "o");\r
- pieceBitmap[2][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "w");\r
- pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "s");\r
- pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "o");\r
- pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "w");\r
- pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "s");\r
- pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "o");\r
- pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "w");\r
- pieceBitmap[0][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "s");\r
- pieceBitmap[1][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "o");\r
- pieceBitmap[2][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "w");\r
- pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "s");\r
- pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "o");\r
- pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "w");\r
- pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");\r
- pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");\r
- pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");\r
- pieceBitmap[0][WhiteAmazon] = DoLoadBitmap(hInst, "l", squareSize, "s");\r
- pieceBitmap[1][WhiteAmazon] = DoLoadBitmap(hInst, "l", squareSize, "o");\r
- pieceBitmap[2][WhiteAmazon] = DoLoadBitmap(hInst, "l", squareSize, "w");\r
- pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s");\r
- pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o");\r
- pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w");\r
- pieceBitmap[0][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "s");\r
- pieceBitmap[1][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "o");\r
- pieceBitmap[2][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "w");\r
- pieceBitmap[0][WhiteCub] = DoLoadBitmap(hInst, "ln", squareSize, "s");\r
- pieceBitmap[1][WhiteCub] = DoLoadBitmap(hInst, "ln", squareSize, "o");\r
- pieceBitmap[2][WhiteCub] = DoLoadBitmap(hInst, "ln", squareSize, "w");\r
- pieceBitmap[0][WhiteWolf] = DoLoadBitmap(hInst, "wolf", squareSize, "s");\r
- pieceBitmap[1][WhiteWolf] = DoLoadBitmap(hInst, "wolf", squareSize, "o");\r
- pieceBitmap[2][WhiteWolf] = DoLoadBitmap(hInst, "wolf", squareSize, "w");\r
- pieceBitmap[0][WhiteCamel] = DoLoadBitmap(hInst, "camel", squareSize, "s");\r
- pieceBitmap[1][WhiteCamel] = DoLoadBitmap(hInst, "camel", squareSize, "o");\r
- pieceBitmap[2][WhiteCamel] = DoLoadBitmap(hInst, "camel", squareSize, "w");\r
- pieceBitmap[0][WhiteZebra] = DoLoadBitmap(hInst, "zebra", squareSize, "s");\r
- pieceBitmap[1][WhiteZebra] = DoLoadBitmap(hInst, "zebra", squareSize, "o");\r
- pieceBitmap[2][WhiteZebra] = DoLoadBitmap(hInst, "n", squareSize, "w");\r
-\r
- if(gameInfo.variant == VariantShogi && BOARD_HEIGHT != 7) { /* promoted Gold representations (but not in Tori!)*/\r
- pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s");\r
- pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "o");\r
- pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
- pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "s");\r
- pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "o");\r
- pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
- pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "s");\r
- pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "o");\r
- pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
- pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "s");\r
- pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "o");\r
- pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
- } else {\r
- pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "s");\r
- pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "o");\r
- pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "w");\r
- pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "s");\r
- pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "o");\r
- pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "w");\r
- pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");\r
- pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");\r
- pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");\r
- pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "s");\r
- pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "o");\r
- pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "w");\r
- }\r
-\r
- } else { /* other size, no special bitmaps available. Use smaller symbols */\r
- if((int)boardSize < 2) minorSize = sizeInfo[0].squareSize;\r
- else minorSize = sizeInfo[(int)boardSize - 2].squareSize;\r
- pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "s");\r
- pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "o");\r
- pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "w");\r
- pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "s");\r
- pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "o");\r
- pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "w");\r
- pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "s");\r
- pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "o");\r
- pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "w");\r
- pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "s");\r
- pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "o");\r
- pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "w");\r
- }\r
-\r
-\r
- if(gameInfo.variant == VariantShogi && squareSize == 58)\r
- /* special Shogi support in this size */\r
- { for (i=0; i<=2; i++) { /* replace all bitmaps */\r
- for (piece = WhitePawn;\r
- (int) piece < (int) BlackPawn;\r
- piece = (ChessSquare) ((int) piece + 1)) {\r
- if (pieceBitmap[i][piece] != NULL)\r
- DeleteObject(pieceBitmap[i][piece]);\r
- }\r
- }\r
- pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");\r
- pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");\r
- pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");\r
- pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");\r
- pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");\r
- pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");\r
- pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");\r
- pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");\r
- pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");\r
- pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");\r
- pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");\r
- pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");\r
- pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");\r
- pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");\r
- pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");\r
- pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");\r
- pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");\r
- pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");\r
- pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");\r
- pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");\r
- pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");\r
- pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");\r
- pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");\r
- pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");\r
- pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");\r
- pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");\r
- pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");\r
- pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");\r
- pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "w");\r
- pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "w");\r
- pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "sr", squareSize, "w");\r
- pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "w");\r
- pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "w");\r
- pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "w");\r
- pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "sw", squareSize, "w");\r
- pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "w");\r
- pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "sp", squareSize, "w");\r
- pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "sn", squareSize, "w");\r
- pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "sr", squareSize, "w");\r
- pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "sr", squareSize, "w");\r
- pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "sl", squareSize, "w");\r
- pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "sw", squareSize, "w");\r
- minorSize = 0;\r
- }\r
-\r
- if(appData.pieceDirectory[0]) for(i=WhitePawn; i<BlackPawn; i++) { // try for all missing pieces with new naming convention\r
- char buf[MSG_SIZ];\r
- if(pieceBitmap[0][i]) continue;\r
- snprintf(buf, MSG_SIZ, "piece%d_", i);\r
- pieceBitmap[0][i] = DoLoadBitmap(hInst, buf, squareSize, "s");\r
- pieceBitmap[1][i] = DoLoadBitmap(hInst, buf, squareSize, "o");\r
- pieceBitmap[2][i] = DoLoadBitmap(hInst, buf, squareSize, "w");\r
- }\r
-}\r
-\r
-HBITMAP\r
-PieceBitmap(ChessSquare p, int kind)\r
-{\r
- if ((int) p >= (int) BlackPawn)\r
- p = (ChessSquare) ((int) p - (int) BlackPawn + (int) WhitePawn);\r
-\r
- return pieceBitmap[kind][(int) p];\r
-}\r
-\r
-/***************************************************************/\r
-\r
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))\r
-#define MAX(a,b) (((a) > (b)) ? (a) : (b))\r
-/*\r
-#define MIN3(a,b,c) (((a) < (b) && (a) < (c)) ? (a) : (((b) < (a) && (b) < (c)) ? (b) : (c)))\r
-#define MAX3(a,b,c) (((a) > (b) && (a) > (c)) ? (a) : (((b) > (a) && (b) > (c)) ? (b) : (c)))\r
-*/\r
-\r
-VOID\r
-SquareToPos(int row, int column, int * x, int * y)\r
-{\r
- if (flipView) {\r
- *x = boardRect.left + lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap) + border;\r
- *y = boardRect.top + lineGap + row * (squareSize + lineGap) + border;\r
- } else {\r
- *x = boardRect.left + lineGap + column * (squareSize + lineGap) + border;\r
- *y = boardRect.top + lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap) + border;\r
- }\r
-}\r
-\r
-VOID\r
-DrawCoordsOnDC(HDC hdc)\r
-{\r
- static char files[] = "0123456789012345678901221098765432109876543210";\r
- static char ranks[] = "wvutsrqponmlkjihgfedcbaabcdefghijklmnopqrstuvw";\r
- char str[2] = { NULLCHAR, NULLCHAR };\r
- int oldMode, oldAlign, x, y, start, i;\r
- HFONT oldFont;\r
- HBRUSH oldBrush;\r
-\r
- if (!appData.showCoords)\r
- return;\r
-\r
- start = flipView ? 1-(ONE!='1') : 45+(ONE!='1')-BOARD_HEIGHT;\r
-\r
- oldBrush = SelectObject(hdc, GetStockObject(BLACK_BRUSH));\r
- oldMode = SetBkMode(hdc, (appData.monoMode ? OPAQUE : TRANSPARENT));\r
- oldAlign = GetTextAlign(hdc);\r
- oldFont = SelectObject(hdc, font[boardSize][COORD_FONT]->hf);\r
-\r
- y = boardRect.top + lineGap;\r
- x = boardRect.left + lineGap + gameInfo.holdingsWidth*(squareSize + lineGap);\r
-\r
- if(border) {\r
- SetTextAlign(hdc, TA_RIGHT|TA_TOP);\r
- x += border - lineGap - 4; y += squareSize - 6;\r
- } else\r
- SetTextAlign(hdc, TA_LEFT|TA_TOP);\r
- for (i = 0; i < BOARD_HEIGHT; i++) {\r
- str[0] = files[start + i];\r
- ExtTextOut(hdc, x + 2 - (border ? gameInfo.holdingsWidth * (squareSize + lineGap) : 0), y + 1, 0, NULL, str, 1, NULL);\r
- y += squareSize + lineGap;\r
- }\r
-\r
- start = flipView ? 23-(BOARD_RGHT-BOARD_LEFT) : 23;\r
-\r
- if(border) {\r
- SetTextAlign(hdc, TA_LEFT|TA_TOP);\r
- x += -border + 4; y += border - squareSize + 6;\r
- } else\r
- SetTextAlign(hdc, TA_RIGHT|TA_BOTTOM);\r
- for (i = 0; i < BOARD_RGHT - BOARD_LEFT; i++) {\r
- str[0] = ranks[start + i];\r
- ExtTextOut(hdc, x + squareSize - 2, y - 1, 0, NULL, str, 1, NULL);\r
- x += squareSize + lineGap;\r
- } \r
-\r
- SelectObject(hdc, oldBrush);\r
- SetBkMode(hdc, oldMode);\r
- SetTextAlign(hdc, oldAlign);\r
- SelectObject(hdc, oldFont);\r
-}\r
-\r
-VOID\r
-DrawGridOnDC(HDC hdc)\r
-{\r
- HPEN oldPen;\r
- \r
- if (lineGap != 0) {\r
- oldPen = SelectObject(hdc, gridPen);\r
- PolyPolyline(hdc, gridEndpoints, gridVertexCounts, BOARD_WIDTH+BOARD_HEIGHT + 2);\r
- SelectObject(hdc, oldPen);\r
- }\r
-}\r
-\r
-#define HIGHLIGHT_PEN 0\r
-#define PREMOVE_PEN 1\r
-\r
-VOID\r
-DrawHighlightOnDC(HDC hdc, BOOLEAN on, int x, int y, int pen)\r
-{\r
- int x1, y1;\r
- HPEN oldPen, hPen;\r
- if (lineGap == 0) return;\r
- if (flipView) {\r
- x1 = boardRect.left +\r
- lineGap/2 + ((BOARD_WIDTH-1)-x) * (squareSize + lineGap) + border;\r
- y1 = boardRect.top +\r
- lineGap/2 + y * (squareSize + lineGap) + border;\r
- } else {\r
- x1 = boardRect.left +\r
- lineGap/2 + x * (squareSize + lineGap) + border;\r
- y1 = boardRect.top +\r
- lineGap/2 + ((BOARD_HEIGHT-1)-y) * (squareSize + lineGap) + border;\r
- }\r
- hPen = pen ? premovePen : highlightPen;\r
- oldPen = SelectObject(hdc, on ? hPen : gridPen);\r
- MoveToEx(hdc, x1, y1, NULL);\r
- LineTo(hdc, x1 + squareSize + lineGap, y1);\r
- LineTo(hdc, x1 + squareSize + lineGap, y1 + squareSize + lineGap);\r
- LineTo(hdc, x1, y1 + squareSize + lineGap);\r
- LineTo(hdc, x1, y1);\r
- SelectObject(hdc, oldPen);\r
-}\r
-\r
-VOID\r
-DrawHighlightsOnDC(HDC hdc, HighlightInfo *h, int pen)\r
-{\r
- int i;\r
- for (i=0; i<2; i++) {\r
- if (h->sq[i].x >= 0 && h->sq[i].y >= 0) \r
- DrawHighlightOnDC(hdc, TRUE,\r
- h->sq[i].x, h->sq[i].y,\r
- pen);\r
- }\r
-}\r
-\r
-/* Note: sqcolor is used only in monoMode */\r
-/* Note that this code is largely duplicated in woptions.c,\r
- function DrawSampleSquare, so that needs to be updated too */\r
-VOID\r
-DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, HDC tmphdc)\r
-{\r
- HBITMAP oldBitmap;\r
- HBRUSH oldBrush;\r
- int tmpSize;\r
-\r
- if (appData.blindfold) return;\r
-\r
- /* [AS] Use font-based pieces if needed */\r
- if( fontBitmapSquareSize >= 0 && (squareSize > 32 || gameInfo.variant >= VariantShogi)) {\r
- /* Create piece bitmaps, or do nothing if piece set is up to date */\r
- CreatePiecesFromFont();\r
-\r
- if( fontBitmapSquareSize == squareSize ) {\r
- int index = TranslatePieceToFontPiece(piece);\r
-\r
- SelectObject( tmphdc, hPieceMask[ index ] );\r
-\r
- if(appData.upsideDown ? color==flipView : (flipView && gameInfo.variant == VariantShogi))\r
- StretchBlt(hdc, x+squareSize, y+squareSize, -squareSize, -squareSize, tmphdc, 0, 0, squareSize, squareSize, SRCAND);\r
- else\r
- BitBlt( hdc,\r
- x, y,\r
- squareSize, squareSize,\r
- tmphdc,\r
- 0, 0,\r
- SRCAND );\r
-\r
- SelectObject( tmphdc, hPieceFace[ index ] );\r
-\r
- if(appData.upsideDown ? color==flipView : (flipView && gameInfo.variant == VariantShogi))\r
- StretchBlt(hdc, x+squareSize, y+squareSize, -squareSize, -squareSize, tmphdc, 0, 0, squareSize, squareSize, SRCPAINT);\r
- else\r
- BitBlt( hdc,\r
- x, y,\r
- squareSize, squareSize,\r
- tmphdc,\r
- 0, 0,\r
- SRCPAINT );\r
-\r
- return;\r
- }\r
- }\r
-\r
- if (appData.monoMode) {\r
- SelectObject(tmphdc, PieceBitmap(piece, \r
- color == sqcolor ? OUTLINE_PIECE : SOLID_PIECE));\r
- BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0,\r
- sqcolor ? SRCCOPY : NOTSRCCOPY);\r
- } else {\r
- HBRUSH xBrush = whitePieceBrush;\r
- tmpSize = squareSize;\r
- if(appData.pieceDirectory[0]) xBrush = GetStockObject(WHITE_BRUSH);\r
- if(minorSize &&\r
- ((piece >= (int)WhiteNightrider && piece <= WhiteGrasshopper) ||\r
- (piece >= (int)BlackNightrider && piece <= BlackGrasshopper)) ) {\r
- /* [HGM] no bitmap available for promoted pieces in Crazyhouse */\r
- /* Bitmaps of smaller size are substituted, but we have to align them */\r
- x += (squareSize - minorSize)>>1;\r
- y += squareSize - minorSize - 2;\r
- tmpSize = minorSize;\r
- }\r
- if (color || appData.allWhite ) {\r
- oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, WHITE_PIECE));\r
- if( color )\r
- oldBrush = SelectObject(hdc, xBrush);\r
- else oldBrush = SelectObject(hdc, blackPieceBrush);\r
- if(appData.upsideDown && color==flipView)\r
- StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, 0x00B8074A);\r
- else\r
- BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);\r
- /* Use black for outline of white pieces */\r
- SelectObject(tmphdc, PieceBitmap(piece, OUTLINE_PIECE));\r
- if(appData.upsideDown && color==flipView)\r
- StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, SRCAND);\r
- else\r
- BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, SRCAND);\r
- } else if(appData.pieceDirectory[0]) {\r
- oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, WHITE_PIECE));\r
- oldBrush = SelectObject(hdc, xBrush);\r
- if(appData.upsideDown && color==flipView)\r
- StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, 0x00B8074A);\r
- else\r
- BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);\r
- SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE));\r
- if(appData.upsideDown && color==flipView)\r
- StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, SRCAND);\r
- else\r
- BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, SRCAND);\r
- } else {\r
- /* Use square color for details of black pieces */\r
- oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE));\r
- oldBrush = SelectObject(hdc, blackPieceBrush);\r
- if(appData.upsideDown && !flipView)\r
- StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, 0x00B8074A);\r
- else\r
- BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);\r
- }\r
- SelectObject(hdc, oldBrush);\r
- SelectObject(tmphdc, oldBitmap);\r
- }\r
-}\r
-\r
-/* [AS] Compute a drawing mode for a square, based on specified settings (see DrawTile) */\r
-int GetBackTextureMode( int algo )\r
-{\r
- int result = BACK_TEXTURE_MODE_DISABLED;\r
-\r
- switch( algo ) \r
- {\r
- case BACK_TEXTURE_MODE_PLAIN:\r
- result = 1; /* Always use identity map */\r
- break;\r
- case BACK_TEXTURE_MODE_FULL_RANDOM:\r
- result = 1 + (myrandom() % 3); /* Pick a transformation at random */\r
- break;\r
- }\r
-\r
- return result;\r
-}\r
-\r
-/* \r
- [AS] Compute and save texture drawing info, otherwise we may not be able\r
- to handle redraws cleanly (as random numbers would always be different).\r
-*/\r
-VOID RebuildTextureSquareInfo()\r
-{\r
- BITMAP bi;\r
- int lite_w = 0;\r
- int lite_h = 0;\r
- int dark_w = 0;\r
- int dark_h = 0;\r
- int row;\r
- int col;\r
-\r
- ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );\r
-\r
- if( liteBackTexture != NULL ) {\r
- if( GetObject( liteBackTexture, sizeof(bi), &bi ) > 0 ) {\r
- lite_w = bi.bmWidth;\r
- lite_h = bi.bmHeight;\r
- }\r
- }\r
-\r
- if( darkBackTexture != NULL ) {\r
- if( GetObject( darkBackTexture, sizeof(bi), &bi ) > 0 ) {\r
- dark_w = bi.bmWidth;\r
- dark_h = bi.bmHeight;\r
- }\r
- }\r
-\r
- for( row=0; row<BOARD_HEIGHT; row++ ) {\r
- for( col=0; col<BOARD_WIDTH; col++ ) {\r
- if( (col + row) & 1 ) {\r
- /* Lite square */\r
- if( lite_w >= squareSize && lite_h >= squareSize ) {\r
- if( lite_w >= squareSize*BOARD_WIDTH )\r
- backTextureSquareInfo[row][col].x = (2*col+1)*lite_w/(2*BOARD_WIDTH) - squareSize/2; /* [HGM] cut out of center of virtual square */\r
- else\r
- backTextureSquareInfo[row][col].x = col * (lite_w - squareSize) / (BOARD_WIDTH-1); /* [HGM] divide by size-1 in stead of size! */\r
- if( lite_h >= squareSize*BOARD_HEIGHT )\r
- backTextureSquareInfo[row][col].y = (2*(BOARD_HEIGHT-row)-1)*lite_h/(2*BOARD_HEIGHT) - squareSize/2;\r
- else\r
- backTextureSquareInfo[row][col].y = (BOARD_HEIGHT-1-row) * (lite_h - squareSize) / (BOARD_HEIGHT-1);\r
- backTextureSquareInfo[row][col].mode = GetBackTextureMode(liteBackTextureMode);\r
- }\r
- }\r
- else {\r
- /* Dark square */\r
- if( dark_w >= squareSize && dark_h >= squareSize ) {\r
- if( dark_w >= squareSize*BOARD_WIDTH )\r
- backTextureSquareInfo[row][col].x = (2*col+1) * dark_w / (2*BOARD_WIDTH) - squareSize/2;\r
- else\r
- backTextureSquareInfo[row][col].x = col * (dark_w - squareSize) / (BOARD_WIDTH-1);\r
- if( dark_h >= squareSize*BOARD_HEIGHT )\r
- backTextureSquareInfo[row][col].y = (2*(BOARD_HEIGHT-row)-1) * dark_h / (2*BOARD_HEIGHT) - squareSize/2;\r
- else\r
- backTextureSquareInfo[row][col].y = (BOARD_HEIGHT-1-row) * (dark_h - squareSize) / (BOARD_HEIGHT-1);\r
- backTextureSquareInfo[row][col].mode = GetBackTextureMode(darkBackTextureMode);\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-/* [AS] Arrow highlighting support */\r
-\r
-static double A_WIDTH = 5; /* Width of arrow body */\r
-\r
-#define A_HEIGHT_FACTOR 6 /* Length of arrow "point", relative to body width */\r
-#define A_WIDTH_FACTOR 3 /* Width of arrow "point", relative to body width */\r
-\r
-static double Sqr( double x )\r
-{\r
- return x*x;\r
-}\r
-\r
-static int Round( double x )\r
-{\r
- return (int) (x + 0.5);\r
-}\r
-\r
-/* Draw an arrow between two points using current settings */\r
-VOID DrawArrowBetweenPoints( HDC hdc, int s_x, int s_y, int d_x, int d_y )\r
-{\r
- POINT arrow[7];\r
- double dx, dy, j, k, x, y;\r
-\r
- if( d_x == s_x ) {\r
- int h = (d_y > s_y) ? +A_WIDTH*A_HEIGHT_FACTOR : -A_WIDTH*A_HEIGHT_FACTOR;\r
-\r
- arrow[0].x = s_x + A_WIDTH + 0.5;\r
- arrow[0].y = s_y;\r
-\r
- arrow[1].x = s_x + A_WIDTH + 0.5;\r
- arrow[1].y = d_y - h;\r
-\r
- arrow[2].x = arrow[1].x + A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5;\r
- arrow[2].y = d_y - h;\r
-\r
- arrow[3].x = d_x;\r
- arrow[3].y = d_y;\r
-\r
- arrow[5].x = arrow[1].x - 2*A_WIDTH + 0.5;\r
- arrow[5].y = d_y - h;\r
-\r
- arrow[4].x = arrow[5].x - A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5;\r
- arrow[4].y = d_y - h;\r
-\r
- arrow[6].x = arrow[1].x - 2*A_WIDTH + 0.5;\r
- arrow[6].y = s_y;\r
- }\r
- else if( d_y == s_y ) {\r
- int w = (d_x > s_x) ? +A_WIDTH*A_HEIGHT_FACTOR : -A_WIDTH*A_HEIGHT_FACTOR;\r
-\r
- arrow[0].x = s_x;\r
- arrow[0].y = s_y + A_WIDTH + 0.5;\r
-\r
- arrow[1].x = d_x - w;\r
- arrow[1].y = s_y + A_WIDTH + 0.5;\r
-\r
- arrow[2].x = d_x - w;\r
- arrow[2].y = arrow[1].y + A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5;\r
-\r
- arrow[3].x = d_x;\r
- arrow[3].y = d_y;\r
-\r
- arrow[5].x = d_x - w;\r
- arrow[5].y = arrow[1].y - 2*A_WIDTH + 0.5;\r
-\r
- arrow[4].x = d_x - w;\r
- arrow[4].y = arrow[5].y - A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5;\r
-\r
- arrow[6].x = s_x;\r
- arrow[6].y = arrow[1].y - 2*A_WIDTH + 0.5;\r
- }\r
- else {\r
- /* [AS] Needed a lot of paper for this! :-) */\r
- dy = (double) (d_y - s_y) / (double) (d_x - s_x);\r
- dx = (double) (s_x - d_x) / (double) (s_y - d_y);\r
- \r
- j = sqrt( Sqr(A_WIDTH) / (1.0 + Sqr(dx)) );\r
-\r
- k = sqrt( Sqr(A_WIDTH*A_HEIGHT_FACTOR) / (1.0 + Sqr(dy)) );\r
-\r
- x = s_x;\r
- y = s_y;\r
-\r
- arrow[0].x = Round(x - j);\r
- arrow[0].y = Round(y + j*dx);\r
-\r
- arrow[1].x = Round(arrow[0].x + 2*j); // [HGM] prevent width to be affected by rounding twice\r
- arrow[1].y = Round(arrow[0].y - 2*j*dx);\r
-\r
- if( d_x > s_x ) {\r
- x = (double) d_x - k;\r
- y = (double) d_y - k*dy;\r
- }\r
- else {\r
- x = (double) d_x + k;\r
- y = (double) d_y + k*dy;\r
- }\r
-\r
- x = Round(x); y = Round(y); // [HGM] make sure width of shaft is rounded the same way on both ends\r
-\r
- arrow[6].x = Round(x - j);\r
- arrow[6].y = Round(y + j*dx);\r
-\r
- arrow[2].x = Round(arrow[6].x + 2*j);\r
- arrow[2].y = Round(arrow[6].y - 2*j*dx);\r
-\r
- arrow[3].x = Round(arrow[2].x + j*(A_WIDTH_FACTOR-1));\r
- arrow[3].y = Round(arrow[2].y - j*(A_WIDTH_FACTOR-1)*dx);\r
-\r
- arrow[4].x = d_x;\r
- arrow[4].y = d_y;\r
-\r
- arrow[5].x = Round(arrow[6].x - j*(A_WIDTH_FACTOR-1));\r
- arrow[5].y = Round(arrow[6].y + j*(A_WIDTH_FACTOR-1)*dx);\r
- }\r
-\r
- Polygon( hdc, arrow, 7 );\r
-}\r
-\r
-/* [AS] Draw an arrow between two squares */\r
-VOID DrawArrowBetweenSquares( HDC hdc, int s_col, int s_row, int d_col, int d_row )\r
-{\r
- int s_x, s_y, d_x, d_y;\r
- HPEN hpen;\r
- HPEN holdpen;\r
- HBRUSH hbrush;\r
- HBRUSH holdbrush;\r
- LOGBRUSH stLB;\r
-\r
- if( s_col == d_col && s_row == d_row ) {\r
- return;\r
- }\r
-\r
- /* Get source and destination points */\r
- SquareToPos( s_row, s_col, &s_x, &s_y);\r
- SquareToPos( d_row, d_col, &d_x, &d_y);\r
-\r
- if( d_y > s_y ) {\r
- d_y += squareSize / 2 - squareSize / 4; // [HGM] round towards same centers on all sides!\r
- }\r
- else if( d_y < s_y ) {\r
- d_y += squareSize / 2 + squareSize / 4;\r
- }\r
- else {\r
- d_y += squareSize / 2;\r
- }\r
-\r
- if( d_x > s_x ) {\r
- d_x += squareSize / 2 - squareSize / 4;\r
- }\r
- else if( d_x < s_x ) {\r
- d_x += squareSize / 2 + squareSize / 4;\r
- }\r
- else {\r
- d_x += squareSize / 2;\r
- }\r
-\r
- s_x += squareSize / 2;\r
- s_y += squareSize / 2;\r
-\r
- /* Adjust width */\r
- A_WIDTH = squareSize / 14.; //[HGM] make float\r
-\r
- /* Draw */\r
- stLB.lbStyle = BS_SOLID;\r
- stLB.lbColor = appData.highlightArrowColor;\r
- stLB.lbHatch = 0;\r
-\r
- hpen = CreatePen( PS_SOLID, 2, RGB(0x00,0x00,0x00) );\r
- holdpen = SelectObject( hdc, hpen );\r
- hbrush = CreateBrushIndirect( &stLB );\r
- holdbrush = SelectObject( hdc, hbrush );\r
-\r
- DrawArrowBetweenPoints( hdc, s_x, s_y, d_x, d_y );\r
-\r
- SelectObject( hdc, holdpen );\r
- SelectObject( hdc, holdbrush );\r
- DeleteObject( hpen );\r
- DeleteObject( hbrush );\r
-}\r
-\r
-BOOL HasHighlightInfo()\r
-{\r
- BOOL result = FALSE;\r
-\r
- if( highlightInfo.sq[0].x >= 0 && highlightInfo.sq[0].y >= 0 &&\r
- highlightInfo.sq[1].x >= 0 && highlightInfo.sq[1].y >= 0 )\r
- {\r
- result = TRUE;\r
- }\r
-\r
- return result;\r
-\r
-\r
-\r
-}\r
-\r
-BOOL IsDrawArrowEnabled()\r
-{\r
- BOOL result = FALSE;\r
-\r
- if( appData.highlightMoveWithArrow && squareSize >= 32 ) {\r
- result = TRUE;\r
- }\r
-\r
- return result;\r
-}\r
-\r
-VOID DrawArrowHighlight( HDC hdc )\r
-{\r
- if( IsDrawArrowEnabled() && HasHighlightInfo() ) {\r
- DrawArrowBetweenSquares( hdc,\r
- highlightInfo.sq[0].x, highlightInfo.sq[0].y,\r
- highlightInfo.sq[1].x, highlightInfo.sq[1].y );\r
- }\r
-}\r
-\r
-HRGN GetArrowHighlightClipRegion( HDC hdc )\r
-{\r
- HRGN result = NULL;\r
-\r
- if( HasHighlightInfo() ) {\r
- int x1, y1, x2, y2;\r
- int sx, sy, dx, dy;\r
-\r
- SquareToPos(highlightInfo.sq[0].y, highlightInfo.sq[0].x, &x1, &y1 );\r
- SquareToPos(highlightInfo.sq[1].y, highlightInfo.sq[1].x, &x2, &y2 );\r
-\r
- sx = MIN( x1, x2 );\r
- sy = MIN( y1, y2 );\r
- dx = MAX( x1, x2 ) + squareSize;\r
- dy = MAX( y1, y2 ) + squareSize;\r
-\r
- result = CreateRectRgn( sx, sy, dx, dy );\r
- }\r
-\r
- return result;\r
-}\r
-\r
-/*\r
- Warning: this function modifies the behavior of several other functions. \r
- \r
- Basically, Winboard is optimized to avoid drawing the whole board if not strictly\r
- needed. Unfortunately, the decision whether or not to perform a full or partial\r
- repaint is scattered all over the place, which is not good for features such as\r
- "arrow highlighting" that require a full repaint of the board.\r
-\r
- So, I've tried to patch the code where I thought it made sense (e.g. after or during\r
- user interaction, when speed is not so important) but especially to avoid errors\r
- in the displayed graphics.\r
-\r
- In such patched places, I always try refer to this function so there is a single\r
- place to maintain knowledge.\r
- \r
- To restore the original behavior, just return FALSE unconditionally.\r
-*/\r
-BOOL IsFullRepaintPreferrable()\r
-{\r
- BOOL result = FALSE;\r
-\r
- if( (appData.highlightLastMove || appData.highlightDragging) && IsDrawArrowEnabled() ) {\r
- /* Arrow may appear on the board */\r
- result = TRUE;\r
- }\r
-\r
- return result;\r
-}\r
-\r
-/* \r
- This function is called by DrawPosition to know whether a full repaint must\r
- be forced or not.\r
-\r
- Only DrawPosition may directly call this function, which makes use of \r
- some state information. Other function should call DrawPosition specifying \r
- the repaint flag, and can use IsFullRepaintPreferrable if needed.\r
-*/\r
-BOOL DrawPositionNeedsFullRepaint()\r
-{\r
- BOOL result = FALSE;\r
-\r
- /* \r
- Probably a slightly better policy would be to trigger a full repaint\r
- when animInfo.piece changes state (i.e. empty -> non-empty and viceversa),\r
- but animation is fast enough that it's difficult to notice.\r
- */\r
- if( animInfo.piece == EmptySquare ) {\r
- if( (appData.highlightLastMove || appData.highlightDragging) && IsDrawArrowEnabled() /*&& HasHighlightInfo()*/ ) {\r
- result = TRUE;\r
- }\r
- }\r
-\r
- return result;\r
-}\r
-\r
-static HBITMAP borderBitmap;\r
-\r
-VOID\r
-DrawBackgroundOnDC(HDC hdc)\r
-{\r
- \r
- BITMAP bi;\r
- HDC tmphdc;\r
- HBITMAP hbm;\r
- static char oldBorder[MSG_SIZ];\r
- int w = 600, h = 600, mode;\r
-\r
- if(strcmp(appData.border, oldBorder)) { // load new one when old one no longer valid\r
- strncpy(oldBorder, appData.border, MSG_SIZ-1);\r
- borderBitmap = LoadImage( 0, appData.border, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); \r
- }\r
- if(borderBitmap == NULL) { // loading failed, use white\r
- FillRect( hdc, &boardRect, whitePieceBrush );\r
- return;\r
- }\r
- tmphdc = CreateCompatibleDC(hdc);\r
- hbm = SelectObject(tmphdc, borderBitmap);\r
- if( GetObject( borderBitmap, sizeof(bi), &bi ) > 0 ) {\r
- w = bi.bmWidth;\r
- h = bi.bmHeight;\r
- }\r
- mode = SetStretchBltMode(hdc, COLORONCOLOR);\r
- StretchBlt(hdc, boardRect.left, boardRect.top, boardRect.right - boardRect.left, \r
- boardRect.bottom - boardRect.top, tmphdc, 0, 0, w, h, SRCCOPY);\r
- SetStretchBltMode(hdc, mode);\r
- SelectObject(tmphdc, hbm);\r
- DeleteDC(tmphdc);\r
-}\r
-\r
-VOID\r
-DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc)\r
-{\r
- int row, column, x, y, square_color, piece_color;\r
- ChessSquare piece;\r
- HBRUSH oldBrush;\r
- HDC texture_hdc = NULL;\r
-\r
- /* [AS] Initialize background textures if needed */\r
- if( liteBackTexture != NULL || darkBackTexture != NULL ) {\r
- static int backTextureBoardSize; /* [HGM] boardsize: also new texture if board format changed */\r
- if( backTextureSquareSize != squareSize \r
- || backTextureBoardSize != BOARD_WIDTH+BOARD_FILES*BOARD_HEIGHT) {\r
- backTextureBoardSize = BOARD_WIDTH+BOARD_FILES*BOARD_HEIGHT;\r
- backTextureSquareSize = squareSize;\r
- RebuildTextureSquareInfo();\r
- }\r
-\r
- texture_hdc = CreateCompatibleDC( hdc );\r
- }\r
-\r
- for (row = 0; row < BOARD_HEIGHT; row++) {\r
- for (column = 0; column < BOARD_WIDTH; column++) {\r
- \r
- SquareToPos(row, column, &x, &y);\r
-\r
- piece = board[row][column];\r
-\r
- square_color = ((column + row) % 2) == 1;\r
- if( gameInfo.variant == VariantXiangqi ) {\r
- square_color = !InPalace(row, column);\r
- if(BOARD_HEIGHT&1) { if(row==BOARD_HEIGHT/2) square_color ^= 1; }\r
- else if(row < BOARD_HEIGHT/2) square_color ^= 1;\r
- }\r
- piece_color = (int) piece < (int) BlackPawn;\r
-\r
-\r
- /* [HGM] holdings file: light square or black */\r
- if(column == BOARD_LEFT-2) {\r
- if( row > BOARD_HEIGHT - gameInfo.holdingsSize - 1 )\r
- square_color = 1;\r
- else {\r
- DisplayHoldingsCount(hdc, x, y, 0, 0); /* black out */\r
- continue;\r
- }\r
- } else\r
- if(column == BOARD_RGHT + 1 ) {\r
- if( row < gameInfo.holdingsSize )\r
- square_color = 1;\r
- else {\r
- DisplayHoldingsCount(hdc, x, y, 0, 0); \r
- continue;\r
- }\r
- }\r
- if(column == BOARD_LEFT-1 ) /* left align */\r
- DisplayHoldingsCount(hdc, x, y, flipView, (int) board[row][column]);\r
- else if( column == BOARD_RGHT) /* right align */\r
- DisplayHoldingsCount(hdc, x, y, !flipView, (int) board[row][column]);\r
- else if( piece == DarkSquare) DisplayHoldingsCount(hdc, x, y, 0, 0);\r
- else\r
- if (appData.monoMode) {\r
- if (piece == EmptySquare) {\r
- BitBlt(hdc, x, y, squareSize, squareSize, 0, 0, 0,\r
- square_color ? WHITENESS : BLACKNESS);\r
- } else {\r
- DrawPieceOnDC(hdc, piece, piece_color, square_color, x, y, tmphdc);\r
- }\r
- } \r
- else if( appData.useBitmaps && backTextureSquareInfo[row][column].mode > 0 ) {\r
- /* [AS] Draw the square using a texture bitmap */\r
- HBITMAP hbm = SelectObject( texture_hdc, square_color ? liteBackTexture : darkBackTexture );\r
- int r = row, c = column; // [HGM] do not flip board in flipView\r
- if(flipView) { r = BOARD_HEIGHT-1 - r; c = BOARD_WIDTH-1 - c; }\r
-\r
- DrawTile( x, y, \r
- squareSize, squareSize, \r
- hdc, \r
- texture_hdc,\r
- backTextureSquareInfo[r][c].mode,\r
- backTextureSquareInfo[r][c].x,\r
- backTextureSquareInfo[r][c].y );\r
-\r
- SelectObject( texture_hdc, hbm );\r
-\r
- if (piece != EmptySquare) {\r
- DrawPieceOnDC(hdc, piece, piece_color, -1, x, y, tmphdc);\r
- }\r
- }\r
- else {\r
- HBRUSH brush = square_color ? lightSquareBrush : darkSquareBrush;\r
-\r
- oldBrush = SelectObject(hdc, brush );\r
- BitBlt(hdc, x, y, squareSize, squareSize, 0, 0, 0, PATCOPY);\r
- SelectObject(hdc, oldBrush);\r
- if (piece != EmptySquare)\r
- DrawPieceOnDC(hdc, piece, piece_color, -1, x, y, tmphdc);\r
- }\r
- }\r
- }\r
-\r
- if( texture_hdc != NULL ) {\r
- DeleteDC( texture_hdc );\r
- }\r
-}\r
-\r
-int saveDiagFlag = 0; FILE *diagFile; // [HGM] diag\r
-void fputDW(FILE *f, int x)\r
-{\r
- fputc(x & 255, f);\r
- fputc(x>>8 & 255, f);\r
- fputc(x>>16 & 255, f);\r
- fputc(x>>24 & 255, f);\r
-}\r
-\r
-#define MAX_CLIPS 200 /* more than enough */\r
-\r
-VOID\r
-DrawLogoOnDC(HDC hdc, RECT logoRect, HBITMAP logo)\r
-{\r
-// HBITMAP bufferBitmap;\r
- BITMAP bi;\r
-// RECT Rect;\r
- HDC tmphdc;\r
- HBITMAP hbm;\r
- int w = 100, h = 50;\r
-\r
- if(logo == NULL) {\r
- if(!logoHeight) return;\r
- FillRect( hdc, &logoRect, whitePieceBrush );\r
- }\r
-// GetClientRect(hwndMain, &Rect);\r
-// bufferBitmap = CreateCompatibleBitmap(hdc, Rect.right-Rect.left+1,\r
-// Rect.bottom-Rect.top+1);\r
- tmphdc = CreateCompatibleDC(hdc);\r
- hbm = SelectObject(tmphdc, logo);\r
- if( GetObject( logo, sizeof(bi), &bi ) > 0 ) {\r
- w = bi.bmWidth;\r
- h = bi.bmHeight;\r
- }\r
- StretchBlt(hdc, logoRect.left, logoRect.top, logoRect.right - logoRect.left, \r
- logoRect.bottom - logoRect.top, tmphdc, 0, 0, w, h, SRCCOPY);\r
- SelectObject(tmphdc, hbm);\r
- DeleteDC(tmphdc);\r
-}\r
-\r
-VOID\r
-DisplayLogos()\r
-{\r
- if(logoHeight) {\r
- HDC hdc = GetDC(hwndMain);\r
- HBITMAP whiteLogo = (HBITMAP) first.programLogo, blackLogo = (HBITMAP) second.programLogo;\r
- if(appData.autoLogo) {\r
- \r
- switch(gameMode) { // pick logos based on game mode\r
- case IcsObserving:\r
- whiteLogo = second.programLogo; // ICS logo\r
- blackLogo = second.programLogo;\r
- default:\r
- break;\r
- case IcsPlayingWhite:\r
- if(!appData.zippyPlay) whiteLogo = userLogo;\r
- blackLogo = second.programLogo; // ICS logo\r
- break;\r
- case IcsPlayingBlack:\r
- whiteLogo = second.programLogo; // ICS logo\r
- blackLogo = appData.zippyPlay ? first.programLogo : userLogo;\r
- break;\r
- case TwoMachinesPlay:\r
- if(first.twoMachinesColor[0] == 'b') {\r
- whiteLogo = second.programLogo;\r
- blackLogo = first.programLogo;\r
- }\r
- break;\r
- case MachinePlaysWhite:\r
- blackLogo = userLogo;\r
- break;\r
- case MachinePlaysBlack:\r
- whiteLogo = userLogo;\r
- blackLogo = first.programLogo;\r
- }\r
- }\r
- DrawLogoOnDC(hdc, leftLogoRect, flipClock ? blackLogo : whiteLogo);\r
- DrawLogoOnDC(hdc, rightLogoRect, flipClock ? whiteLogo : blackLogo);\r
- ReleaseDC(hwndMain, hdc);\r
- }\r
-}\r
-\r
-void\r
-UpdateLogos(int display)\r
-{ // called after loading new engine(s), in tourney or from menu\r
- LoadLogo(&first, 0, FALSE);\r
- LoadLogo(&second, 1, appData.icsActive);\r
- InitDrawingSizes(-2, 0); // adapt layout of board window to presence/absence of logos\r
- if(display) DisplayLogos();\r
-}\r
-\r
-static HDC hdcSeek;\r
-\r
-// [HGM] seekgraph\r
-void DrawSeekAxis( int x, int y, int xTo, int yTo )\r
-{\r
- POINT stPt;\r
- HPEN hp = SelectObject( hdcSeek, gridPen );\r
- MoveToEx( hdcSeek, boardRect.left+x, boardRect.top+y, &stPt );\r
- LineTo( hdcSeek, boardRect.left+xTo, boardRect.top+yTo );\r
- SelectObject( hdcSeek, hp );\r
-}\r
-\r
-// front-end wrapper for drawing functions to do rectangles\r
-void DrawSeekBackground( int left, int top, int right, int bottom )\r
-{\r
- HPEN hp;\r
- RECT rc;\r
-\r
- if (hdcSeek == NULL) {\r
- hdcSeek = GetDC(hwndMain);\r
- if (!appData.monoMode) {\r
- SelectPalette(hdcSeek, hPal, FALSE);\r
- RealizePalette(hdcSeek);\r
- }\r
- }\r
- hp = SelectObject( hdcSeek, gridPen );\r
- rc.top = boardRect.top+top; rc.left = boardRect.left+left; \r
- rc.bottom = boardRect.top+bottom; rc.right = boardRect.left+right;\r
- FillRect( hdcSeek, &rc, lightSquareBrush );\r
- SelectObject( hdcSeek, hp );\r
-}\r
-\r
-// front-end wrapper for putting text in graph\r
-void DrawSeekText(char *buf, int x, int y)\r
-{\r
- SIZE stSize;\r
- SetBkMode( hdcSeek, TRANSPARENT );\r
- GetTextExtentPoint32( hdcSeek, buf, strlen(buf), &stSize );\r
- TextOut( hdcSeek, boardRect.left+x-3, boardRect.top+y-stSize.cy/2, buf, strlen(buf) );\r
-}\r
-\r
-void DrawSeekDot(int x, int y, int color)\r
-{\r
- int square = color & 0x80;\r
- HBRUSH oldBrush = SelectObject(hdcSeek, \r
- color == 0 ? markerBrush[1] : color == 1 ? darkSquareBrush : explodeBrush);\r
- color &= 0x7F;\r
- if(square)\r
- Rectangle(hdcSeek, boardRect.left+x - squareSize/9, boardRect.top+y - squareSize/9,\r
- boardRect.left+x + squareSize/9, boardRect.top+y + squareSize/9);\r
- else\r
- Ellipse(hdcSeek, boardRect.left+x - squareSize/8, boardRect.top+y - squareSize/8,\r
- boardRect.left+x + squareSize/8, boardRect.top+y + squareSize/8);\r
- SelectObject(hdcSeek, oldBrush);\r
-}\r
-\r
-void DrawSeekOpen()\r
-{\r
-}\r
-\r
-void DrawSeekClose()\r
-{\r
-}\r
-\r
-\r
-\r
-VOID\r
-HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)\r
-{\r
- static Board lastReq[2], lastDrawn[2];\r
- static HighlightInfo lastDrawnHighlight, lastDrawnPremove;\r
- static int lastDrawnFlipView = 0;\r
- static int lastReqValid[2] = {0, 0}, lastDrawnValid[2] = {0, 0};\r
- int releaseDC, x, y, x2, y2, row, column, num_clips = 0, i;\r
- HDC tmphdc;\r
- HDC hdcmem;\r
- HBITMAP bufferBitmap;\r
- HBITMAP oldBitmap;\r
- RECT Rect;\r
- HRGN clips[MAX_CLIPS];\r
- ChessSquare dragged_piece = EmptySquare;\r
- int nr = twoBoards*partnerUp;\r
-\r
- /* I'm undecided on this - this function figures out whether a full\r
- * repaint is necessary on its own, so there's no real reason to have the\r
- * caller tell it that. I think this can safely be set to FALSE - but\r
- * if we trust the callers not to request full repaints unnessesarily, then\r
- * we could skip some clipping work. In other words, only request a full\r
- * redraw when the majority of pieces have changed positions (ie. flip, \r
- * gamestart and similar) --Hawk\r
- */\r
- Boolean fullrepaint = repaint;\r
-\r
- if(DrawSeekGraph()) return; // [HG} seekgraph: suppress printing board if seek graph up\r
-\r
- if( DrawPositionNeedsFullRepaint() ) {\r
- fullrepaint = TRUE;\r
- }\r
-\r
- if (board == NULL) {\r
- if (!lastReqValid[nr]) {\r
- return;\r
- }\r
- board = lastReq[nr];\r
- } else {\r
- CopyBoard(lastReq[nr], board);\r
- lastReqValid[nr] = 1;\r
- }\r
-\r
- if (doingSizing) {\r
- return;\r
- }\r
-\r
- if (IsIconic(hwndMain)) {\r
- return;\r
- }\r
-\r
- if (hdc == NULL) {\r
- hdc = GetDC(hwndMain);\r
- if (!appData.monoMode) {\r
- SelectPalette(hdc, hPal, FALSE);\r
- RealizePalette(hdc);\r
- }\r
- releaseDC = TRUE;\r
- } else {\r
- releaseDC = FALSE;\r
- }\r
-\r
- /* Create some work-DCs */\r
- hdcmem = CreateCompatibleDC(hdc);\r
- tmphdc = CreateCompatibleDC(hdc);\r
-\r
- /* If dragging is in progress, we temporarely remove the piece */\r
- /* [HGM] or temporarily decrease count if stacked */\r
- /* !! Moved to before board compare !! */\r
- if (dragInfo.from.x >= 0 && dragInfo.pos.x >= 0) {\r
- dragged_piece = board[dragInfo.from.y][dragInfo.from.x];\r
- if(dragInfo.from.x == BOARD_LEFT-2 ) {\r
- if(--board[dragInfo.from.y][dragInfo.from.x+1] == 0 )\r
- board[dragInfo.from.y][dragInfo.from.x] = EmptySquare;\r
- } else \r
- if(dragInfo.from.x == BOARD_RGHT+1) {\r
- if(--board[dragInfo.from.y][dragInfo.from.x-1] == 0 )\r
- board[dragInfo.from.y][dragInfo.from.x] = EmptySquare;\r
- } else \r
- board[dragInfo.from.y][dragInfo.from.x] = gatingPiece;\r
- }\r
-\r
- /* Figure out which squares need updating by comparing the \r
- * newest board with the last drawn board and checking if\r
- * flipping has changed.\r
- */\r
- if (!fullrepaint && lastDrawnValid[nr] && (nr == 1 || lastDrawnFlipView == flipView)) {\r
- for (row = 0; row < BOARD_HEIGHT; row++) { /* [HGM] true size, not 8 */\r
- for (column = 0; column < BOARD_WIDTH; column++) {\r
- if (lastDrawn[nr][row][column] != board[row][column]) {\r
- SquareToPos(row, column, &x, &y);\r
- clips[num_clips++] =\r
- CreateRectRgn(x, y, x + squareSize, y + squareSize);\r
- }\r
- }\r
- }\r
- if(nr == 0) { // [HGM] dual: no highlights on second board\r
- for (i=0; i<2; i++) {\r
- if (lastDrawnHighlight.sq[i].x != highlightInfo.sq[i].x ||\r
- lastDrawnHighlight.sq[i].y != highlightInfo.sq[i].y) {\r
- if (lastDrawnHighlight.sq[i].x >= 0 &&\r
- lastDrawnHighlight.sq[i].y >= 0) {\r
- SquareToPos(lastDrawnHighlight.sq[i].y,\r
- lastDrawnHighlight.sq[i].x, &x, &y);\r
- clips[num_clips++] =\r
- CreateRectRgn(x - lineGap, y - lineGap, \r
- x + squareSize + lineGap, y + squareSize + lineGap);\r
- }\r
- if (highlightInfo.sq[i].x >= 0 && highlightInfo.sq[i].y >= 0) {\r
- SquareToPos(highlightInfo.sq[i].y, highlightInfo.sq[i].x, &x, &y);\r
- clips[num_clips++] =\r
- CreateRectRgn(x - lineGap, y - lineGap, \r
- x + squareSize + lineGap, y + squareSize + lineGap);\r
- }\r
- }\r
- }\r
- for (i=0; i<2; i++) {\r
- if (lastDrawnPremove.sq[i].x != premoveHighlightInfo.sq[i].x ||\r
- lastDrawnPremove.sq[i].y != premoveHighlightInfo.sq[i].y) {\r
- if (lastDrawnPremove.sq[i].x >= 0 &&\r
- lastDrawnPremove.sq[i].y >= 0) {\r
- SquareToPos(lastDrawnPremove.sq[i].y,\r
- lastDrawnPremove.sq[i].x, &x, &y);\r
- clips[num_clips++] =\r
- CreateRectRgn(x - lineGap, y - lineGap, \r
- x + squareSize + lineGap, y + squareSize + lineGap);\r
- }\r
- if (premoveHighlightInfo.sq[i].x >= 0 && \r
- premoveHighlightInfo.sq[i].y >= 0) {\r
- SquareToPos(premoveHighlightInfo.sq[i].y, \r
- premoveHighlightInfo.sq[i].x, &x, &y);\r
- clips[num_clips++] =\r
- CreateRectRgn(x - lineGap, y - lineGap, \r
- x + squareSize + lineGap, y + squareSize + lineGap);\r
- }\r
- }\r
- }\r
- } else { // nr == 1\r
- partnerHighlightInfo.sq[0].y = board[EP_STATUS-4];\r
- partnerHighlightInfo.sq[0].x = board[EP_STATUS-3];\r
- partnerHighlightInfo.sq[1].y = board[EP_STATUS-2];\r
- partnerHighlightInfo.sq[1].x = board[EP_STATUS-1];\r
- for (i=0; i<2; i++) {\r
- if (partnerHighlightInfo.sq[i].x >= 0 &&\r
- partnerHighlightInfo.sq[i].y >= 0) {\r
- SquareToPos(partnerHighlightInfo.sq[i].y,\r
- partnerHighlightInfo.sq[i].x, &x, &y);\r
- clips[num_clips++] =\r
- CreateRectRgn(x - lineGap, y - lineGap, \r
- x + squareSize + lineGap, y + squareSize + lineGap);\r
- }\r
- if (oldPartnerHighlight.sq[i].x >= 0 && \r
- oldPartnerHighlight.sq[i].y >= 0) {\r
- SquareToPos(oldPartnerHighlight.sq[i].y, \r
- oldPartnerHighlight.sq[i].x, &x, &y);\r
- clips[num_clips++] =\r
- CreateRectRgn(x - lineGap, y - lineGap, \r
- x + squareSize + lineGap, y + squareSize + lineGap);\r
- }\r
- }\r
- }\r
- } else {\r
- fullrepaint = TRUE;\r
- }\r
-\r
- /* Create a buffer bitmap - this is the actual bitmap\r
- * being written to. When all the work is done, we can\r
- * copy it to the real DC (the screen). This avoids\r
- * the problems with flickering.\r
- */\r
- GetClientRect(hwndMain, &Rect);\r
- bufferBitmap = CreateCompatibleBitmap(hdc, Rect.right-Rect.left+1,\r
- Rect.bottom-Rect.top+1);\r
- oldBitmap = SelectObject(hdcmem, bufferBitmap);\r
- if (!appData.monoMode) {\r
- SelectPalette(hdcmem, hPal, FALSE);\r
- }\r
-\r
- /* Create clips for dragging */\r
- if (!fullrepaint) {\r
- if (dragInfo.from.x >= 0) {\r
- SquareToPos(dragInfo.from.y, dragInfo.from.x, &x, &y);\r
- clips[num_clips++] = CreateRectRgn(x, y, x+squareSize, y+squareSize);\r
- }\r
- if (dragInfo.start.x >= 0) {\r
- SquareToPos(dragInfo.start.y, dragInfo.start.x, &x, &y);\r
- clips[num_clips++] = CreateRectRgn(x, y, x+squareSize, y+squareSize);\r
- }\r
- if (dragInfo.pos.x >= 0) {\r
- x = dragInfo.pos.x - squareSize / 2;\r
- y = dragInfo.pos.y - squareSize / 2;\r
- clips[num_clips++] = CreateRectRgn(x, y, x+squareSize, y+squareSize);\r
- }\r
- if (dragInfo.lastpos.x >= 0) {\r
- x = dragInfo.lastpos.x - squareSize / 2;\r
- y = dragInfo.lastpos.y - squareSize / 2;\r
- clips[num_clips++] = CreateRectRgn(x, y, x+squareSize, y+squareSize);\r
- }\r
- }\r
-\r
- /* Are we animating a move? \r
- * If so, \r
- * - remove the piece from the board (temporarely)\r
- * - calculate the clipping region\r
- */\r
- if (!fullrepaint) {\r
- if (animInfo.piece != EmptySquare) {\r
- board[animInfo.from.y][animInfo.from.x] = EmptySquare;\r
- x = boardRect.left + animInfo.lastpos.x;\r
- y = boardRect.top + animInfo.lastpos.y;\r
- x2 = boardRect.left + animInfo.pos.x;\r
- y2 = boardRect.top + animInfo.pos.y;\r
- clips[num_clips++] = CreateRectRgn(MIN(x,x2), MIN(y,y2), MAX(x,x2)+squareSize, MAX(y,y2)+squareSize);\r
- /* Slight kludge. The real problem is that after AnimateMove is\r
- done, the position on the screen does not match lastDrawn.\r
- This currently causes trouble only on e.p. captures in\r
- atomic, where the piece moves to an empty square and then\r
- explodes. The old and new positions both had an empty square\r
- at the destination, but animation has drawn a piece there and\r
- we have to remember to erase it. [HGM] moved until after setting lastDrawn */\r
-\r
- lastDrawn[0][animInfo.to.y][animInfo.to.x] = animInfo.piece;\r
- }\r
- }\r
-\r
- /* No clips? Make sure we have fullrepaint set to TRUE */\r
- if (num_clips == 0)\r
- fullrepaint = TRUE;\r
-\r
- /* Set clipping on the memory DC */\r
- if (!fullrepaint) {\r
- SelectClipRgn(hdcmem, clips[0]);\r
- for (x = 1; x < num_clips; x++) {\r
- if (ExtSelectClipRgn(hdcmem, clips[x], RGN_OR) == ERROR)\r
- abort(); // this should never ever happen!\r
- }\r
- }\r
-\r
- /* Do all the drawing to the memory DC */\r
- if(explodeInfo.radius) { // [HGM] atomic\r
- HBRUSH oldBrush;\r
- int x, y, r=(explodeInfo.radius * squareSize)/100;\r
- ChessSquare piece = board[explodeInfo.fromY][explodeInfo.fromX];\r
- board[explodeInfo.fromY][explodeInfo.fromX] = EmptySquare; // suppress display of capturer\r
- SquareToPos(explodeInfo.toY, explodeInfo.toX, &x, &y);\r
- x += squareSize/2;\r
- y += squareSize/2;\r
- if(!fullrepaint) {\r
- clips[num_clips] = CreateRectRgn(x-r, y-r, x+r, y+r);\r
- ExtSelectClipRgn(hdcmem, clips[num_clips++], RGN_OR);\r
- }\r
- DrawGridOnDC(hdcmem);\r
- DrawHighlightsOnDC(hdcmem, &highlightInfo, HIGHLIGHT_PEN);\r
- DrawHighlightsOnDC(hdcmem, &premoveHighlightInfo, PREMOVE_PEN);\r
- DrawBoardOnDC(hdcmem, board, tmphdc);\r
- board[explodeInfo.fromY][explodeInfo.fromX] = piece;\r
- oldBrush = SelectObject(hdcmem, explodeBrush);\r
- Ellipse(hdcmem, x-r, y-r, x+r, y+r);\r
- SelectObject(hdcmem, oldBrush);\r
- } else {\r
- if(border) DrawBackgroundOnDC(hdcmem);\r
- DrawGridOnDC(hdcmem);\r
- if(nr == 0) { // [HGM] dual: decide which highlights to draw\r
- DrawHighlightsOnDC(hdcmem, &highlightInfo, HIGHLIGHT_PEN);\r
- DrawHighlightsOnDC(hdcmem, &premoveHighlightInfo, PREMOVE_PEN);\r
- } else {\r
- DrawHighlightsOnDC(hdcmem, &partnerHighlightInfo, HIGHLIGHT_PEN);\r
- oldPartnerHighlight = partnerHighlightInfo;\r
- }\r
- DrawBoardOnDC(hdcmem, board, tmphdc);\r
- }\r
- if(nr == 0) // [HGM] dual: markers only on left board\r
- for (row = 0; row < BOARD_HEIGHT; row++) {\r
- for (column = 0; column < BOARD_WIDTH; column++) {\r
- if (marker[row][column]) { // marker changes only occur with full repaint!\r
- HBRUSH oldBrush = SelectObject(hdcmem, markerBrush[marker[row][column]-1]);\r
- SquareToPos(row, column, &x, &y);\r
- Ellipse(hdcmem, x + squareSize/4, y + squareSize/4,\r
- x + 3*squareSize/4, y + 3*squareSize/4);\r
- SelectObject(hdcmem, oldBrush);\r
- }\r
- }\r
- }\r
-\r
- if( appData.highlightMoveWithArrow ) {\r
-\r
- DrawArrowHighlight(hdcmem);\r
- }\r
-\r
- DrawCoordsOnDC(hdcmem);\r
-\r
- CopyBoard(lastDrawn[nr], board); /* [HGM] Moved to here from end of routine, */\r
- /* to make sure lastDrawn contains what is actually drawn */\r
-\r
- /* Put the dragged piece back into place and draw it (out of place!) */\r
- if (dragged_piece != EmptySquare) {\r
- /* [HGM] or restack */\r
- if(dragInfo.from.x == BOARD_LEFT-2 )\r
- board[dragInfo.from.y][dragInfo.from.x+1]++;\r
- else\r
- if(dragInfo.from.x == BOARD_RGHT+1 )\r
- board[dragInfo.from.y][dragInfo.from.x-1]++;\r
-\r
- board[dragInfo.from.y][dragInfo.from.x] = dragged_piece;\r
- x = dragInfo.pos.x - squareSize / 2;\r
- y = dragInfo.pos.y - squareSize / 2;\r
- DrawPieceOnDC(hdcmem, dragInfo.piece,\r
- ((int) dragInfo.piece < (int) BlackPawn), \r
- (dragInfo.from.y + dragInfo.from.x) % 2, x, y, tmphdc);\r
- } \r
- \r
- /* Put the animated piece back into place and draw it */\r
- if (animInfo.piece != EmptySquare) {\r
- board[animInfo.from.y][animInfo.from.x] = animInfo.piece;\r
- x = boardRect.left + animInfo.pos.x;\r
- y = boardRect.top + animInfo.pos.y;\r
- DrawPieceOnDC(hdcmem, animInfo.piece,\r
- ((int) animInfo.piece < (int) BlackPawn),\r
- (animInfo.from.y + animInfo.from.x) % 2, x, y, tmphdc);\r
- }\r
-\r
- /* Release the bufferBitmap by selecting in the old bitmap \r
- * and delete the memory DC\r
- */\r
- SelectObject(hdcmem, oldBitmap);\r
- DeleteDC(hdcmem);\r
-\r
- /* Set clipping on the target DC */\r
- if (!fullrepaint) {\r
- if(nr == 1) for (x = 0; x < num_clips; x++) { // [HGM] dual: translate clips\r
- RECT rect;\r
- GetRgnBox(clips[x], &rect);\r
- DeleteObject(clips[x]);\r
- clips[x] = CreateRectRgn(rect.left + wpMain.width/2, rect.top, \r
- rect.right + wpMain.width/2, rect.bottom);\r
- }\r
- SelectClipRgn(hdc, clips[0]);\r
- for (x = 1; x < num_clips; x++) {\r
- if (ExtSelectClipRgn(hdc, clips[x], RGN_OR) == ERROR)\r
- abort(); // this should never ever happen!\r
- } \r
- }\r
-\r
- /* Copy the new bitmap onto the screen in one go.\r
- * This way we avoid any flickering\r
- */\r
- oldBitmap = SelectObject(tmphdc, bufferBitmap);\r
- BitBlt(hdc, boardRect.left + twoBoards*partnerUp*wpMain.width/2, boardRect.top, // [HGM] dual\r
- boardRect.right - boardRect.left,\r
- boardRect.bottom - boardRect.top,\r
- tmphdc, boardRect.left, boardRect.top, SRCCOPY);\r
- if(saveDiagFlag) { \r
- BITMAP b; int i, j=0, m, w, wb, fac=0; char *pData; \r
- BITMAPINFOHEADER bih; int color[16], nrColors=0;\r
- HBITMAP src = bufferBitmap, obmp; HDC tmp = CreateCompatibleDC(hdc);\r
-\r
- bufferBitmap = CreateCompatibleBitmap(hdc, boardRect.right-boardRect.left, Rect.bottom-Rect.top-2*OUTER_MARGIN);\r
- obmp = SelectObject(tmp, bufferBitmap);\r
- BitBlt(tmp, 0, 0, boardRect.right - boardRect.left, Rect.bottom - Rect.top - 2*OUTER_MARGIN,\r
- tmphdc, boardRect.left, OUTER_MARGIN, SRCCOPY);\r
- GetObject(bufferBitmap, sizeof(b), &b);\r
- if(pData = malloc(b.bmWidthBytes*b.bmHeight + 10000)) {\r
- bih.biSize = sizeof(BITMAPINFOHEADER);\r
- bih.biWidth = b.bmWidth;\r
- bih.biHeight = b.bmHeight;\r
- bih.biPlanes = 1;\r
- bih.biBitCount = b.bmBitsPixel;\r
- bih.biCompression = 0;\r
- bih.biSizeImage = b.bmWidthBytes*b.bmHeight;\r
- bih.biXPelsPerMeter = 0;\r
- bih.biYPelsPerMeter = 0;\r
- bih.biClrUsed = 0;\r
- bih.biClrImportant = 0;\r
-// fprintf(diagFile, "t=%d\nw=%d\nh=%d\nB=%d\nP=%d\nX=%d\n", \r
-// b.bmType, b.bmWidth, b.bmHeight, b.bmWidthBytes, b.bmPlanes, b.bmBitsPixel);\r
- GetDIBits(tmphdc,bufferBitmap,0,b.bmHeight,pData,(BITMAPINFO*)&bih,DIB_RGB_COLORS);\r
-// fprintf(diagFile, "%8x\n", (int) pData);\r
-\r
- wb = b.bmWidthBytes;\r
- // count colors\r
- for(i=0; i<wb*(b.bmHeight - boardRect.top + OUTER_MARGIN)>>2; i++) {\r
- int k = ((int*) pData)[i];\r
- for(j=0; j<nrColors; j++) if(color[j] == k) break;\r
- if(j >= 16) break;\r
- color[j] = k;\r
- if(j >= nrColors) nrColors = j+1;\r
- }\r
- if(j<16) { // 16 colors is enough. Compress to 4 bits per pixel\r
- INT p = 0;\r
- for(i=0; i<b.bmHeight - boardRect.top + OUTER_MARGIN; i++) {\r
- for(w=0; w<(wb>>2); w+=2) {\r
- int k = ((int*) pData)[(wb*i>>2) + w];\r
- for(j=0; j<nrColors; j++) if(color[j] == k) break;\r
- k = ((int*) pData)[(wb*i>>2) + w + 1];\r
- for(m=0; m<nrColors; m++) if(color[m] == k) break;\r
- pData[p++] = m | j<<4;\r
- }\r
- while(p&3) pData[p++] = 0;\r
- }\r
- fac = 3;\r
- wb = ((wb+31)>>5)<<2;\r
- }\r
- // write BITMAPFILEHEADER\r
- fprintf(diagFile, "BM");\r
- fputDW(diagFile, wb*(b.bmHeight - boardRect.top + OUTER_MARGIN)+0x36 + (fac?64:0));\r
- fputDW(diagFile, 0);\r
- fputDW(diagFile, 0x36 + (fac?64:0));\r
- // write BITMAPINFOHEADER\r
- fputDW(diagFile, 40);\r
- fputDW(diagFile, b.bmWidth);\r
- fputDW(diagFile, b.bmHeight - boardRect.top + OUTER_MARGIN);\r
- if(fac) fputDW(diagFile, 0x040001); // planes and bits/pixel\r
- else fputDW(diagFile, 0x200001); // planes and bits/pixel\r
- fputDW(diagFile, 0);\r
- fputDW(diagFile, 0);\r
- fputDW(diagFile, 0);\r
- fputDW(diagFile, 0);\r
- fputDW(diagFile, 0);\r
- fputDW(diagFile, 0);\r
- // write color table\r
- if(fac)\r
- for(i=0; i<16; i++) fputDW(diagFile, color[i]);\r
- // write bitmap data\r
- for(i=0; i<wb*(b.bmHeight - boardRect.top + OUTER_MARGIN); i++) \r
- fputc(pData[i], diagFile);\r
- free(pData);\r
- }\r
- DeleteObject(bufferBitmap); bufferBitmap = src;\r
- SelectObject(tmp, obmp);\r
- DeleteDC(tmp);\r
- }\r
-\r
- SelectObject(tmphdc, oldBitmap);\r
-\r
- /* Massive cleanup */\r
- for (x = 0; x < num_clips; x++)\r
- DeleteObject(clips[x]);\r
-\r
- DeleteDC(tmphdc);\r
- DeleteObject(bufferBitmap);\r
-\r
- if (releaseDC) \r
- ReleaseDC(hwndMain, hdc);\r
- \r
- if (lastDrawnFlipView != flipView && nr == 0) {\r
- if (flipView)\r
- CheckMenuItem(GetMenu(hwndMain),IDM_FlipView, MF_BYCOMMAND|MF_CHECKED);\r
- else\r
- CheckMenuItem(GetMenu(hwndMain),IDM_FlipView, MF_BYCOMMAND|MF_UNCHECKED);\r
- }\r
-\r
-/* CopyBoard(lastDrawn, board);*/\r
- lastDrawnHighlight = highlightInfo;\r
- lastDrawnPremove = premoveHighlightInfo;\r
- lastDrawnFlipView = flipView;\r
- lastDrawnValid[nr] = 1;\r
-}\r
-\r
-/* [HGM] diag: Save the current board display to the given open file and close the file */\r
-int\r
-SaveDiagram(f)\r
- FILE *f;\r
-{\r
- saveDiagFlag = 1; diagFile = f;\r
- HDCDrawPosition(NULL, TRUE, NULL);\r
- saveDiagFlag = 0;\r
-\r
- fclose(f);\r
- return TRUE;\r
-}\r
-\r
-\r
-/*---------------------------------------------------------------------------*\\r
-| CLIENT PAINT PROCEDURE\r
-| This is the main event-handler for the WM_PAINT message.\r
-|\r
-\*---------------------------------------------------------------------------*/\r
-VOID\r
-PaintProc(HWND hwnd)\r
-{\r
- HDC hdc;\r
- PAINTSTRUCT ps;\r
- HFONT oldFont;\r
-\r
- if((hdc = BeginPaint(hwnd, &ps))) {\r
- if (IsIconic(hwnd)) {\r
- DrawIcon(hdc, 2, 2, iconCurrent);\r
- } else {\r
- if (!appData.monoMode) {\r
- SelectPalette(hdc, hPal, FALSE);\r
- RealizePalette(hdc);\r
- }\r
- HDCDrawPosition(hdc, 1, NULL);\r
- if(twoBoards) { // [HGM] dual: also redraw other board in other orientation\r
- flipView = !flipView; partnerUp = !partnerUp;\r
- HDCDrawPosition(hdc, 1, NULL);\r
- flipView = !flipView; partnerUp = !partnerUp;\r
- }\r
- oldFont =\r
- SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);\r
- ExtTextOut(hdc, messageRect.left, messageRect.top,\r
- ETO_CLIPPED|ETO_OPAQUE,\r
- &messageRect, messageText, strlen(messageText), NULL);\r
- SelectObject(hdc, oldFont);\r
- DisplayBothClocks();\r
- DisplayLogos();\r
- }\r
- EndPaint(hwnd,&ps);\r
- }\r
-\r
- return;\r
-}\r
-\r
-\r
-/*\r
- * If the user selects on a border boundary, return -1; if off the board,\r
- * return -2. Otherwise map the event coordinate to the square.\r
- * The offset boardRect.left or boardRect.top must already have been\r
- * subtracted from x.\r
- */\r
-int EventToSquare(x, limit)\r
- int x, limit;\r
-{\r
- if (x <= border)\r
- return -2;\r
- if (x < lineGap + border)\r
- return -1;\r
- x -= lineGap + border;\r
- if ((x % (squareSize + lineGap)) >= squareSize)\r
- return -1;\r
- x /= (squareSize + lineGap);\r
- if (x >= limit)\r
- return -2;\r
- return x;\r
-}\r
-\r
-typedef struct {\r
- char piece;\r
- int command;\r
- char* name;\r
-} DropEnable;\r
-\r
-DropEnable dropEnables[] = {\r
- { 'P', DP_Pawn, N_("Pawn") },\r
- { 'N', DP_Knight, N_("Knight") },\r
- { 'B', DP_Bishop, N_("Bishop") },\r
- { 'R', DP_Rook, N_("Rook") },\r
- { 'Q', DP_Queen, N_("Queen") },\r
-};\r
-\r
-VOID\r
-SetupDropMenu(HMENU hmenu)\r
-{\r
- int i, count, enable;\r
- char *p;\r
- extern char white_holding[], black_holding[];\r
- char item[MSG_SIZ];\r
-\r
- for (i=0; i<sizeof(dropEnables)/sizeof(DropEnable); i++) {\r
- p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,\r
- dropEnables[i].piece);\r
- count = 0;\r
- while (p && *p++ == dropEnables[i].piece) count++;\r
- snprintf(item, MSG_SIZ, "%s %d", T_(dropEnables[i].name), count);\r
- enable = count > 0 || !appData.testLegality\r
- /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse\r
- && !appData.icsActive);\r
- ModifyMenu(hmenu, dropEnables[i].command,\r
- MF_BYCOMMAND | (enable ? MF_ENABLED : MF_GRAYED) | MF_STRING,\r
- dropEnables[i].command, item);\r
- }\r
-}\r
-\r
-void DragPieceBegin(int x, int y, Boolean instantly)\r
-{\r
- dragInfo.lastpos.x = boardRect.left + x;\r
- dragInfo.lastpos.y = boardRect.top + y;\r
- if(instantly) dragInfo.pos = dragInfo.lastpos;\r
- dragInfo.from.x = fromX;\r
- dragInfo.from.y = fromY;\r
- dragInfo.piece = boards[currentMove][fromY][fromX];\r
- dragInfo.start = dragInfo.from;\r
- SetCapture(hwndMain);\r
-}\r
-\r
-void DragPieceEnd(int x, int y)\r
-{\r
- ReleaseCapture();\r
- dragInfo.start.x = dragInfo.start.y = -1;\r
- dragInfo.from = dragInfo.start;\r
- dragInfo.pos = dragInfo.lastpos = dragInfo.start;\r
-}\r
-\r
-void ChangeDragPiece(ChessSquare piece)\r
-{\r
- dragInfo.piece = piece;\r
-}\r
-\r
-/* Event handler for mouse messages */\r
-VOID\r
-MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- int x, y, menuNr;\r
- POINT pt;\r
- static int recursive = 0;\r
- HMENU hmenu;\r
- BOOLEAN forceFullRepaint = IsFullRepaintPreferrable(); /* [AS] */\r
-\r
- if (recursive) {\r
- if (message == WM_MBUTTONUP) {\r
- /* Hideous kludge to fool TrackPopupMenu into paying attention\r
- to the middle button: we simulate pressing the left button too!\r
- */\r
- PostMessage(hwnd, WM_LBUTTONDOWN, wParam, lParam);\r
- PostMessage(hwnd, WM_LBUTTONUP, wParam, lParam);\r
- }\r
- return;\r
- }\r
- recursive++;\r
- \r
- pt.x = LOWORD(lParam);\r
- pt.y = HIWORD(lParam);\r
- x = EventToSquare(pt.x - boardRect.left, BOARD_WIDTH);\r
- y = EventToSquare(pt.y - boardRect.top, BOARD_HEIGHT);\r
- if (!flipView && y >= 0) {\r
- y = BOARD_HEIGHT - 1 - y;\r
- }\r
- if (flipView && x >= 0) {\r
- x = BOARD_WIDTH - 1 - x;\r
- }\r
-\r
- shiftKey = GetKeyState(VK_SHIFT) < 0; // [HGM] remember last shift status\r
- controlKey = GetKeyState(VK_CONTROL) < 0; // [HGM] remember last shift status\r
-\r
- switch (message) {\r
- case WM_LBUTTONDOWN:\r
- if (PtInRect((LPRECT) &whiteRect, pt)) {\r
- ClockClick(flipClock); break;\r
- } else if (PtInRect((LPRECT) &blackRect, pt)) {\r
- ClockClick(!flipClock); break;\r
- }\r
- if(dragging) { // [HGM] lion: don't destroy dragging info if we are already dragging\r
- dragInfo.start.x = dragInfo.start.y = -1;\r
- dragInfo.from = dragInfo.start;\r
- }\r
- if(fromX == -1 && frozen) { // not sure where this is for\r
- fromX = fromY = -1; \r
- DrawPosition(forceFullRepaint || FALSE, NULL); /* [AS] */\r
- break;\r
- }\r
- LeftClick(Press, pt.x - boardRect.left, pt.y - boardRect.top);\r
- DrawPosition(TRUE, NULL);\r
- break;\r
-\r
- case WM_LBUTTONUP:\r
- LeftClick(Release, pt.x - boardRect.left, pt.y - boardRect.top);\r
- DrawPosition(TRUE, NULL);\r
- break;\r
-\r
- case WM_MOUSEMOVE:\r
- if(SeekGraphClick(Press, pt.x - boardRect.left, pt.y - boardRect.top, 1)) break;\r
- if(PromoScroll(pt.x - boardRect.left, pt.y - boardRect.top)) break;\r
- MovePV(pt.x - boardRect.left, pt.y - boardRect.top, boardRect.bottom - boardRect.top);\r
- if ((appData.animateDragging || appData.highlightDragging)\r
- && (wParam & MK_LBUTTON || dragging == 2)\r
- && dragInfo.from.x >= 0) \r
- {\r
- BOOL full_repaint = FALSE;\r
-\r
- if (appData.animateDragging) {\r
- dragInfo.pos = pt;\r
- }\r
- if (appData.highlightDragging) {\r
- HoverEvent(highlightInfo.sq[1].x, highlightInfo.sq[1].y, x, y);\r
- if( IsDrawArrowEnabled() && (x < 0 || x >= BOARD_WIDTH || y < 0 || y >= BOARD_HEIGHT) ) {\r
- full_repaint = TRUE;\r
- }\r
- }\r
- \r
- DrawPosition( full_repaint, NULL);\r
- \r
- dragInfo.lastpos = dragInfo.pos;\r
- }\r
- break;\r
-\r
- case WM_MOUSEWHEEL: // [DM]\r
- { static int lastDir = 0; // [HGM] build in some hysteresis to avoid spurious events\r
- /* Mouse Wheel is being rolled forward\r
- * Play moves forward\r
- */\r
- if((short)HIWORD(wParam) < 0 && currentMove < forwardMostMove) \r
- { if(lastDir == 1) ForwardEvent(); else lastDir = 1; } // [HGM] suppress first event in direction\r
- /* Mouse Wheel is being rolled backward\r
- * Play moves backward\r
- */\r
- if((short)HIWORD(wParam) > 0 && currentMove > backwardMostMove) \r
- { if(lastDir == -1) BackwardEvent(); else lastDir = -1; }\r
- }\r
- break;\r
-\r
- case WM_MBUTTONUP:\r
- case WM_RBUTTONUP:\r
- ReleaseCapture();\r
- RightClick(Release, pt.x - boardRect.left, pt.y - boardRect.top, &fromX, &fromY);\r
- break;\r
- \r
- case WM_MBUTTONDOWN:\r
- case WM_RBUTTONDOWN:\r
- ErrorPopDown();\r
- ReleaseCapture();\r
- fromX = fromY = -1;\r
- dragInfo.pos.x = dragInfo.pos.y = -1;\r
- dragInfo.start.x = dragInfo.start.y = -1;\r
- dragInfo.from = dragInfo.start;\r
- dragInfo.lastpos = dragInfo.pos;\r
- if (appData.highlightDragging) {\r
- ClearHighlights();\r
- }\r
- if(y == -2) {\r
- /* [HGM] right mouse button in clock area edit-game mode ups clock */\r
- if (PtInRect((LPRECT) &whiteRect, pt)) {\r
- if (GetKeyState(VK_SHIFT) < 0) AdjustClock(flipClock, 1);\r
- } else if (PtInRect((LPRECT) &blackRect, pt)) {\r
- if (GetKeyState(VK_SHIFT) < 0) AdjustClock(!flipClock, 1);\r
- }\r
- break;\r
- }\r
- DrawPosition(TRUE, NULL);\r
-\r
- menuNr = RightClick(Press, pt.x - boardRect.left, pt.y - boardRect.top, &fromX, &fromY);\r
- switch (menuNr) {\r
- case 0:\r
- if (message == WM_MBUTTONDOWN) {\r
- buttonCount = 3; /* even if system didn't think so */\r
- if (wParam & MK_SHIFT) \r
- MenuPopup(hwnd, pt, LoadMenu(hInst, "BlackPieceMenu"), -1);\r
- else\r
- MenuPopup(hwnd, pt, LoadMenu(hInst, "WhitePieceMenu"), -1);\r
- } else { /* message == WM_RBUTTONDOWN */\r
- /* Just have one menu, on the right button. Windows users don't\r
- think to try the middle one, and sometimes other software steals\r
- it, or it doesn't really exist. */\r
- if(gameInfo.variant != VariantShogi)\r
- MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1);\r
- else\r
- MenuPopup(hwnd, pt, LoadMenu(hInst, "ShogiPieceMenu"), -1);\r
- }\r
- break;\r
- case 2:\r
- SetCapture(hwndMain);\r
- break;\r
- case 1:\r
- hmenu = LoadMenu(hInst, "DropPieceMenu");\r
- SetupDropMenu(hmenu);\r
- MenuPopup(hwnd, pt, hmenu, -1);\r
- default:\r
- break;\r
- }\r
- break;\r
- }\r
-\r
- recursive--;\r
-}\r
-\r
-/* Preprocess messages for buttons in main window */\r
-LRESULT CALLBACK\r
-ButtonProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- int id = GetWindowLongPtr(hwnd, GWLP_ID);\r
- int i, dir;\r
-\r
- for (i=0; i<N_BUTTONS; i++) {\r
- if (buttonDesc[i].id == id) break;\r
- }\r
- if (i == N_BUTTONS) return 0;\r
- switch (message) {\r
- case WM_KEYDOWN:\r
- switch (wParam) {\r
- case VK_LEFT:\r
- case VK_RIGHT:\r
- dir = (wParam == VK_LEFT) ? -1 : 1;\r
- SetFocus(buttonDesc[(i + dir + N_BUTTONS) % N_BUTTONS].hwnd);\r
- return TRUE;\r
- }\r
- break;\r
- case WM_CHAR:\r
- switch (wParam) {\r
- case '\r':\r
- SendMessage(hwndMain, WM_COMMAND, MAKEWPARAM(buttonDesc[i].id, 0), 0);\r
- return TRUE;\r
- default:\r
- if (appData.icsActive && (isalpha((char)wParam) || wParam == '0')) {\r
- // [HGM] movenum: only letters or leading zero should go to ICS input\r
- HWND h = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
- SetFocus(h);\r
- SendMessage(h, WM_CHAR, wParam, lParam);\r
- return TRUE;\r
- } else if (isalpha((char)wParam) || isdigit((char)wParam)){\r
- TypeInEvent((char)wParam);\r
- }\r
- break;\r
- }\r
- break;\r
- }\r
- return CallWindowProc(buttonDesc[i].wndproc, hwnd, message, wParam, lParam);\r
-}\r
-\r
-static int promoStyle;\r
-\r
-/* Process messages for Promotion dialog box */\r
-LRESULT CALLBACK\r
-Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
-\r
- char promoChar;\r
-\r
- switch (message) {\r
-\r
- case WM_INITDIALOG: /* message: initialize dialog box */\r
- /* Center the dialog over the application window */\r
- CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER));\r
- Translate(hDlg, DLG_PromotionKing);\r
- ShowWindow(GetDlgItem(hDlg, PB_King), \r
- (!appData.testLegality || gameInfo.variant == VariantSuicide ||\r
- gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove) ||\r
- gameInfo.variant == VariantGiveaway || gameInfo.variant == VariantSuper ) ?\r
- SW_SHOW : SW_HIDE);\r
- /* [HGM] Only allow C & A promotions if these pieces are defined */\r
- ShowWindow(GetDlgItem(hDlg, PB_Archbishop),\r
- ((PieceToChar(WhiteAngel) >= 'A' && WhiteOnMove(currentMove) &&\r
- PieceToChar(WhiteAngel) != '~') ||\r
- (PieceToChar(BlackAngel) >= 'A' && !WhiteOnMove(currentMove) &&\r
- PieceToChar(BlackAngel) != '~') ) ?\r
- SW_SHOW : SW_HIDE);\r
- ShowWindow(GetDlgItem(hDlg, PB_Chancellor), \r
- ((PieceToChar(WhiteMarshall) >= 'A' && WhiteOnMove(currentMove) &&\r
- PieceToChar(WhiteMarshall) != '~') ||\r
- (PieceToChar(BlackMarshall) >= 'A' && !WhiteOnMove(currentMove) &&\r
- PieceToChar(BlackMarshall) != '~') ) ?\r
- SW_SHOW : SW_HIDE);\r
- /* [HGM] Hide B & R button in Shogi, use Q as promote, N as defer */\r
- ShowWindow(GetDlgItem(hDlg, PB_Rook), !promoStyle ? SW_SHOW : SW_HIDE);\r
- ShowWindow(GetDlgItem(hDlg, PB_Bishop), !promoStyle ? SW_SHOW : SW_HIDE);\r
- if(promoStyle) {\r
- SetDlgItemText(hDlg, PB_Queen, "YES");\r
- SetDlgItemText(hDlg, PB_Knight, "NO");\r
- SetWindowText(hDlg, "Promote?");\r
- }\r
- ShowWindow(GetDlgItem(hDlg, IDC_Centaur), \r
- gameInfo.variant == VariantSuper ?\r
- SW_SHOW : SW_HIDE);\r
- return TRUE;\r
-\r
- case WM_COMMAND: /* message: received a command */\r
- switch (LOWORD(wParam)) {\r
- case IDCANCEL:\r
- EndDialog(hDlg, TRUE); /* Exit the dialog */\r
- ClearHighlights();\r
- DrawPosition(FALSE, NULL);\r
- return TRUE;\r
- case PB_King:\r
- promoChar = gameInfo.variant == VariantSuper ? PieceToChar(BlackSilver) : PieceToChar(BlackKing);\r
- break;\r
- case PB_Queen:\r
- promoChar = promoStyle ? '+' : ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteQueen : BlackQueen));\r
- break;\r
- case PB_Rook:\r
- promoChar = ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteRook : BlackRook));\r
- if(gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove)) promoChar = PieceToChar(BlackDragon);\r
- break;\r
- case PB_Bishop:\r
- promoChar = ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteBishop : BlackBishop));\r
- if(gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove)) promoChar = PieceToChar(BlackAlfil);\r
- break;\r
- case PB_Chancellor:\r
- promoChar = ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteMarshall : BlackMarshall));\r
- break;\r
- case PB_Archbishop:\r
- promoChar = ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteAngel : BlackAngel));\r
- break;\r
- case PB_Knight:\r
- promoChar = gameInfo.variant == VariantShogi ? '=' : promoStyle ? NULLCHAR : \r
- ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteKnight : BlackKnight));\r
- break;\r
- default:\r
- return FALSE;\r
- }\r
- if(promoChar == '.') return FALSE; // invalid piece chosen \r
- EndDialog(hDlg, TRUE); /* Exit the dialog */\r
- UserMoveEvent(fromX, fromY, toX, toY, promoChar);\r
- fromX = fromY = -1;\r
- if (!appData.highlightLastMove) {\r
- ClearHighlights();\r
- DrawPosition(FALSE, NULL);\r
- }\r
- return TRUE;\r
- }\r
- return FALSE;\r
-}\r
-\r
-/* Pop up promotion dialog */\r
-VOID\r
-PromotionPopup(HWND hwnd)\r
-{\r
- FARPROC lpProc;\r
-\r
- lpProc = MakeProcInstance((FARPROC)Promotion, hInst);\r
- DialogBox(hInst, MAKEINTRESOURCE(DLG_PromotionKing),\r
- hwnd, (DLGPROC)lpProc);\r
- FreeProcInstance(lpProc);\r
-}\r
-\r
-void\r
-PromotionPopUp(char choice)\r
-{\r
- promoStyle = (choice == '+' || IS_SHOGI(gameInfo.variant));\r
- DrawPosition(TRUE, NULL);\r
- PromotionPopup(hwndMain);\r
-}\r
-\r
-VOID\r
-LoadGameDialog(HWND hwnd, char* title)\r
-{\r
- UINT number = 0;\r
- FILE *f;\r
- char fileTitle[MSG_SIZ];\r
- f = OpenFileDialog(hwnd, "rb", "",\r
- appData.oldSaveStyle ? "gam" : "pgn",\r
- GAME_FILT,\r
- title, &number, fileTitle, NULL);\r
- if (f != NULL) {\r
- cmailMsgLoaded = FALSE;\r
- if (number == 0) {\r
- int error = GameListBuild(f);\r
- if (error) {\r
- DisplayError(_("Cannot build game list"), error);\r
- } else if (!ListEmpty(&gameList) &&\r
- ((ListGame *) gameList.tailPred)->number > 1) {\r
- GameListPopUp(f, fileTitle);\r
- return;\r
- }\r
- GameListDestroy();\r
- number = 1;\r
- }\r
- LoadGame(f, number, fileTitle, FALSE);\r
- }\r
-}\r
-\r
-int get_term_width()\r
-{\r
- HDC hdc;\r
- TEXTMETRIC tm;\r
- RECT rc;\r
- HFONT hfont, hold_font;\r
- LOGFONT lf;\r
- HWND hText;\r
-\r
- if (hwndConsole)\r
- hText = GetDlgItem(hwndConsole, OPT_ConsoleText);\r
- else\r
- return 79;\r
-\r
- // get the text metrics\r
- hdc = GetDC(hText);\r
- lf = font[boardSize][CONSOLE_FONT]->lf;\r
- if (consoleCF.dwEffects & CFE_BOLD)\r
- lf.lfWeight = FW_BOLD;\r
- if (consoleCF.dwEffects & CFE_ITALIC)\r
- lf.lfItalic = TRUE;\r
- if (consoleCF.dwEffects & CFE_STRIKEOUT)\r
- lf.lfStrikeOut = TRUE;\r
- if (consoleCF.dwEffects & CFE_UNDERLINE)\r
- lf.lfUnderline = TRUE;\r
- hfont = CreateFontIndirect(&lf);\r
- hold_font = SelectObject(hdc, hfont);\r
- GetTextMetrics(hdc, &tm);\r
- SelectObject(hdc, hold_font);\r
- DeleteObject(hfont);\r
- ReleaseDC(hText, hdc);\r
-\r
- // get the rectangle\r
- SendMessage(hText, EM_GETRECT, 0, (LPARAM)&rc);\r
-\r
- return (rc.right-rc.left) / tm.tmAveCharWidth;\r
-}\r
-\r
-void UpdateICSWidth(HWND hText)\r
-{\r
- LONG old_width, new_width;\r
-\r
- new_width = get_term_width(hText, FALSE);\r
- old_width = GetWindowLongPtr(hText, GWLP_USERDATA);\r
- if (new_width != old_width)\r
- {\r
- ics_update_width(new_width);\r
- SetWindowLongPtr(hText, GWLP_USERDATA, new_width);\r
- }\r
-}\r
-\r
-VOID\r
-ChangedConsoleFont()\r
-{\r
- CHARFORMAT cfmt;\r
- CHARRANGE tmpsel, sel;\r
- MyFont *f = font[boardSize][CONSOLE_FONT];\r
- HWND hText = GetDlgItem(hwndConsole, OPT_ConsoleText);\r
- HWND hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- PARAFORMAT paraf;\r
-\r
- cfmt.cbSize = sizeof(CHARFORMAT);\r
- cfmt.dwMask = CFM_FACE|CFM_SIZE|CFM_CHARSET;\r
- safeStrCpy(cfmt.szFaceName, font[boardSize][CONSOLE_FONT]->mfp.faceName,\r
- sizeof(cfmt.szFaceName)/sizeof(cfmt.szFaceName[0]) );\r
- /* yHeight is expressed in twips. A twip is 1/20 of a font's point\r
- * size. This was undocumented in the version of MSVC++ that I had\r
- * when I wrote the code, but is apparently documented now.\r
- */\r
- cfmt.yHeight = (int)(f->mfp.pointSize * 20.0 + 0.5);\r
- cfmt.bCharSet = f->lf.lfCharSet;\r
- cfmt.bPitchAndFamily = f->lf.lfPitchAndFamily;\r
- SendMessage(hText, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &cfmt); \r
- SendMessage(hInput, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &cfmt); \r
- /* Why are the following seemingly needed too? */\r
- SendMessage(hText, EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM) &cfmt); \r
- SendMessage(hInput, EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM) &cfmt); \r
- SendMessage(hText, EM_EXGETSEL, 0, (LPARAM)&sel);\r
- tmpsel.cpMin = 0;\r
- tmpsel.cpMax = -1; /*999999?*/\r
- SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&tmpsel);\r
- SendMessage(hText, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cfmt); \r
- /* Trying putting this here too. It still seems to tickle a RichEdit\r
- * bug: sometimes RichEdit indents the first line of a paragraph too.\r
- */\r
- paraf.cbSize = sizeof(paraf);\r
- paraf.dwMask = PFM_OFFSET | PFM_STARTINDENT;\r
- paraf.dxStartIndent = 0;\r
- paraf.dxOffset = WRAP_INDENT;\r
- SendMessage(hText, EM_SETPARAFORMAT, 0, (LPARAM) ¶f);\r
- SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- UpdateICSWidth(hText);\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Window Proc for main window\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/* Process messages for main window, etc. */\r
-LRESULT CALLBACK\r
-WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- FARPROC lpProc;\r
- int wmId;\r
- char *defName;\r
- FILE *f;\r
- UINT number;\r
- char fileTitle[MSG_SIZ];\r
- static SnapData sd;\r
- static int peek=0;\r
-\r
- switch (message) {\r
-\r
- case WM_PAINT: /* message: repaint portion of window */\r
- PaintProc(hwnd);\r
- break;\r
-\r
- case WM_ERASEBKGND:\r
- if (IsIconic(hwnd)) {\r
- /* Cheat; change the message */\r
- return (DefWindowProc(hwnd, WM_ICONERASEBKGND, wParam, lParam));\r
- } else {\r
- return (DefWindowProc(hwnd, message, wParam, lParam));\r
- }\r
- break;\r
-\r
- case WM_LBUTTONDOWN:\r
- case WM_MBUTTONDOWN:\r
- case WM_RBUTTONDOWN:\r
- case WM_LBUTTONUP:\r
- case WM_MBUTTONUP:\r
- case WM_RBUTTONUP:\r
- case WM_MOUSEMOVE:\r
- case WM_MOUSEWHEEL:\r
- MouseEvent(hwnd, message, wParam, lParam);\r
- break;\r
-\r
- case WM_KEYUP:\r
- if((char)wParam == '\b') {\r
- ForwardEvent(); peek = 0;\r
- }\r
-\r
- JAWS_KBUP_NAVIGATION\r
-\r
- break;\r
-\r
- case WM_KEYDOWN:\r
- if((char)wParam == '\b') {\r
- if(!peek) BackwardEvent(), peek = 1;\r
- }\r
-\r
- JAWS_KBDOWN_NAVIGATION\r
-\r
- break;\r
-\r
- case WM_CHAR:\r
- \r
- JAWS_ALT_INTERCEPT\r
-\r
- if (appData.icsActive && ((char)wParam == '\r' || (char)wParam > ' ' && !((char)wParam >= '1' && (char)wParam <= '9'))) { \r
- // [HGM] movenum: for non-zero digits we always do type-in dialog\r
- HWND h = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
- SetFocus(h);\r
- SendMessage(h, message, wParam, lParam);\r
- } else if(lParam != KF_REPEAT) {\r
- if (isalpha((char)wParam) || isdigit((char)wParam)) {\r
- TypeInEvent((char)wParam);\r
- } else if((char)wParam == 003) CopyGameToClipboard();\r
- else if((char)wParam == 026) PasteGameOrFENFromClipboard();\r
- }\r
-\r
- break;\r
-\r
- case WM_PALETTECHANGED:\r
- if (hwnd != (HWND)wParam && !appData.monoMode) {\r
- int nnew;\r
- HDC hdc = GetDC(hwndMain);\r
- SelectPalette(hdc, hPal, TRUE);\r
- nnew = RealizePalette(hdc);\r
- if (nnew > 0) {\r
- paletteChanged = TRUE;\r
-\r
- InvalidateRect(hwnd, &boardRect, FALSE);\r
- }\r
- ReleaseDC(hwnd, hdc);\r
- }\r
- break;\r
-\r
- case WM_QUERYNEWPALETTE:\r
- if (!appData.monoMode /*&& paletteChanged*/) {\r
- int nnew;\r
- HDC hdc = GetDC(hwndMain);\r
- paletteChanged = FALSE;\r
- SelectPalette(hdc, hPal, FALSE);\r
- nnew = RealizePalette(hdc);\r
- if (nnew > 0) {\r
- InvalidateRect(hwnd, &boardRect, FALSE);\r
- }\r
- ReleaseDC(hwnd, hdc);\r
- return TRUE;\r
- }\r
- return FALSE;\r
-\r
- case WM_COMMAND: /* message: command from application menu */\r
- wmId = LOWORD(wParam);\r
-\r
- switch (wmId) {\r
- case IDM_NewGame:\r
- ResetGameEvent();\r
- SAY("new game enter a move to play against the computer with white");\r
- break;\r
-\r
- case IDM_NewGameFRC:\r
- if( NewGameFRC() == 0 ) {\r
- ResetGameEvent();\r
- }\r
- break;\r
-\r
- case IDM_NewVariant:\r
- NewVariantPopup(hwnd);\r
- break;\r
-\r
- case IDM_LoadGame:\r
- LoadGameDialog(hwnd, _("Load Game from File"));\r
- break;\r
-\r
- case IDM_LoadNextGame:\r
- ReloadGame(1);\r
- break;\r
-\r
- case IDM_LoadPrevGame:\r
- ReloadGame(-1);\r
- break;\r
-\r
- case IDM_ReloadGame:\r
- ReloadGame(0);\r
- break;\r
-\r
- case IDM_LoadPosition:\r
- if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {\r
- Reset(FALSE, TRUE);\r
- }\r
- number = 1;\r
- f = OpenFileDialog(hwnd, "rb", "",\r
- appData.oldSaveStyle ? "pos" : "fen",\r
- POSITION_FILT,\r
- _("Load Position from File"), &number, fileTitle, NULL);\r
- if (f != NULL) {\r
- LoadPosition(f, number, fileTitle);\r
- }\r
- break;\r
-\r
- case IDM_LoadNextPosition:\r
- ReloadPosition(1);\r
- break;\r
-\r
- case IDM_LoadPrevPosition:\r
- ReloadPosition(-1);\r
- break;\r
-\r
- case IDM_ReloadPosition:\r
- ReloadPosition(0);\r
- break;\r
-\r
- case IDM_SaveGame:\r
- defName = DefaultFileName(appData.oldSaveStyle ? "gam" : "pgn");\r
- f = OpenFileDialog(hwnd, "a", defName,\r
- appData.oldSaveStyle ? "gam" : "pgn",\r
- GAME_FILT,\r
- _("Save Game to File"), NULL, fileTitle, NULL);\r
- if (f != NULL) {\r
- SaveGame(f, 0, "");\r
- }\r
- break;\r
-\r
- case IDM_SavePosition:\r
- defName = DefaultFileName(appData.oldSaveStyle ? "pos" : "fen");\r
- f = OpenFileDialog(hwnd, "a", defName,\r
- appData.oldSaveStyle ? "pos" : "fen",\r
- POSITION_FILT,\r
- _("Save Position to File"), NULL, fileTitle, NULL);\r
- if (f != NULL) {\r
- SavePosition(f, 0, "");\r
- }\r
- break;\r
-\r
- case IDM_SaveDiagram:\r
- defName = "diagram";\r
- f = OpenFileDialog(hwnd, "wb", defName,\r
- "bmp",\r
- DIAGRAM_FILT,\r
- _("Save Diagram to File"), NULL, fileTitle, NULL);\r
- if (f != NULL) {\r
- SaveDiagram(f);\r
- }\r
- break;\r
-\r
- case IDM_SaveSelected:\r
- f = OpenFileDialog(hwnd, "a", "",\r
- "pgn",\r
- GAME_FILT,\r
- _("Save Game to File"), NULL, fileTitle, NULL);\r
- if (f != NULL) {\r
- SaveSelected(f, 0, "");\r
- }\r
- break;\r
-\r
- case IDM_CreateBook:\r
- CreateBookEvent();\r
- break;\r
-\r
- case IDM_CopyGame:\r
- CopyGameToClipboard();\r
- break;\r
-\r
- case IDM_PasteGame:\r
- PasteGameFromClipboard();\r
- break;\r
-\r
- case IDM_CopyGameListToClipboard:\r
- CopyGameListToClipboard();\r
- break;\r
-\r
- /* [AS] Autodetect FEN or PGN data */\r
- case IDM_PasteAny:\r
- PasteGameOrFENFromClipboard();\r
- break;\r
-\r
- /* [AS] Move history */\r
- case IDM_ShowMoveHistory:\r
- if( MoveHistoryIsUp() ) {\r
- MoveHistoryPopDown();\r
- }\r
- else {\r
- MoveHistoryPopUp();\r
- }\r
- break;\r
-\r
- /* [AS] Eval graph */\r
- case IDM_ShowEvalGraph:\r
- if( EvalGraphIsUp() ) {\r
- EvalGraphPopDown();\r
- }\r
- else {\r
- EvalGraphPopUp();\r
- SetFocus(hwndMain);\r
- }\r
- break;\r
-\r
- /* [AS] Engine output */\r
- case IDM_ShowEngineOutput:\r
- if( EngineOutputIsUp() ) {\r
- EngineOutputPopDown();\r
- }\r
- else {\r
- EngineOutputPopUp();\r
- }\r
- break;\r
-\r
- /* [AS] User adjudication */\r
- case IDM_UserAdjudication_White:\r
- UserAdjudicationEvent( +1 );\r
- break;\r
-\r
- case IDM_UserAdjudication_Black:\r
- UserAdjudicationEvent( -1 );\r
- break;\r
-\r
- case IDM_UserAdjudication_Draw:\r
- UserAdjudicationEvent( 0 );\r
- break;\r
-\r
- /* [AS] Game list options dialog */\r
- case IDM_GameListOptions:\r
- GameListOptions();\r
- break;\r
-\r
- case IDM_NewChat:\r
- ChatPopUp(NULL);\r
- break;\r
-\r
- case IDM_CopyPosition:\r
- CopyFENToClipboard();\r
- break;\r
-\r
- case IDM_PastePosition:\r
- PasteFENFromClipboard();\r
- break;\r
-\r
- case IDM_MailMove:\r
- MailMoveEvent();\r
- break;\r
-\r
- case IDM_ReloadCMailMsg:\r
- Reset(TRUE, TRUE);\r
- ReloadCmailMsgEvent(FALSE);\r
- break;\r
-\r
- case IDM_Minimize:\r
- ShowWindow(hwnd, SW_MINIMIZE);\r
- break;\r
-\r
- case IDM_Exit:\r
- ExitEvent(0);\r
- break;\r
-\r
- case IDM_MachineWhite:\r
- MachineWhiteEvent();\r
- /*\r
- * refresh the tags dialog only if it's visible\r
- */\r
- if (gameMode == MachinePlaysWhite && IsWindowVisible(editTagsDialog)) {\r
- char *tags;\r
- tags = PGNTags(&gameInfo);\r
- TagsPopUp(tags, CmailMsg());\r
- free(tags);\r
- }\r
- SAY("computer starts playing white");\r
- break;\r
-\r
- case IDM_MachineBlack:\r
- MachineBlackEvent();\r
- /*\r
- * refresh the tags dialog only if it's visible\r
- */\r
- if (gameMode == MachinePlaysBlack && IsWindowVisible(editTagsDialog)) {\r
- char *tags;\r
- tags = PGNTags(&gameInfo);\r
- TagsPopUp(tags, CmailMsg());\r
- free(tags);\r
- }\r
- SAY("computer starts playing black");\r
- break;\r
-\r
- case IDM_Match: // [HGM] match: flows into next case, after setting Match Mode and nr of Games\r
- if(matchMode) EnableMenuItem(GetMenu(hwndMain), IDM_Match, MF_BYCOMMAND|MF_GRAYED);\r
- MatchEvent(2); // distinguish from command-line-triggered case (matchMode=1)\r
- break;\r
-\r
- case IDM_TwoMachines:\r
- TwoMachinesEvent();\r
- /*\r
-\r
- * refresh the tags dialog only if it's visible\r
- */\r
- if (gameMode == TwoMachinesPlay && IsWindowVisible(editTagsDialog)) {\r
- char *tags;\r
- tags = PGNTags(&gameInfo);\r
- TagsPopUp(tags, CmailMsg());\r
- free(tags);\r
- }\r
- SAY("computer starts playing both sides");\r
- break;\r
-\r
- case IDM_AnalysisMode:\r
- if(AnalyzeModeEvent()) {\r
- SAY("analyzing current position");\r
- }\r
- break;\r
-\r
- case IDM_AnalyzeFile:\r
- AnalyzeFileEvent();\r
- break;\r
-\r
- case IDM_IcsClient:\r
- IcsClientEvent();\r
- break;\r
-\r
- case IDM_EditGame:\r
- case IDM_EditGame2:\r
- EditGameEvent();\r
- SAY("edit game");\r
- break;\r
-\r
- case IDM_EditPosition:\r
- case IDM_EditPosition2:\r
- EditPositionEvent();\r
- SAY("enter a FEN string or setup a position on the board using the control R pop up menu");\r
- break;\r
-\r
- case IDM_Training:\r
- TrainingEvent();\r
- break;\r
-\r
- case IDM_ShowGameList:\r
- ShowGameListProc();\r
- break;\r
-\r
- case IDM_EditProgs1:\r
- EditTagsPopUp(firstChessProgramNames, &firstChessProgramNames);\r
- break;\r
-\r
- case IDM_LoadProg1:\r
- LoadEnginePopUp(hwndMain, 0);\r
- break;\r
-\r
- case IDM_LoadProg2:\r
- LoadEnginePopUp(hwndMain, 1);\r
- break;\r
-\r
- case IDM_EditServers:\r
- EditTagsPopUp(icsNames, &icsNames);\r
- break;\r
-\r
- case IDM_EditTags:\r
- case IDM_Tags:\r
- EditTagsProc();\r
- break;\r
-\r
- case IDM_EditBook:\r
- EditBookEvent();\r
- break;\r
-\r
- case IDM_EditComment:\r
- case IDM_Comment:\r
- if (commentUp && editComment) {\r
- CommentPopDown();\r
- } else {\r
- EditCommentEvent();\r
- }\r
- break;\r
-\r
- case IDM_Pause:\r
- PauseEvent();\r
- break;\r
-\r
- case IDM_Accept:\r
- AcceptEvent();\r
- break;\r
-\r
- case IDM_Decline:\r
- DeclineEvent();\r
- break;\r
-\r
- case IDM_Rematch:\r
-\r
- RematchEvent();\r
- break;\r
-\r
- case IDM_CallFlag:\r
- CallFlagEvent();\r
- break;\r
-\r
- case IDM_Draw:\r
- DrawEvent();\r
- break;\r
-\r
- case IDM_Adjourn:\r
- AdjournEvent();\r
- break;\r
-\r
- case IDM_Abort:\r
- AbortEvent();\r
- break;\r
-\r
- case IDM_Resign:\r
- ResignEvent();\r
- break;\r
-\r
- case IDM_StopObserving:\r
- StopObservingEvent();\r
- break;\r
-\r
- case IDM_StopExamining:\r
- StopExaminingEvent();\r
- break;\r
-\r
- case IDM_Upload:\r
- UploadGameEvent();\r
- break;\r
-\r
- case IDM_TypeInMove:\r
- TypeInEvent('\000');\r
- break;\r
-\r
- case IDM_TypeInName:\r
- PopUpNameDialog('\000');\r
- break;\r
-\r
- case IDM_Backward:\r
- BackwardEvent();\r
- SetFocus(hwndMain);\r
- break;\r
-\r
- JAWS_MENU_ITEMS\r
-\r
- case IDM_Forward:\r
- ForwardEvent();\r
- SetFocus(hwndMain);\r
- break;\r
-\r
- case IDM_ToStart:\r
- ToStartEvent();\r
- SetFocus(hwndMain);\r
- break;\r
-\r
- case IDM_ToEnd:\r
- ToEndEvent();\r
- SetFocus(hwndMain);\r
- break;\r
-\r
- case OPT_GameListNext: // [HGM] forward these two accelerators to Game List\r
- case OPT_GameListPrev:\r
- if(gameListDialog) SendMessage(gameListDialog, WM_COMMAND, wmId, 0);\r
- break;\r
-\r
- case IDM_Revert:\r
- RevertEvent(FALSE);\r
- break;\r
-\r
- case IDM_Annotate: // [HGM] vari: revert with annotation\r
- RevertEvent(TRUE);\r
- break;\r
-\r
- case IDM_TruncateGame:\r
- TruncateGameEvent();\r
- break;\r
-\r
- case IDM_MoveNow:\r
- MoveNowEvent();\r
- break;\r
-\r
- case IDM_RetractMove:\r
- RetractMoveEvent();\r
- break;\r
-\r
- case IDM_FlipView:\r
- flipView = !flipView;\r
- DrawPosition(FALSE, NULL);\r
- break;\r
-\r
- case IDM_FlipClock:\r
- flipClock = !flipClock;\r
- DisplayBothClocks();\r
- DisplayLogos();\r
- break;\r
-\r
- case IDM_MuteSounds:\r
- mute = !mute; // [HGM] mute: keep track of global muting variable\r
- CheckMenuItem(GetMenu(hwndMain),IDM_MuteSounds, \r
- MF_BYCOMMAND|(mute?MF_CHECKED:MF_UNCHECKED));\r
- break;\r
-\r
- case IDM_GeneralOptions:\r
- GeneralOptionsPopup(hwnd);\r
- DrawPosition(TRUE, NULL);\r
- break;\r
-\r
- case IDM_BoardOptions:\r
- BoardOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_ThemeOptions:\r
- ThemeOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_EnginePlayOptions:\r
- EnginePlayOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_Engine1Options:\r
- EngineOptionsPopup(hwnd, &first);\r
- break;\r
-\r
- case IDM_Engine2Options:\r
- savedHwnd = hwnd;\r
- if(WaitForEngine(&second, SettingsMenuIfReady)) break;\r
- EngineOptionsPopup(hwnd, &second);\r
- break;\r
-\r
- case IDM_OptionsUCI:\r
- UciOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_Tourney:\r
- TourneyPopup(hwnd);\r
- break;\r
-\r
- case IDM_IcsOptions:\r
- IcsOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_Fonts:\r
- FontsOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_Sounds:\r
- SoundOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_CommPort:\r
- CommPortOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_LoadOptions:\r
- LoadOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_SaveOptions:\r
- SaveOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_TimeControl:\r
- TimeControlOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_SaveSettings:\r
- SaveSettings(settingsFileName);\r
- break;\r
-\r
- case IDM_SaveSettingsOnExit:\r
- saveSettingsOnExit = !saveSettingsOnExit;\r
- (void) CheckMenuItem(GetMenu(hwndMain), IDM_SaveSettingsOnExit,\r
- MF_BYCOMMAND|(saveSettingsOnExit ?\r
- MF_CHECKED : MF_UNCHECKED));\r
- break;\r
-\r
- case IDM_Hint:\r
- HintEvent();\r
- break;\r
-\r
- case IDM_Book:\r
- BookEvent();\r
- break;\r
-\r
- case IDM_AboutGame:\r
- AboutGameEvent();\r
- break;\r
-\r
- case IDM_Debug:\r
- appData.debugMode = !appData.debugMode;\r
- if (appData.debugMode) {\r
- char dir[MSG_SIZ];\r
- GetCurrentDirectory(MSG_SIZ, dir);\r
- SetCurrentDirectory(installDir);\r
- debugFP = fopen(appData.nameOfDebugFile, "w");\r
- SetCurrentDirectory(dir);\r
- setbuf(debugFP, NULL);\r
- } else {\r
- fclose(debugFP);\r
- debugFP = NULL;\r
- }\r
- break;\r
-\r
- case IDM_HELPCONTENTS:\r
- if (!MyHelp (hwnd, "winboard.hlp", HELP_KEY,(DWORD)(LPSTR)"CONTENTS") &&\r
- !HtmlHelp(hwnd, "winboard.chm", 0, 0) ) {\r
- MessageBox (GetFocus(),\r
- _("Unable to activate help"),\r
- szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND);\r
- }\r
- break;\r
-\r
- case IDM_HELPSEARCH:\r
- if (!MyHelp (hwnd, "winboard.hlp", HELP_PARTIALKEY, (DWORD)(LPSTR)"") &&\r
- !HtmlHelp(hwnd, "winboard.chm", 0, 0) ) {\r
- MessageBox (GetFocus(),\r
- _("Unable to activate help"),\r
- szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND);\r
- }\r
- break;\r
-\r
- case IDM_HELPHELP:\r
- if(!WinHelp(hwnd, (LPSTR)NULL, HELP_HELPONHELP, 0)) {\r
- MessageBox (GetFocus(),\r
- _("Unable to activate help"),\r
- szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND);\r
- }\r
- break;\r
-\r
- case IDM_ABOUT:\r
- lpProc = MakeProcInstance((FARPROC)About, hInst);\r
- DialogBox(hInst, \r
- (gameInfo.event && strcmp(gameInfo.event, "Easter Egg Hunt") == 0) ?\r
- "AboutBox2" : "AboutBox", hwnd, (DLGPROC)lpProc);\r
- FreeProcInstance(lpProc);\r
- break;\r
-\r
- case IDM_DirectCommand1:\r
- AskQuestionEvent(_("Direct Command"),\r
- _("Send to chess program:"), "", "1");\r
- break;\r
- case IDM_DirectCommand2:\r
- AskQuestionEvent(_("Direct Command"),\r
- _("Send to second chess program:"), "", "2");\r
- break;\r
-\r
- case EP_WhitePawn:\r
- EditPositionMenuEvent(WhitePawn, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_WhiteKnight:\r
- EditPositionMenuEvent(WhiteKnight, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_WhiteBishop:\r
- EditPositionMenuEvent(WhiteBishop, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_WhiteRook:\r
- EditPositionMenuEvent(WhiteRook, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_WhiteQueen:\r
- EditPositionMenuEvent(WhiteQueen, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_WhiteFerz:\r
- EditPositionMenuEvent(WhiteFerz, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_WhiteWazir:\r
- EditPositionMenuEvent(WhiteWazir, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_WhiteAlfil:\r
- EditPositionMenuEvent(WhiteAlfil, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_WhiteCannon:\r
- EditPositionMenuEvent(WhiteCannon, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_WhiteCardinal:\r
- EditPositionMenuEvent(WhiteAngel, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_WhiteMarshall:\r
- EditPositionMenuEvent(WhiteMarshall, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_WhiteKing:\r
- EditPositionMenuEvent(WhiteKing, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackPawn:\r
- EditPositionMenuEvent(BlackPawn, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackKnight:\r
- EditPositionMenuEvent(BlackKnight, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackBishop:\r
- EditPositionMenuEvent(BlackBishop, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackRook:\r
- EditPositionMenuEvent(BlackRook, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackQueen:\r
- EditPositionMenuEvent(BlackQueen, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackFerz:\r
- EditPositionMenuEvent(BlackFerz, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackWazir:\r
- EditPositionMenuEvent(BlackWazir, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackAlfil:\r
- EditPositionMenuEvent(BlackAlfil, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackCannon:\r
- EditPositionMenuEvent(BlackCannon, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackCardinal:\r
- EditPositionMenuEvent(BlackAngel, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackMarshall:\r
- EditPositionMenuEvent(BlackMarshall, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackKing:\r
- EditPositionMenuEvent(BlackKing, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_EmptySquare:\r
- EditPositionMenuEvent(EmptySquare, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_ClearBoard:\r
- EditPositionMenuEvent(ClearBoard, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_White:\r
- EditPositionMenuEvent(WhitePlay, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_Black:\r
- EditPositionMenuEvent(BlackPlay, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_Promote:\r
- EditPositionMenuEvent(PromotePiece, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_Demote:\r
- EditPositionMenuEvent(DemotePiece, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case DP_Pawn:\r
- DropMenuEvent(WhitePawn, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case DP_Knight:\r
- DropMenuEvent(WhiteKnight, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case DP_Bishop:\r
- DropMenuEvent(WhiteBishop, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case DP_Rook:\r
- DropMenuEvent(WhiteRook, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case DP_Queen:\r
- DropMenuEvent(WhiteQueen, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case IDM_English:\r
- barbaric = 0; appData.language = "";\r
- TranslateMenus(0);\r
- CheckMenuItem(GetMenu(hwndMain), lastChecked, MF_BYCOMMAND|MF_UNCHECKED);\r
- CheckMenuItem(GetMenu(hwndMain), IDM_English, MF_BYCOMMAND|MF_CHECKED);\r
- lastChecked = wmId;\r
- break;\r
-\r
- default:\r
- if(wmId >= IDM_RecentEngines && wmId < IDM_RecentEngines + appData.recentEngines)\r
- RecentEngineEvent(wmId - IDM_RecentEngines);\r
- else\r
- if(wmId > IDM_English && wmId < IDM_English+20) {\r
- LoadLanguageFile(languageFile[wmId - IDM_English - 1]);\r
- TranslateMenus(0);\r
- CheckMenuItem(GetMenu(hwndMain), lastChecked, MF_BYCOMMAND|MF_UNCHECKED);\r
- CheckMenuItem(GetMenu(hwndMain), wmId, MF_BYCOMMAND|MF_CHECKED);\r
- lastChecked = wmId;\r
- break;\r
- }\r
- return (DefWindowProc(hwnd, message, wParam, lParam));\r
- }\r
- break;\r
-\r
- case WM_TIMER:\r
- switch (wParam) {\r
- case CLOCK_TIMER_ID:\r
- KillTimer(hwnd, clockTimerEvent); /* Simulate one-shot timer as in X */\r
- clockTimerEvent = 0;\r
- DecrementClocks(); /* call into back end */\r
- break;\r
- case LOAD_GAME_TIMER_ID:\r
- KillTimer(hwnd, loadGameTimerEvent); /* Simulate one-shot timer as in X*/\r
- loadGameTimerEvent = 0;\r
- AutoPlayGameLoop(); /* call into back end */\r
- break;\r
- case ANALYSIS_TIMER_ID:\r
- if ((gameMode == AnalyzeMode || gameMode == AnalyzeFile\r
- || appData.icsEngineAnalyze) && appData.periodicUpdates) {\r
- AnalysisPeriodicEvent(0);\r
- } else {\r
- KillTimer(hwnd, analysisTimerEvent);\r
- analysisTimerEvent = 0;\r
- }\r
- break;\r
- case DELAYED_TIMER_ID:\r
- KillTimer(hwnd, delayedTimerEvent);\r
- delayedTimerEvent = 0;\r
- delayedTimerCallback();\r
- break;\r
- }\r
- break;\r
-\r
- case WM_USER_Input:\r
- InputEvent(hwnd, message, wParam, lParam);\r
- break;\r
-\r
- /* [AS] Also move "attached" child windows */\r
- case WM_WINDOWPOSCHANGING:\r
-\r
- if( hwnd == hwndMain && appData.useStickyWindows ) {\r
- LPWINDOWPOS lpwp = (LPWINDOWPOS) lParam;\r
-\r
- if( ((lpwp->flags & SWP_NOMOVE) == 0) /*&& ((lpwp->flags & SWP_NOSIZE) != 0)*/ ) { // [HGM] in Win8 size always accompanies move?\r
- /* Window is moving */\r
- RECT rcMain;\r
-\r
-// GetWindowRect( hwnd, &rcMain ); //[HGM] sticky: in XP this returned new position, not old\r
- rcMain.left = wpMain.x; // replace by these 4 lines to reconstruct old rect\r
- rcMain.right = wpMain.x + wpMain.width;\r
- rcMain.top = wpMain.y;\r
- rcMain.bottom = wpMain.y + wpMain.height;\r
- \r
- ReattachAfterMove( &rcMain, lpwp->x, lpwp->y, moveHistoryDialog, &wpMoveHistory );\r
- ReattachAfterMove( &rcMain, lpwp->x, lpwp->y, evalGraphDialog, &wpEvalGraph );\r
- ReattachAfterMove( &rcMain, lpwp->x, lpwp->y, engineOutputDialog, &wpEngineOutput );\r
- ReattachAfterMove( &rcMain, lpwp->x, lpwp->y, gameListDialog, &wpGameList );\r
- ReattachAfterMove( &rcMain, lpwp->x, lpwp->y, hwndConsole, &wpConsole );\r
- wpMain.x = lpwp->x;\r
- wpMain.y = lpwp->y;\r
-\r
- }\r
- }\r
- break;\r
-\r
- /* [AS] Snapping */\r
- case WM_ENTERSIZEMOVE:\r
- if(appData.debugMode) { fprintf(debugFP, "size-move\n"); }\r
- if (hwnd == hwndMain) {\r
- doingSizing = TRUE;\r
- lastSizing = 0;\r
- }\r
- return OnEnterSizeMove( &sd, hwnd, wParam, lParam );\r
- break;\r
-\r
- case WM_SIZING:\r
- if(appData.debugMode) { fprintf(debugFP, "sizing\n"); }\r
- if (hwnd == hwndMain) {\r
- lastSizing = wParam;\r
- }\r
- break;\r
-\r
- case WM_MOVING:\r
- if(appData.debugMode) { fprintf(debugFP, "moving\n"); }\r
- return OnMoving( &sd, hwnd, wParam, lParam );\r
-\r
- case WM_EXITSIZEMOVE:\r
- if(appData.debugMode) { fprintf(debugFP, "exit size-move, size = %d\n", squareSize); }\r
- if (hwnd == hwndMain) {\r
- RECT client;\r
- doingSizing = FALSE;\r
- InvalidateRect(hwnd, &boardRect, FALSE);\r
- GetClientRect(hwnd, &client);\r
- ResizeBoard(client.right, client.bottom, lastSizing);\r
- lastSizing = 0;\r
- if(appData.debugMode) { fprintf(debugFP, "square size = %d\n", squareSize); }\r
- }\r
- return OnExitSizeMove( &sd, hwnd, wParam, lParam );\r
- break;\r
-\r
- case WM_DESTROY: /* message: window being destroyed */\r
- PostQuitMessage(0);\r
- break;\r
-\r
- case WM_CLOSE:\r
- if (hwnd == hwndMain) {\r
- ExitEvent(0);\r
- }\r
- break;\r
-\r
- default: /* Passes it on if unprocessed */\r
- return (DefWindowProc(hwnd, message, wParam, lParam));\r
- }\r
-\r
-\r
- return 0;\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Misc utility routines\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
- * Decent random number generator, at least not as bad as Windows\r
- * standard rand, which returns a value in the range 0 to 0x7fff.\r
- */\r
-unsigned int randstate;\r
-\r
-int\r
-myrandom(void)\r
-{\r
- randstate = randstate * 1664525 + 1013904223;\r
- return (int) randstate & 0x7fffffff;\r
-}\r
-\r
-void\r
-mysrandom(unsigned int seed)\r
-{\r
- randstate = seed;\r
-}\r
-\r
-\r
-/* \r
- * returns TRUE if user selects a different color, FALSE otherwise \r
- */\r
-\r
-BOOL\r
-ChangeColor(HWND hwnd, COLORREF *which)\r
-{\r
- static BOOL firstTime = TRUE;\r
- static DWORD customColors[16];\r
- CHOOSECOLOR cc;\r
- COLORREF newcolor;\r
- int i;\r
- ColorClass ccl;\r
-\r
- if (firstTime) {\r
- /* Make initial colors in use available as custom colors */\r
- /* Should we put the compiled-in defaults here instead? */\r
- i = 0;\r
- customColors[i++] = lightSquareColor & 0xffffff;\r
- customColors[i++] = darkSquareColor & 0xffffff;\r
- customColors[i++] = whitePieceColor & 0xffffff;\r
- customColors[i++] = blackPieceColor & 0xffffff;\r
- customColors[i++] = highlightSquareColor & 0xffffff;\r
- customColors[i++] = premoveHighlightColor & 0xffffff;\r
-\r
- for (ccl = (ColorClass) 0; ccl < NColorClasses && i < 16; ccl++) {\r
- customColors[i++] = textAttribs[ccl].color;\r
- }\r
- while (i < 16) customColors[i++] = RGB(255, 255, 255);\r
- firstTime = FALSE;\r
- }\r
-\r
- cc.lStructSize = sizeof(cc);\r
- cc.hwndOwner = hwnd;\r
- cc.hInstance = NULL;\r
- cc.rgbResult = (DWORD) (*which & 0xffffff);\r
- cc.lpCustColors = (LPDWORD) customColors;\r
- cc.Flags = CC_RGBINIT|CC_FULLOPEN;\r
-\r
- if (!ChooseColor(&cc)) return FALSE;\r
-\r
- newcolor = (COLORREF) (0x2000000 | cc.rgbResult);\r
- if (newcolor == *which) return FALSE;\r
- *which = newcolor;\r
- return TRUE;\r
-\r
- /*\r
- InitDrawingColors();\r
- InvalidateRect(hwnd, &boardRect, FALSE);\r
- */\r
-}\r
-\r
-BOOLEAN\r
-MyLoadSound(MySound *ms)\r
-{\r
- BOOL ok = FALSE;\r
- struct stat st;\r
- FILE *f;\r
-\r
- if (ms->data && ms->flag) free(ms->data);\r
- ms->data = NULL;\r
-\r
- switch (ms->name[0]) {\r
- case NULLCHAR:\r
- /* Silence */\r
- ok = TRUE;\r
- break;\r
- case '$':\r
- /* System sound from Control Panel. Don't preload here. */\r
- ok = TRUE;\r
- break;\r
- case '!':\r
- if (ms->name[1] == NULLCHAR) {\r
- /* "!" alone = silence */\r
- ok = TRUE;\r
- } else {\r
- /* Builtin wave resource. Error if not found. */\r
- HANDLE h = FindResource(hInst, ms->name + 1, "WAVE");\r
- if (h == NULL) break;\r
- ms->data = (void *)LoadResource(hInst, h);\r
- ms->flag = 0; // not maloced, so cannot be freed!\r
- if (h == NULL) break;\r
- ok = TRUE;\r
- }\r
- break;\r
- default:\r
- /* .wav file. Error if not found. */\r
- f = fopen(ms->name, "rb");\r
- if (f == NULL) break;\r
- if (fstat(fileno(f), &st) < 0) break;\r
- ms->data = malloc(st.st_size);\r
- ms->flag = 1;\r
- if (fread(ms->data, st.st_size, 1, f) < 1) break;\r
- fclose(f);\r
- ok = TRUE;\r
- break;\r
- }\r
- if (!ok) {\r
- char buf[MSG_SIZ];\r
- snprintf(buf, MSG_SIZ, _("Error loading sound %s"), ms->name);\r
- DisplayError(buf, GetLastError());\r
- }\r
- return ok;\r
-}\r
-\r
-BOOLEAN\r
-MyPlaySound(MySound *ms)\r
-{\r
- BOOLEAN ok = FALSE;\r
-\r
- if(mute) return TRUE; // [HGM] mute: suppress all sound play when muted\r
- switch (ms->name[0]) {\r
- case NULLCHAR:\r
- if(appData.debugMode) fprintf(debugFP, "silence\n");\r
- /* Silence */\r
- ok = TRUE;\r
- break;\r
- case '$':\r
- /* System sound from Control Panel (deprecated feature).\r
- "$" alone or an unset sound name gets default beep (still in use). */\r
- if (ms->name[1]) {\r
- ok = PlaySound(ms->name + 1, NULL, SND_ALIAS|SND_ASYNC);\r
- }\r
- if (!ok) ok = MessageBeep(MB_OK);\r
- break; \r
- case '!':\r
- /* Builtin wave resource, or "!" alone for silence */\r
- if (ms->name[1]) {\r
- if (ms->data == NULL) return FALSE;\r
- ok = PlaySound(ms->data, NULL, SND_MEMORY|SND_ASYNC);\r
- } else {\r
- ok = TRUE;\r
- }\r
- break;\r
- default:\r
- /* .wav file. Error if not found. */\r
- if (ms->data == NULL) return FALSE;\r
- ok = PlaySound(ms->data, NULL, SND_MEMORY|SND_ASYNC);\r
- break;\r
- }\r
- /* Don't print an error: this can happen innocently if the sound driver\r
- is busy; for instance, if another instance of WinBoard is playing\r
- a sound at about the same time. */\r
- return ok;\r
-}\r
-\r
-\r
-LRESULT CALLBACK\r
-OldOpenFileHook(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- BOOL ok;\r
- OPENFILENAME *ofn;\r
- static UINT *number; /* gross that this is static */\r
-\r
- switch (message) {\r
- case WM_INITDIALOG: /* message: initialize dialog box */\r
- /* Center the dialog over the application window */\r
- ofn = (OPENFILENAME *) lParam;\r
- if (ofn->Flags & OFN_ENABLETEMPLATE) {\r
- number = (UINT *) ofn->lCustData;\r
- SendMessage(GetDlgItem(hDlg, edt2), WM_SETTEXT, 0, (LPARAM) "");\r
- } else {\r
- number = NULL;\r
- }\r
- CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
- Translate(hDlg, 1536);\r
- return FALSE; /* Allow for further processing */\r
-\r
- case WM_COMMAND:\r
- if ((LOWORD(wParam) == IDOK) && (number != NULL)) {\r
- *number = GetDlgItemInt(hDlg, OPT_IndexNumberOld, &ok, FALSE);\r
- }\r
- return FALSE; /* Allow for further processing */\r
- }\r
- return FALSE;\r
-}\r
-\r
-UINT APIENTRY\r
-OpenFileHook(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)\r
-{\r
- static UINT *number;\r
- OPENFILENAME *ofname;\r
- OFNOTIFY *ofnot;\r
- switch (uiMsg) {\r
- case WM_INITDIALOG:\r
- Translate(hdlg, DLG_IndexNumber);\r
- ofname = (OPENFILENAME *)lParam;\r
- number = (UINT *)(ofname->lCustData);\r
- break;\r
- case WM_NOTIFY:\r
- ofnot = (OFNOTIFY *)lParam;\r
- if (ofnot->hdr.code == CDN_FILEOK) {\r
- *number = GetDlgItemInt(hdlg, OPT_IndexNumber, NULL, FALSE);\r
- }\r
- break;\r
- }\r
- return 0;\r
-}\r
-\r
-\r
-FILE *\r
-OpenFileDialog(HWND hwnd, char *write, char *defName, char *defExt, // [HGM] diag: type of 'write' now string\r
- char *nameFilt, char *dlgTitle, UINT *number,\r
- char fileTitle[MSG_SIZ], char fileName[MSG_SIZ])\r
-{\r
- OPENFILENAME openFileName;\r
- char buf1[MSG_SIZ];\r
- FILE *f;\r
-\r
- if (fileName == NULL) fileName = buf1;\r
- if (defName == NULL) {\r
- safeStrCpy(fileName, "*.", 3 );\r
- strcat(fileName, defExt);\r
- } else {\r
- safeStrCpy(fileName, defName, MSG_SIZ );\r
- }\r
- if (fileTitle) safeStrCpy(fileTitle, "", MSG_SIZ );\r
- if (number) *number = 0;\r
-\r
- openFileName.lStructSize = sizeof(OPENFILENAME);\r
- openFileName.hwndOwner = hwnd;\r
- openFileName.hInstance = (HANDLE) hInst;\r
- openFileName.lpstrFilter = nameFilt;\r
- openFileName.lpstrCustomFilter = (LPSTR) NULL;\r
- openFileName.nMaxCustFilter = 0L;\r
- openFileName.nFilterIndex = 1L;\r
- openFileName.lpstrFile = fileName;\r
- openFileName.nMaxFile = MSG_SIZ;\r
- openFileName.lpstrFileTitle = fileTitle;\r
- openFileName.nMaxFileTitle = fileTitle ? MSG_SIZ : 0;\r
- openFileName.lpstrInitialDir = NULL;\r
- openFileName.lpstrTitle = dlgTitle;\r
- openFileName.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY \r
- | (write[0] != 'r' ? 0 : OFN_FILEMUSTEXIST) \r
- | (number ? OFN_ENABLETEMPLATE | OFN_ENABLEHOOK: 0)\r
- | (oldDialog ? 0 : OFN_EXPLORER);\r
- openFileName.nFileOffset = 0;\r
- openFileName.nFileExtension = 0;\r
- openFileName.lpstrDefExt = defExt;\r
- openFileName.lCustData = (LONG) number;\r
- openFileName.lpfnHook = oldDialog ?\r
- (LPOFNHOOKPROC) OldOpenFileHook : (LPOFNHOOKPROC) OpenFileHook;\r
- openFileName.lpTemplateName = (LPSTR)(oldDialog ? 1536 : DLG_IndexNumber);\r
-\r
- if (write[0] != 'r' ? GetSaveFileName(&openFileName) : \r
- GetOpenFileName(&openFileName)) {\r
- /* open the file */\r
- f = fopen(openFileName.lpstrFile, write);\r
- if (f == NULL) {\r
- MessageBox(hwnd, _("File open failed"), NULL,\r
- MB_OK|MB_ICONEXCLAMATION);\r
- return NULL;\r
- }\r
- } else {\r
- int err = CommDlgExtendedError();\r
- if (err != 0) DisplayError(_("Internal error in file dialog box"), err);\r
- return FALSE;\r
- }\r
- return f;\r
-}\r
-\r
-\r
-\r
-VOID APIENTRY\r
-MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def)\r
-{\r
- HMENU hmenuTrackPopup; /* floating pop-up menu */\r
-\r
- /*\r
- * Get the first pop-up menu in the menu template. This is the\r
- * menu that TrackPopupMenu displays.\r
- */\r
- hmenuTrackPopup = GetSubMenu(hmenu, 0);\r
- TranslateOneMenu(10, hmenuTrackPopup);\r
-\r
- SetMenuDefaultItem(hmenuTrackPopup, def, FALSE);\r
-\r
- /*\r
- * TrackPopup uses screen coordinates, so convert the\r
- * coordinates of the mouse click to screen coordinates.\r
- */\r
- ClientToScreen(hwnd, (LPPOINT) &pt);\r
-\r
- /* Draw and track the floating pop-up menu. */\r
- TrackPopupMenu(hmenuTrackPopup, TPM_CENTERALIGN | TPM_RIGHTBUTTON,\r
- pt.x, pt.y, 0, hwnd, NULL);\r
-\r
- /* Destroy the menu.*/\r
- DestroyMenu(hmenu);\r
-}\r
- \r
-typedef struct {\r
- HWND hDlg, hText;\r
- int sizeX, sizeY, newSizeX, newSizeY;\r
- HDWP hdwp;\r
-} ResizeEditPlusButtonsClosure;\r
-\r
-BOOL CALLBACK\r
-ResizeEditPlusButtonsCallback(HWND hChild, LPARAM lparam)\r
-{\r
- ResizeEditPlusButtonsClosure *cl = (ResizeEditPlusButtonsClosure *)lparam;\r
- RECT rect;\r
- POINT pt;\r
-\r
- if (hChild == cl->hText) return TRUE;\r
- GetWindowRect(hChild, &rect); /* gives screen coords */\r
- pt.x = rect.left + (cl->newSizeX - cl->sizeX)/2;\r
- pt.y = rect.top + cl->newSizeY - cl->sizeY;\r
- ScreenToClient(cl->hDlg, &pt);\r
- cl->hdwp = DeferWindowPos(cl->hdwp, hChild, NULL, \r
- pt.x, pt.y, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);\r
- return TRUE;\r
-}\r
-\r
-/* Resize a dialog that has a (rich) edit field filling most of\r
- the top, with a row of buttons below */\r
-VOID\r
-ResizeEditPlusButtons(HWND hDlg, HWND hText, int sizeX, int sizeY, int newSizeX, int newSizeY)\r
-{\r
- RECT rectText;\r
- int newTextHeight, newTextWidth;\r
- ResizeEditPlusButtonsClosure cl;\r
- \r
- /*if (IsIconic(hDlg)) return;*/\r
- if (newSizeX == sizeX && newSizeY == sizeY) return;\r
- \r
- cl.hdwp = BeginDeferWindowPos(8);\r
-\r
- GetWindowRect(hText, &rectText); /* gives screen coords */\r
- newTextWidth = rectText.right - rectText.left + newSizeX - sizeX;\r
- newTextHeight = rectText.bottom - rectText.top + newSizeY - sizeY;\r
- if (newTextHeight < 0) {\r
- newSizeY += -newTextHeight;\r
- newTextHeight = 0;\r
- }\r
- cl.hdwp = DeferWindowPos(cl.hdwp, hText, NULL, 0, 0, \r
- newTextWidth, newTextHeight, SWP_NOZORDER|SWP_NOMOVE);\r
-\r
- cl.hDlg = hDlg;\r
- cl.hText = hText;\r
- cl.sizeX = sizeX;\r
- cl.sizeY = sizeY;\r
- cl.newSizeX = newSizeX;\r
- cl.newSizeY = newSizeY;\r
- EnumChildWindows(hDlg, ResizeEditPlusButtonsCallback, (LPARAM)&cl);\r
-\r
- EndDeferWindowPos(cl.hdwp);\r
-}\r
-\r
-BOOL CenterWindowEx(HWND hwndChild, HWND hwndParent, int mode)\r
-{\r
- RECT rChild, rParent;\r
- int wChild, hChild, wParent, hParent;\r
- int wScreen, hScreen, xNew, yNew;\r
- HDC hdc;\r
-\r
- /* Get the Height and Width of the child window */\r
- GetWindowRect (hwndChild, &rChild);\r
- wChild = rChild.right - rChild.left;\r
- hChild = rChild.bottom - rChild.top;\r
-\r
- /* Get the Height and Width of the parent window */\r
- GetWindowRect (hwndParent, &rParent);\r
- wParent = rParent.right - rParent.left;\r
- hParent = rParent.bottom - rParent.top;\r
-\r
- /* Get the display limits */\r
- hdc = GetDC (hwndChild);\r
- wScreen = GetDeviceCaps (hdc, HORZRES);\r
- hScreen = GetDeviceCaps (hdc, VERTRES);\r
- ReleaseDC(hwndChild, hdc);\r
-\r
- /* Calculate new X position, then adjust for screen */\r
- xNew = rParent.left + ((wParent - wChild) /2);\r
- if (xNew < 0) {\r
- xNew = 0;\r
- } else if ((xNew+wChild) > wScreen) {\r
- xNew = wScreen - wChild;\r
- }\r
-\r
- /* Calculate new Y position, then adjust for screen */\r
- if( mode == 0 ) {\r
- yNew = rParent.top + ((hParent - hChild) /2);\r
- }\r
- else {\r
- yNew = rParent.top + GetSystemMetrics( SM_CYCAPTION ) * 2 / 3;\r
- }\r
-\r
- if (yNew < 0) {\r
- yNew = 0;\r
- } else if ((yNew+hChild) > hScreen) {\r
- yNew = hScreen - hChild;\r
- }\r
-\r
- /* Set it, and return */\r
- return SetWindowPos (hwndChild, NULL,\r
- xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);\r
-}\r
-\r
-/* Center one window over another */\r
-BOOL CenterWindow (HWND hwndChild, HWND hwndParent)\r
-{\r
- return CenterWindowEx( hwndChild, hwndParent, 0 );\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Startup Dialog functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-void\r
-InitComboStrings(HANDLE hwndCombo, char **cd)\r
-{\r
- SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0);\r
-\r
- while (*cd != NULL) {\r
- SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) T_(*cd));\r
- cd++;\r
- }\r
-}\r
-\r
-void\r
-InitComboStringsFromOption(HANDLE hwndCombo, char *str)\r
-{\r
- char buf1[MAX_ARG_LEN];\r
- int len;\r
-\r
- if (str[0] == '@') {\r
- FILE* f = fopen(str + 1, "r");\r
- if (f == NULL) {\r
- DisplayFatalError(str + 1, errno, 2);\r
- return;\r
- }\r
- len = fread(buf1, 1, sizeof(buf1)-1, f);\r
- fclose(f);\r
- buf1[len] = NULLCHAR;\r
- str = buf1;\r
- }\r
-\r
- SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0);\r
-\r
- for (;;) {\r
- char buf[MSG_SIZ];\r
- char *end = strchr(str, '\n');\r
- if (end == NULL) return;\r
- memcpy(buf, str, end - str);\r
- buf[end - str] = NULLCHAR;\r
- SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) buf);\r
- str = end + 1;\r
- }\r
-}\r
-\r
-void\r
-SetStartupDialogEnables(HWND hDlg)\r
-{\r
- EnableWindow(GetDlgItem(hDlg, OPT_ChessEngineName),\r
- IsDlgButtonChecked(hDlg, OPT_ChessEngine) ||\r
- (appData.zippyPlay && IsDlgButtonChecked(hDlg, OPT_ChessServer)));\r
- EnableWindow(GetDlgItem(hDlg, OPT_SecondChessEngineName),\r
- IsDlgButtonChecked(hDlg, OPT_ChessEngine));\r
- EnableWindow(GetDlgItem(hDlg, OPT_ChessServerName),\r
- IsDlgButtonChecked(hDlg, OPT_ChessServer));\r
- EnableWindow(GetDlgItem(hDlg, OPT_AdditionalOptions),\r
- IsDlgButtonChecked(hDlg, OPT_AnyAdditional));\r
- EnableWindow(GetDlgItem(hDlg, IDOK),\r
- IsDlgButtonChecked(hDlg, OPT_ChessEngine) ||\r
- IsDlgButtonChecked(hDlg, OPT_ChessServer) ||\r
- IsDlgButtonChecked(hDlg, OPT_View));\r
-}\r
-\r
-char *\r
-QuoteForFilename(char *filename)\r
-{\r
- int dquote, space;\r
- dquote = strchr(filename, '"') != NULL;\r
- space = strchr(filename, ' ') != NULL;\r
- if (dquote || space) {\r
- if (dquote) {\r
- return "'";\r
- } else {\r
- return "\"";\r
- }\r
- } else {\r
- return "";\r
- }\r
-}\r
-\r
-VOID\r
-InitEngineBox(HWND hDlg, HWND hwndCombo, char* nthcp, char* nthd, char* nthdir, char *nthnames)\r
-{\r
- char buf[MSG_SIZ];\r
- char *q;\r
-\r
- InitComboStringsFromOption(hwndCombo, nthnames);\r
- q = QuoteForFilename(nthcp);\r
- snprintf(buf, MSG_SIZ, "%s%s%s", q, nthcp, q);\r
- if (*nthdir != NULLCHAR) {\r
- q = QuoteForFilename(nthdir);\r
- snprintf(buf + strlen(buf), MSG_SIZ, " /%s=%s%s%s", nthd, q, nthdir, q);\r
- }\r
- if (*nthcp == NULLCHAR) {\r
- SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
- } else if (SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) buf) == CB_ERR) {\r
- SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);\r
- SendMessage(hwndCombo, WM_SETTEXT, (WPARAM) 0, (LPARAM) buf);\r
- }\r
-}\r
-\r
-LRESULT CALLBACK\r
-StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- char buf[MSG_SIZ];\r
- HANDLE hwndCombo;\r
- char *p;\r
-\r
- switch (message) {\r
- case WM_INITDIALOG:\r
- /* Center the dialog */\r
- CenterWindow (hDlg, GetDesktopWindow());\r
- Translate(hDlg, DLG_Startup);\r
- /* Initialize the dialog items */\r
- InitEngineBox(hDlg, GetDlgItem(hDlg, OPT_ChessEngineName),\r
- appData.firstChessProgram, "fd", appData.firstDirectory,\r
- firstChessProgramNames);\r
- InitEngineBox(hDlg, GetDlgItem(hDlg, OPT_SecondChessEngineName),\r
- appData.secondChessProgram, singleList ? "fd" : "sd", appData.secondDirectory,\r
- singleList ? firstChessProgramNames : secondChessProgramNames); //[HGM] single: use first list in second combo\r
- hwndCombo = GetDlgItem(hDlg, OPT_ChessServerName);\r
- InitComboStringsFromOption(hwndCombo, icsNames); \r
- snprintf(buf, MSG_SIZ, "%s /icsport=%s", appData.icsHost, appData.icsPort);\r
- if (*appData.icsHelper != NULLCHAR) {\r
- char *q = QuoteForFilename(appData.icsHelper);\r
- sprintf(buf + strlen(buf), " /icshelper=%s%s%s", q, appData.icsHelper, q);\r
- }\r
- if (*appData.icsHost == NULLCHAR) {\r
- SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
- /*SendMessage(hwndCombo, CB_SHOWDROPDOWN, (WPARAM) TRUE, (LPARAM) 0); !!too soon */\r
- } else if (SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) buf) == CB_ERR) {\r
- SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);\r
- SendMessage(hwndCombo, WM_SETTEXT, (WPARAM) 0, (LPARAM) buf);\r
- }\r
-\r
- if (appData.icsActive) {\r
- CheckDlgButton(hDlg, OPT_ChessServer, BST_CHECKED);\r
- }\r
- else if (appData.noChessProgram) {\r
- CheckDlgButton(hDlg, OPT_View, BST_CHECKED);\r
- }\r
- else {\r
- CheckDlgButton(hDlg, OPT_ChessEngine, BST_CHECKED);\r
- }\r
-\r
- SetStartupDialogEnables(hDlg);\r
- return TRUE;\r
-\r
- case WM_COMMAND:\r
- switch (LOWORD(wParam)) {\r
- case IDOK:\r
- if (IsDlgButtonChecked(hDlg, OPT_ChessEngine)) {\r
- safeStrCpy(buf, "/fcp=", sizeof(buf)/sizeof(buf[0]) );\r
- GetDlgItemText(hDlg, OPT_ChessEngineName, buf + strlen(buf), sizeof(buf) - strlen(buf));\r
- p = buf;\r
- comboLine = strdup(p+5); // [HGM] recent: remember complete line of first combobox\r
- ParseArgs(StringGet, &p);\r
- safeStrCpy(buf, singleList ? "/fcp=" : "/scp=", sizeof(buf)/sizeof(buf[0]) );\r
- GetDlgItemText(hDlg, OPT_SecondChessEngineName, buf + strlen(buf), sizeof(buf) - strlen(buf));\r
- p = buf;\r
- SwapEngines(singleList); // temporarily swap first and second, to load a second 'first', ...\r
- ParseArgs(StringGet, &p);\r
- SwapEngines(singleList); // ... and then make it 'second'\r
-\r
- appData.noChessProgram = FALSE;\r
- appData.icsActive = FALSE;\r
- } else if (IsDlgButtonChecked(hDlg, OPT_ChessServer)) {\r
- safeStrCpy(buf, "/ics /icshost=", sizeof(buf)/sizeof(buf[0]) );\r
- GetDlgItemText(hDlg, OPT_ChessServerName, buf + strlen(buf), sizeof(buf) - strlen(buf));\r
- p = buf;\r
- ParseArgs(StringGet, &p);\r
- if (appData.zippyPlay) {\r
- safeStrCpy(buf, "/fcp=", sizeof(buf)/sizeof(buf[0]) );\r
- GetDlgItemText(hDlg, OPT_ChessEngineName, buf + strlen(buf), sizeof(buf) - strlen(buf));\r
- p = buf;\r
- ParseArgs(StringGet, &p);\r
- }\r
- } else if (IsDlgButtonChecked(hDlg, OPT_View)) {\r
- appData.noChessProgram = TRUE;\r
- appData.icsActive = FALSE;\r
- } else {\r
- MessageBox(hDlg, _("Choose an option, or cancel to exit"),\r
- _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
- return TRUE;\r
- }\r
- if (IsDlgButtonChecked(hDlg, OPT_AnyAdditional)) {\r
- GetDlgItemText(hDlg, OPT_AdditionalOptions, buf, sizeof(buf));\r
- p = buf;\r
- ParseArgs(StringGet, &p);\r
- }\r
- EndDialog(hDlg, TRUE);\r
- return TRUE;\r
-\r
- case IDCANCEL:\r
- ExitEvent(0);\r
- return TRUE;\r
-\r
- case IDM_HELPCONTENTS:\r
- if (!WinHelp (hDlg, "winboard.hlp", HELP_KEY,(DWORD)(LPSTR)"CONTENTS")) {\r
- MessageBox (GetFocus(),\r
- _("Unable to activate help"),\r
- szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND);\r
- }\r
- break;\r
-\r
- default:\r
- SetStartupDialogEnables(hDlg);\r
- break;\r
- }\r
- break;\r
- }\r
- return FALSE;\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * About box dialog functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/* Process messages for "About" dialog box */\r
-LRESULT CALLBACK\r
-About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- switch (message) {\r
- case WM_INITDIALOG: /* message: initialize dialog box */\r
- /* Center the dialog over the application window */\r
- CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
- SetDlgItemText(hDlg, ABOUTBOX_Version, programVersion);\r
- Translate(hDlg, ABOUTBOX);\r
- JAWS_COPYRIGHT\r
- return (TRUE);\r
-\r
- case WM_COMMAND: /* message: received a command */\r
- if (LOWORD(wParam) == IDOK /* "OK" box selected? */\r
- || LOWORD(wParam) == IDCANCEL) { /* System menu close command? */\r
- EndDialog(hDlg, TRUE); /* Exit the dialog */\r
- return (TRUE);\r
- }\r
- break;\r
- }\r
- return (FALSE);\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Comment Dialog functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-LRESULT CALLBACK\r
-CommentDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- static HANDLE hwndText = NULL;\r
- int len, newSizeX, newSizeY;\r
- static int sizeX, sizeY;\r
- char *str;\r
- RECT rect;\r
- MINMAXINFO *mmi;\r
-\r
- switch (message) {\r
- case WM_INITDIALOG: /* message: initialize dialog box */\r
- /* Initialize the dialog items */\r
- Translate(hDlg, DLG_EditComment);\r
- hwndText = GetDlgItem(hDlg, OPT_CommentText);\r
- SetDlgItemText(hDlg, OPT_CommentText, commentText);\r
- EnableWindow(GetDlgItem(hDlg, OPT_CancelComment), editComment);\r
- EnableWindow(GetDlgItem(hDlg, OPT_ClearComment), editComment);\r
- EnableWindow(GetDlgItem(hDlg, OPT_EditComment), !editComment);\r
- SendMessage(hwndText, EM_SETREADONLY, !editComment, 0);\r
- SetWindowText(hDlg, commentTitle);\r
- if (editComment) {\r
- SetFocus(hwndText);\r
- } else {\r
- SetFocus(GetDlgItem(hDlg, IDOK));\r
- }\r
- SendMessage(GetDlgItem(hDlg, OPT_CommentText),\r
- WM_SETFONT, (WPARAM)font[boardSize][COMMENT_FONT]->hf,\r
- MAKELPARAM(FALSE, 0));\r
- /* Size and position the dialog */\r
- if (!commentDialog) {\r
- commentDialog = hDlg;\r
- GetClientRect(hDlg, &rect);\r
- sizeX = rect.right;\r
- sizeY = rect.bottom;\r
- if (wpComment.x != CW_USEDEFAULT && wpComment.y != CW_USEDEFAULT &&\r
- wpComment.width != CW_USEDEFAULT && wpComment.height != CW_USEDEFAULT) {\r
- WINDOWPLACEMENT wp;\r
- EnsureOnScreen(&wpComment.x, &wpComment.y, 0, 0);\r
- wp.length = sizeof(WINDOWPLACEMENT);\r
- wp.flags = 0;\r
- wp.showCmd = SW_SHOW;\r
- wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;\r
- wp.rcNormalPosition.left = wpComment.x;\r
- wp.rcNormalPosition.right = wpComment.x + wpComment.width;\r
- wp.rcNormalPosition.top = wpComment.y;\r
- wp.rcNormalPosition.bottom = wpComment.y + wpComment.height;\r
- SetWindowPlacement(hDlg, &wp);\r
-\r
- GetClientRect(hDlg, &rect);\r
- newSizeX = rect.right;\r
- newSizeY = rect.bottom;\r
- ResizeEditPlusButtons(hDlg, hwndText, sizeX, sizeY,\r
- newSizeX, newSizeY);\r
- sizeX = newSizeX;\r
- sizeY = newSizeY;\r
- }\r
- }\r
- SendDlgItemMessage( hDlg, OPT_CommentText, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_KEYEVENTS );\r
- return FALSE;\r
-\r
- case WM_COMMAND: /* message: received a command */\r
- switch (LOWORD(wParam)) {\r
- case IDOK:\r
- if (editComment) {\r
- char *p, *q;\r
- /* Read changed options from the dialog box */\r
- hwndText = GetDlgItem(hDlg, OPT_CommentText);\r
- len = GetWindowTextLength(hwndText);\r
- str = (char *) malloc(len + 1);\r
- GetWindowText(hwndText, str, len + 1);\r
- p = q = str;\r
- while (*q) {\r
- if (*q == '\r')\r
- q++;\r
- else\r
- *p++ = *q++;\r
- }\r
- *p = NULLCHAR;\r
- ReplaceComment(commentIndex, str);\r
- free(str);\r
- }\r
- CommentPopDown();\r
- return TRUE;\r
-\r
- case IDCANCEL:\r
- case OPT_CancelComment:\r
- CommentPopDown();\r
- return TRUE;\r
-\r
- case OPT_ClearComment:\r
- SetDlgItemText(hDlg, OPT_CommentText, "");\r
- break;\r
-\r
- case OPT_EditComment:\r
- EditCommentEvent();\r
- return TRUE;\r
-\r
- default:\r
- break;\r
- }\r
- break;\r
-\r
- case WM_NOTIFY: // [HGM] vari: cloned from whistory.c\r
- if( wParam == OPT_CommentText ) {\r
- MSGFILTER * lpMF = (MSGFILTER *) lParam;\r
-\r
- if( lpMF->msg == WM_RBUTTONDOWN && (lpMF->wParam & (MK_CONTROL | MK_SHIFT)) == 0 ||\r
- lpMF->msg == WM_CHAR && lpMF->wParam == '\022' ) {\r
- POINTL pt;\r
- LRESULT index;\r
-\r
- pt.x = LOWORD( lpMF->lParam );\r
- pt.y = HIWORD( lpMF->lParam );\r
-\r
- if(lpMF->msg == WM_CHAR) {\r
- CHARRANGE sel;\r
- SendDlgItemMessage( hDlg, OPT_CommentText, EM_EXGETSEL, 0, (LPARAM) &sel );\r
- index = sel.cpMin;\r
- } else\r
- index = SendDlgItemMessage( hDlg, OPT_CommentText, EM_CHARFROMPOS, 0, (LPARAM) &pt );\r
-\r
- hwndText = GetDlgItem(hDlg, OPT_CommentText); // cloned from above\r
- len = GetWindowTextLength(hwndText);\r
- str = (char *) malloc(len + 1);\r
- GetWindowText(hwndText, str, len + 1);\r
- ReplaceComment(commentIndex, str);\r
- if(commentIndex != currentMove) ToNrEvent(commentIndex);\r
- LoadVariation( index, str ); // [HGM] also does the actual moving to it, now\r
- free(str);\r
-\r
- /* Zap the message for good: apparently, returning non-zero is not enough */\r
- lpMF->msg = WM_USER;\r
-\r
- return TRUE;\r
- }\r
- }\r
- break;\r
-\r
- case WM_SIZE:\r
- newSizeX = LOWORD(lParam);\r
- newSizeY = HIWORD(lParam);\r
- ResizeEditPlusButtons(hDlg, hwndText, sizeX, sizeY, newSizeX, newSizeY);\r
- sizeX = newSizeX;\r
- sizeY = newSizeY;\r
- break;\r
-\r
- case WM_GETMINMAXINFO:\r
- /* Prevent resizing window too small */\r
- mmi = (MINMAXINFO *) lParam;\r
- mmi->ptMinTrackSize.x = 100;\r
- mmi->ptMinTrackSize.y = 100;\r
- break;\r
- }\r
- return FALSE;\r
-}\r
-\r
-VOID\r
-EitherCommentPopUp(int index, char *title, char *str, BOOLEAN edit)\r
-{\r
- FARPROC lpProc;\r
- char *p, *q;\r
-\r
- CheckMenuItem(GetMenu(hwndMain), IDM_Comment, edit ? MF_CHECKED : MF_UNCHECKED);\r
-\r
- if (str == NULL) str = "";\r
- p = (char *) malloc(2 * strlen(str) + 2);\r
- q = p;\r
- while (*str) {\r
- if (*str == '\n') *q++ = '\r';\r
- *q++ = *str++;\r
- }\r
- *q = NULLCHAR;\r
- if (commentText != NULL) free(commentText);\r
-\r
- commentIndex = index;\r
- commentTitle = title;\r
- commentText = p;\r
- editComment = edit;\r
-\r
- if (commentDialog) {\r
- SendMessage(commentDialog, WM_INITDIALOG, 0, 0);\r
- if (!commentUp) ShowWindow(commentDialog, SW_SHOW);\r
- } else {\r
- lpProc = MakeProcInstance((FARPROC)CommentDialog, hInst);\r
- CreateDialog(hInst, MAKEINTRESOURCE(DLG_EditComment),\r
- hwndMain, (DLGPROC)lpProc);\r
- FreeProcInstance(lpProc);\r
- }\r
- commentUp = TRUE;\r
-}\r
-\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Type-in move dialog functions\r
- * \r
-\*---------------------------------------------------------------------------*/\r
-\r
-LRESULT CALLBACK\r
-TypeInMoveDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- char move[MSG_SIZ];\r
- HWND hInput;\r
-\r
- switch (message) {\r
- case WM_INITDIALOG:\r
- move[0] = (char) lParam;\r
- move[1] = NULLCHAR;\r
- CenterWindowEx(hDlg, GetWindow(hDlg, GW_OWNER), 1 );\r
- Translate(hDlg, DLG_TypeInMove);\r
- hInput = GetDlgItem(hDlg, OPT_Move);\r
- SetWindowText(hInput, move);\r
- SetFocus(hInput);\r
- SendMessage(hInput, EM_SETSEL, (WPARAM)9999, (LPARAM)9999);\r
- return FALSE;\r
-\r
- case WM_COMMAND:\r
- switch (LOWORD(wParam)) {\r
- case IDOK:\r
-\r
- shiftKey = GetKeyState(VK_SHIFT) < 0; // [HGM] remember last shift status\r
- GetDlgItemText(hDlg, OPT_Move, move, sizeof(move));\r
- TypeInDoneEvent(move);\r
- EndDialog(hDlg, TRUE);\r
- return TRUE;\r
- case IDCANCEL:\r
- EndDialog(hDlg, FALSE);\r
- return TRUE;\r
- default:\r
- break;\r
- }\r
- break;\r
- }\r
- return FALSE;\r
-}\r
-\r
-VOID\r
-PopUpMoveDialog(char firstchar)\r
-{\r
- FARPROC lpProc;\r
-\r
- lpProc = MakeProcInstance((FARPROC)TypeInMoveDialog, hInst);\r
- DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_TypeInMove),\r
- hwndMain, (DLGPROC)lpProc, (LPARAM)firstchar);\r
- FreeProcInstance(lpProc);\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Type-in name dialog functions\r
- * \r
-\*---------------------------------------------------------------------------*/\r
-\r
-LRESULT CALLBACK\r
-TypeInNameDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- char move[MSG_SIZ];\r
- HWND hInput;\r
-\r
- switch (message) {\r
- case WM_INITDIALOG:\r
- move[0] = (char) lParam;\r
- move[1] = NULLCHAR;\r
- CenterWindowEx(hDlg, GetWindow(hDlg, GW_OWNER), 1 );\r
- Translate(hDlg, DLG_TypeInName);\r
- hInput = GetDlgItem(hDlg, OPT_Name);\r
- SetWindowText(hInput, move);\r
- SetFocus(hInput);\r
- SendMessage(hInput, EM_SETSEL, (WPARAM)9999, (LPARAM)9999);\r
- return FALSE;\r
-\r
- case WM_COMMAND:\r
- switch (LOWORD(wParam)) {\r
- case IDOK:\r
- GetDlgItemText(hDlg, OPT_Name, move, sizeof(move));\r
- appData.userName = strdup(move);\r
- SetUserLogo(); DisplayLogos();\r
- SetGameInfo();\r
- if(gameMode == MachinePlaysWhite || gameMode == MachinePlaysBlack) {\r
- snprintf(move, MSG_SIZ, "%s vs. %s", gameInfo.white, gameInfo.black);\r
- DisplayTitle(move);\r
- }\r
-\r
-\r
- EndDialog(hDlg, TRUE);\r
- return TRUE;\r
- case IDCANCEL:\r
- EndDialog(hDlg, FALSE);\r
- return TRUE;\r
- default:\r
- break;\r
- }\r
- break;\r
- }\r
- return FALSE;\r
-}\r
-\r
-VOID\r
-PopUpNameDialog(char firstchar)\r
-{\r
- FARPROC lpProc;\r
- \r
- lpProc = MakeProcInstance((FARPROC)TypeInNameDialog, hInst);\r
- DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_TypeInName),\r
- hwndMain, (DLGPROC)lpProc, (LPARAM)firstchar);\r
- FreeProcInstance(lpProc);\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Error dialogs\r
- * \r
-\*---------------------------------------------------------------------------*/\r
-\r
-/* Nonmodal error box */\r
-LRESULT CALLBACK ErrorDialog(HWND hDlg, UINT message,\r
- WPARAM wParam, LPARAM lParam);\r
-\r
-VOID\r
-ErrorPopUp(char *title, char *content)\r
-{\r
- FARPROC lpProc;\r
- char *p, *q;\r
- BOOLEAN modal = hwndMain == NULL;\r
-\r
- p = content;\r
- q = errorMessage;\r
- while (*p) {\r
- if (*p == '\n') {\r
- if (modal) {\r
- *q++ = ' ';\r
- p++;\r
- } else {\r
- *q++ = '\r';\r
- *q++ = *p++;\r
- }\r
- } else {\r
- *q++ = *p++;\r
- }\r
- }\r
- *q = NULLCHAR;\r
- strncpy(errorTitle, title, sizeof(errorTitle));\r
- errorTitle[sizeof(errorTitle) - 1] = '\0';\r
- \r
- if (modal) {\r
- MessageBox(NULL, errorMessage, errorTitle, MB_OK|MB_ICONEXCLAMATION);\r
- } else {\r
- lpProc = MakeProcInstance((FARPROC)ErrorDialog, hInst);\r
- CreateDialog(hInst, MAKEINTRESOURCE(DLG_Error),\r
- hwndMain, (DLGPROC)lpProc);\r
- FreeProcInstance(lpProc);\r
- }\r
-}\r
-\r
-VOID\r
-ErrorPopDown()\r
-{\r
- if (!appData.popupMoveErrors && moveErrorMessageUp) DisplayMessage("", "");\r
- if (errorDialog == NULL) return;\r
- DestroyWindow(errorDialog);\r
- errorDialog = NULL;\r
- if(errorExitStatus) ExitEvent(errorExitStatus);\r
-}\r
-\r
-LRESULT CALLBACK\r
-ErrorDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- RECT rChild;\r
-\r
- switch (message) {\r
- case WM_INITDIALOG:\r
- GetWindowRect(hDlg, &rChild);\r
-\r
- /*\r
- SetWindowPos(hDlg, NULL, rChild.left,\r
- rChild.top + boardRect.top - (rChild.bottom - rChild.top), \r
- 0, 0, SWP_NOZORDER|SWP_NOSIZE);\r
- */\r
-\r
- /* \r
- [AS] It seems that the above code wants to move the dialog up in the "caption\r
- area" of the main window, but it uses the dialog height as an hard-coded constant,\r
- and it doesn't work when you resize the dialog.\r
- For now, just give it a default position.\r
- */\r
- SetWindowPos(hDlg, NULL, boardRect.left+8, boardRect.top+8, 0, 0, SWP_NOZORDER|SWP_NOSIZE);\r
- Translate(hDlg, DLG_Error);\r
-\r
- errorDialog = hDlg;\r
- SetWindowText(hDlg, errorTitle);\r
- SetDlgItemText(hDlg, OPT_ErrorText, errorMessage);\r
- return FALSE;\r
-\r
- case WM_COMMAND:\r
- switch (LOWORD(wParam)) {\r
- case IDOK:\r
- case IDCANCEL:\r
- if (errorDialog == hDlg) errorDialog = NULL;\r
- DestroyWindow(hDlg);\r
- return TRUE;\r
-\r
- default:\r
- break;\r
- }\r
- break;\r
- }\r
- return FALSE;\r
-}\r
-\r
-#ifdef GOTHIC\r
-HWND gothicDialog = NULL;\r
-\r
-LRESULT CALLBACK\r
-GothicDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- RECT rChild;\r
- int height = GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYFRAME);\r
-\r
- switch (message) {\r
- case WM_INITDIALOG:\r
- GetWindowRect(hDlg, &rChild);\r
-\r
- SetWindowPos(hDlg, NULL, wpMain.x, wpMain.y-height, wpMain.width, height,\r
- SWP_NOZORDER);\r
-\r
- /* \r
- [AS] It seems that the above code wants to move the dialog up in the "caption\r
- area" of the main window, but it uses the dialog height as an hard-coded constant,\r
- and it doesn't work when you resize the dialog.\r
- For now, just give it a default position.\r
- */\r
- gothicDialog = hDlg;\r
- SetWindowText(hDlg, errorTitle);\r
- SetDlgItemText(hDlg, OPT_ErrorText, errorMessage);\r
- return FALSE;\r
-\r
- case WM_COMMAND:\r
- switch (LOWORD(wParam)) {\r
- case IDOK:\r
- case IDCANCEL:\r
- if (errorDialog == hDlg) errorDialog = NULL;\r
- DestroyWindow(hDlg);\r
- return TRUE;\r
-\r
- default:\r
- break;\r
- }\r
- break;\r
- }\r
- return FALSE;\r
-}\r
-\r
-VOID\r
-GothicPopUp(char *title, VariantClass variant)\r
-{\r
- FARPROC lpProc;\r
- static char *lastTitle;\r
-\r
- strncpy(errorTitle, title, sizeof(errorTitle));\r
- errorTitle[sizeof(errorTitle) - 1] = '\0';\r
-\r
- if(lastTitle != title && gothicDialog != NULL) {\r
- DestroyWindow(gothicDialog);\r
- gothicDialog = NULL;\r
- }\r
- if(variant != VariantNormal && gothicDialog == NULL) {\r
- title = lastTitle;\r
- lpProc = MakeProcInstance((FARPROC)GothicDialog, hInst);\r
- CreateDialog(hInst, MAKEINTRESOURCE(DLG_Error),\r
- hwndMain, (DLGPROC)lpProc);\r
- FreeProcInstance(lpProc);\r
- }\r
-}\r
-#endif\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Ics Interaction console functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-#define HISTORY_SIZE 64\r
-static char *history[HISTORY_SIZE];\r
-int histIn = 0, histP = 0;\r
-\r
-\r
-VOID\r
-SaveInHistory(char *cmd)\r
-{\r
- if (history[histIn] != NULL) {\r
- free(history[histIn]);\r
- history[histIn] = NULL;\r
- }\r
- if (*cmd == NULLCHAR) return;\r
- history[histIn] = StrSave(cmd);\r
- histIn = (histIn + 1) % HISTORY_SIZE;\r
- if (history[histIn] != NULL) {\r
- free(history[histIn]);\r
-\r
- history[histIn] = NULL;\r
- }\r
- histP = histIn;\r
-}\r
-\r
-char *\r
-PrevInHistory(char *cmd)\r
-{\r
- int newhp;\r
- if (histP == histIn) {\r
- if (history[histIn] != NULL) free(history[histIn]);\r
- history[histIn] = StrSave(cmd);\r
- }\r
- newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;\r
- if (newhp == histIn || history[newhp] == NULL) return NULL;\r
- histP = newhp;\r
- return history[histP];\r
-}\r
-\r
-char *\r
-NextInHistory()\r
-{\r
- if (histP == histIn) return NULL;\r
- histP = (histP + 1) % HISTORY_SIZE;\r
- return history[histP]; \r
-}\r
-\r
-HMENU\r
-LoadIcsTextMenu(IcsTextMenuEntry *e)\r
-{\r
- HMENU hmenu, h;\r
- int i = 0;\r
- hmenu = LoadMenu(hInst, "TextMenu");\r
- h = GetSubMenu(hmenu, 0);\r
- while (e->item) {\r
- if (strcmp(e->item, "-") == 0) {\r
- AppendMenu(h, MF_SEPARATOR, 0, 0);\r
- } else { // [HGM] re-written a bit to use only one AppendMenu call for both cases (| or no |)\r
- int flags = MF_STRING, j = 0;\r
- if (e->item[0] == '|') {\r
- flags |= MF_MENUBARBREAK;\r
- j++;\r
- }\r
- if(!strcmp(e->command, "none")) flags |= MF_GRAYED; // [HGM] chatclick: provide inactive dummy\r
- AppendMenu(h, flags, IDM_CommandX + i, e->item + j);\r
- }\r
- e++;\r
- i++;\r
- } \r
- return hmenu;\r
-}\r
-\r
-WNDPROC consoleTextWindowProc;\r
-\r
-void\r
-CommandX(HWND hwnd, char *command, BOOLEAN getname, BOOLEAN immediate)\r
-{\r
- char buf[MSG_SIZ], name[MSG_SIZ];\r
- HWND hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- CHARRANGE sel;\r
-\r
- if (!getname) {\r
- SetWindowText(hInput, command);\r
- if (immediate) {\r
- SendMessage(hInput, WM_CHAR, '\r', 0);\r
- } else {\r
- sel.cpMin = 999999;\r
- sel.cpMax = 999999;\r
- SendMessage(hInput, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- SetFocus(hInput);\r
- }\r
- return;\r
- } \r
- SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel);\r
- if (sel.cpMin == sel.cpMax) {\r
- /* Expand to surrounding word */\r
- TEXTRANGE tr;\r
- do {\r
- tr.chrg.cpMax = sel.cpMin;\r
- tr.chrg.cpMin = --sel.cpMin;\r
- if (sel.cpMin < 0) break;\r
- tr.lpstrText = name;\r
- SendMessage(hwnd, EM_GETTEXTRANGE, 0, (LPARAM) &tr);\r
- } while (isalpha(name[0]) || isdigit(name[0]) || name[0] == '-');\r
- sel.cpMin++;\r
-\r
- do {\r
- tr.chrg.cpMin = sel.cpMax;\r
- tr.chrg.cpMax = ++sel.cpMax;\r
- tr.lpstrText = name;\r
- if (SendMessage(hwnd, EM_GETTEXTRANGE, 0, (LPARAM) &tr) < 1) break;\r
- } while (isalpha(name[0]) || isdigit(name[0]) || name[0] == '-');\r
- sel.cpMax--;\r
-\r
- if (sel.cpMax == sel.cpMin || sel.cpMax - sel.cpMin > MSG_SIZ/2) {\r
- MessageBeep(MB_ICONEXCLAMATION);\r
- return;\r
- }\r
- tr.chrg = sel;\r
- tr.lpstrText = name;\r
- SendMessage(hwnd, EM_GETTEXTRANGE, 0, (LPARAM) &tr);\r
- } else {\r
- if (sel.cpMax - sel.cpMin > MSG_SIZ/2) {\r
- MessageBeep(MB_ICONEXCLAMATION);\r
- return;\r
- }\r
- SendMessage(hwnd, EM_GETSELTEXT, 0, (LPARAM) name);\r
- }\r
- if (immediate) {\r
- if(strstr(command, "%s")) snprintf(buf, MSG_SIZ, command, name); else\r
- snprintf(buf, MSG_SIZ, "%s %s", command, name);\r
- SetWindowText(hInput, buf);\r
- SendMessage(hInput, WM_CHAR, '\r', 0);\r
- } else {\r
- if(!strcmp(command, "chat")) { ChatPopUp(name); return; }\r
- snprintf(buf, MSG_SIZ, "%s %s ", command, name); /* trailing space */\r
- SetWindowText(hInput, buf);\r
- sel.cpMin = 999999;\r
- sel.cpMax = 999999;\r
- SendMessage(hInput, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- SetFocus(hInput);\r
- }\r
-}\r
-\r
-LRESULT CALLBACK \r
-ConsoleTextSubclass(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- HWND hInput;\r
- CHARRANGE sel;\r
-\r
- switch (message) {\r
- case WM_KEYDOWN:\r
- if (!(GetKeyState(VK_CONTROL) & ~1)) break;\r
- if(wParam=='R') return 0;\r
- switch (wParam) {\r
- case VK_PRIOR:\r
- SendMessage(hwnd, EM_LINESCROLL, 0, -999999);\r
- return 0;\r
- case VK_NEXT:\r
- sel.cpMin = 999999;\r
- sel.cpMax = 999999;\r
- SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- SendMessage(hwnd, EM_SCROLLCARET, 0, 0);\r
- return 0;\r
- }\r
- break;\r
- case WM_CHAR:\r
- if(wParam != '\022') {\r
- if (wParam == '\t') {\r
- if (GetKeyState(VK_SHIFT) < 0) {\r
- /* shifted */\r
- if (IsIconic(hwndMain)) ShowWindow(hwndMain, SW_RESTORE);\r
- if (buttonDesc[0].hwnd) {\r
- SetFocus(buttonDesc[0].hwnd);\r
- } else {\r
- SetFocus(hwndMain);\r
- }\r
- } else {\r
- /* unshifted */\r
- SetFocus(GetDlgItem(hwndConsole, OPT_ConsoleInput));\r
- }\r
- } else {\r
- hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- JAWS_DELETE( SetFocus(hInput); )\r
- SendMessage(hInput, message, wParam, lParam);\r
- }\r
- return 0;\r
- } // [HGM] navigate: for Ctrl+R, flow into next case (moved up here) to summon up menu\r
- lParam = -1;\r
- case WM_RBUTTONDOWN:\r
- if (!(GetKeyState(VK_SHIFT) & ~1)) {\r
- /* Move selection here if it was empty */\r
- POINT pt;\r
- pt.x = LOWORD(lParam);\r
- pt.y = HIWORD(lParam);\r
- SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel);\r
- if (sel.cpMin == sel.cpMax) {\r
- if(lParam != -1) sel.cpMin = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&pt); /*doc is wrong*/\r
- sel.cpMax = sel.cpMin;\r
- SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- }\r
- SendMessage(hwnd, EM_HIDESELECTION, FALSE, FALSE);\r
-{ // [HGM] chatclick: code moved here from WM_RBUTTONUP case, to have menu appear on down-click\r
- POINT pt;\r
- HMENU hmenu = LoadIcsTextMenu(icsTextMenuEntry);\r
- SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel);\r
- if (sel.cpMin == sel.cpMax) {\r
- EnableMenuItem(hmenu, IDM_Copy, MF_BYCOMMAND|MF_GRAYED);\r
- EnableMenuItem(hmenu, IDM_QuickPaste, MF_BYCOMMAND|MF_GRAYED);\r
- }\r
- if (!IsClipboardFormatAvailable(CF_TEXT)) {\r
- EnableMenuItem(hmenu, IDM_Paste, MF_BYCOMMAND|MF_GRAYED);\r
- }\r
- pt.x = LOWORD(lParam)-30; // [HGM] chatclick: make menu pop up with pointer above upper-right item\r
- pt.y = HIWORD(lParam)-10; // make it appear as if mouse moved there, so it will be selected on up-click\r
- PostMessage(hwnd, WM_MOUSEMOVE, wParam, lParam+5);\r
- MenuPopup(hwnd, pt, hmenu, -1);\r
-}\r
- }\r
- return 0;\r
- case WM_RBUTTONUP:\r
- if (GetKeyState(VK_SHIFT) & ~1) {\r
- SendDlgItemMessage(hwndConsole, OPT_ConsoleText, \r
- WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0);\r
- }\r
- return 0;\r
- case WM_PASTE:\r
- hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- SetFocus(hInput);\r
- return SendMessage(hInput, message, wParam, lParam);\r
- case WM_MBUTTONDOWN:\r
- return SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0);\r
- case WM_COMMAND:\r
- switch (LOWORD(wParam)) {\r
- case IDM_QuickPaste:\r
- {\r
- SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel);\r
- if (sel.cpMin == sel.cpMax) {\r
- MessageBeep(MB_ICONEXCLAMATION);\r
- return 0;\r
- }\r
- SendMessage(hwnd, WM_COPY, 0, 0);\r
- hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- SendMessage(hInput, WM_PASTE, 0, 0);\r
- SetFocus(hInput);\r
- return 0;\r
- }\r
- case IDM_Cut:\r
- SendMessage(hwnd, WM_CUT, 0, 0);\r
- return 0;\r
- case IDM_Paste:\r
- SendMessage(hwnd, WM_PASTE, 0, 0);\r
- return 0;\r
- case IDM_Copy:\r
- SendMessage(hwnd, WM_COPY, 0, 0);\r
- return 0;\r
- default:\r
- {\r
- int i = LOWORD(wParam) - IDM_CommandX;\r
- if (i >= 0 && i < ICS_TEXT_MENU_SIZE &&\r
- icsTextMenuEntry[i].command != NULL) {\r
- CommandX(hwnd, icsTextMenuEntry[i].command,\r
- icsTextMenuEntry[i].getname,\r
- icsTextMenuEntry[i].immediate);\r
- return 0;\r
- }\r
- }\r
- break;\r
- }\r
- break;\r
- }\r
- return (*consoleTextWindowProc)(hwnd, message, wParam, lParam);\r
-}\r
-\r
-WNDPROC consoleInputWindowProc;\r
-\r
-LRESULT CALLBACK\r
-ConsoleInputSubclass(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- char buf[MSG_SIZ];\r
- char *p;\r
- static BOOL sendNextChar = FALSE;\r
- static BOOL quoteNextChar = FALSE;\r
- InputSource *is = consoleInputSource;\r
- CHARFORMAT cf;\r
- CHARRANGE sel;\r
-\r
- switch (message) {\r
- case WM_CHAR:\r
- if (!appData.localLineEditing || sendNextChar) {\r
- is->buf[0] = (CHAR) wParam;\r
- is->count = 1;\r
- SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is);\r
- sendNextChar = FALSE;\r
- return 0;\r
- }\r
- if (quoteNextChar) {\r
- buf[0] = (char) wParam;\r
- buf[1] = NULLCHAR;\r
- SendMessage(hwnd, EM_REPLACESEL, TRUE, (LPARAM) buf);\r
- quoteNextChar = FALSE;\r
- return 0;\r
- }\r
- switch (wParam) {\r
- case '\r': /* Enter key */\r
- is->count = GetWindowText(hwnd, is->buf, INPUT_SOURCE_BUF_SIZE-1); \r
- if (consoleEcho) SaveInHistory(is->buf);\r
- is->buf[is->count++] = '\n';\r
- is->buf[is->count] = NULLCHAR;\r
- SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is);\r
- if (consoleEcho) {\r
- ConsoleOutput(is->buf, is->count, TRUE);\r
- } else if (appData.localLineEditing) {\r
- ConsoleOutput("\n", 1, TRUE);\r
- }\r
- /* fall thru */\r
- case '\033': /* Escape key */\r
- SetWindowText(hwnd, "");\r
- cf.cbSize = sizeof(CHARFORMAT);\r
- cf.dwMask = CFM_COLOR|CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_STRIKEOUT;\r
- if (consoleEcho) {\r
- cf.crTextColor = textAttribs[ColorNormal].color;\r
- } else {\r
- cf.crTextColor = COLOR_ECHOOFF;\r
- }\r
- cf.dwEffects = textAttribs[ColorNormal].effects;\r
- SendMessage(hwnd, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);\r
- return 0;\r
- case '\t': /* Tab key */\r
- if (GetKeyState(VK_SHIFT) < 0) {\r
- /* shifted */\r
- SetFocus(GetDlgItem(hwndConsole, OPT_ConsoleText));\r
- } else {\r
- /* unshifted */\r
- if (IsIconic(hwndMain)) ShowWindow(hwndMain, SW_RESTORE);\r
- if (buttonDesc[0].hwnd) {\r
- SetFocus(buttonDesc[0].hwnd);\r
- } else {\r
- SetFocus(hwndMain);\r
- }\r
- }\r
- return 0;\r
- case '\023': /* Ctrl+S */\r
- sendNextChar = TRUE;\r
- return 0;\r
- case '\021': /* Ctrl+Q */\r
- quoteNextChar = TRUE;\r
- return 0;\r
- JAWS_REPLAY\r
- default:\r
- break;\r
- }\r
- break;\r
- case WM_KEYDOWN:\r
- switch (wParam) {\r
- case VK_UP:\r
- GetWindowText(hwnd, buf, MSG_SIZ);\r
- p = PrevInHistory(buf);\r
- if (p != NULL) {\r
- SetWindowText(hwnd, p);\r
- sel.cpMin = 999999;\r
- sel.cpMax = 999999;\r
- SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- return 0;\r
- }\r
- break;\r
- case VK_DOWN:\r
- p = NextInHistory();\r
- if (p != NULL) {\r
- SetWindowText(hwnd, p);\r
- sel.cpMin = 999999;\r
- sel.cpMax = 999999;\r
- SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- return 0;\r
- }\r
- break;\r
- case VK_HOME:\r
- case VK_END:\r
- if (!(GetKeyState(VK_CONTROL) & ~1)) break;\r
- /* fall thru */\r
- case VK_PRIOR:\r
- case VK_NEXT:\r
- SendDlgItemMessage(hwndConsole, OPT_ConsoleText, message, wParam, lParam);\r
- return 0;\r
- }\r
- break;\r
- case WM_MBUTTONDOWN:\r
- SendDlgItemMessage(hwndConsole, OPT_ConsoleText, \r
- WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0);\r
- break;\r
- case WM_RBUTTONUP:\r
- if (GetKeyState(VK_SHIFT) & ~1) {\r
- SendDlgItemMessage(hwndConsole, OPT_ConsoleText, \r
- WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0);\r
- } else {\r
- POINT pt;\r
- HMENU hmenu;\r
- hmenu = LoadMenu(hInst, "InputMenu");\r
- SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel);\r
- if (sel.cpMin == sel.cpMax) {\r
- EnableMenuItem(hmenu, IDM_Copy, MF_BYCOMMAND|MF_GRAYED);\r
- EnableMenuItem(hmenu, IDM_Cut, MF_BYCOMMAND|MF_GRAYED);\r
- }\r
- if (!IsClipboardFormatAvailable(CF_TEXT)) {\r
- EnableMenuItem(hmenu, IDM_Paste, MF_BYCOMMAND|MF_GRAYED);\r
- }\r
- pt.x = LOWORD(lParam);\r
- pt.y = HIWORD(lParam);\r
- MenuPopup(hwnd, pt, hmenu, -1);\r
- }\r
- return 0;\r
- case WM_COMMAND:\r
- switch (LOWORD(wParam)) { \r
- case IDM_Undo:\r
- SendMessage(hwnd, EM_UNDO, 0, 0);\r
- return 0;\r
- case IDM_SelectAll:\r
- sel.cpMin = 0;\r
- sel.cpMax = -1; /*999999?*/\r
- SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- return 0;\r
- case IDM_Cut:\r
- SendMessage(hwnd, WM_CUT, 0, 0);\r
- return 0;\r
- case IDM_Paste:\r
- SendMessage(hwnd, WM_PASTE, 0, 0);\r
- return 0;\r
- case IDM_Copy:\r
- SendMessage(hwnd, WM_COPY, 0, 0);\r
- return 0;\r
- }\r
- break;\r
- }\r
- return (*consoleInputWindowProc)(hwnd, message, wParam, lParam);\r
-}\r
-\r
-#define CO_MAX 100000\r
-#define CO_TRIM 1000\r
-\r
-LRESULT CALLBACK\r
-ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- static SnapData sd;\r
- HWND hText, hInput;\r
- RECT rect;\r
- static int sizeX, sizeY;\r
- int newSizeX, newSizeY;\r
- MINMAXINFO *mmi;\r
- WORD wMask;\r
-\r
- hText = GetDlgItem(hDlg, OPT_ConsoleText);\r
- hInput = GetDlgItem(hDlg, OPT_ConsoleInput);\r
-\r
- switch (message) {\r
- case WM_NOTIFY:\r
- if (((NMHDR*)lParam)->code == EN_LINK)\r
- {\r
- ENLINK *pLink = (ENLINK*)lParam;\r
- if (pLink->msg == WM_LBUTTONUP)\r
- {\r
- TEXTRANGE tr;\r
-\r
- tr.chrg = pLink->chrg;\r
- tr.lpstrText = malloc(1+tr.chrg.cpMax-tr.chrg.cpMin);\r
- SendMessage(hText, EM_GETTEXTRANGE, 0, (LPARAM)&tr);\r
- ShellExecute(NULL, "open", tr.lpstrText, NULL, NULL, SW_SHOW);\r
- free(tr.lpstrText);\r
- }\r
- }\r
- break;\r
- case WM_INITDIALOG: /* message: initialize dialog box */\r
- hwndConsole = hDlg;\r
- SetFocus(hInput);\r
- consoleTextWindowProc = (WNDPROC)\r
- SetWindowLongPtr(hText, GWLP_WNDPROC, (LONG_PTR) ConsoleTextSubclass);\r
- SendMessage(hText, EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor);\r
- consoleInputWindowProc = (WNDPROC)\r
- SetWindowLongPtr(hInput, GWLP_WNDPROC, (LONG_PTR) ConsoleInputSubclass);\r
- SendMessage(hInput, EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor);\r
- Colorize(ColorNormal, TRUE);\r
- SendMessage(hInput, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &consoleCF);\r
- ChangedConsoleFont();\r
- GetClientRect(hDlg, &rect);\r
- sizeX = rect.right;\r
- sizeY = rect.bottom;\r
- if (wpConsole.x != CW_USEDEFAULT && wpConsole.y != CW_USEDEFAULT &&\r
- wpConsole.width != CW_USEDEFAULT && wpConsole.height != CW_USEDEFAULT) {\r
- WINDOWPLACEMENT wp;\r
- EnsureOnScreen(&wpConsole.x, &wpConsole.y, 0, 0);\r
- wp.length = sizeof(WINDOWPLACEMENT);\r
- wp.flags = 0;\r
- wp.showCmd = SW_SHOW;\r
- wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;\r
- wp.rcNormalPosition.left = wpConsole.x;\r
- wp.rcNormalPosition.right = wpConsole.x + wpConsole.width;\r
- wp.rcNormalPosition.top = wpConsole.y;\r
- wp.rcNormalPosition.bottom = wpConsole.y + wpConsole.height;\r
- SetWindowPlacement(hDlg, &wp);\r
- }\r
-\r
- // [HGM] Chessknight's change 2004-07-13\r
- else { /* Determine Defaults */\r
- WINDOWPLACEMENT wp;\r
- wpConsole.x = wpMain.width + 1;\r
- wpConsole.y = wpMain.y;\r
- wpConsole.width = screenWidth - wpMain.width;\r
- wpConsole.height = wpMain.height;\r
- EnsureOnScreen(&wpConsole.x, &wpConsole.y, 0, 0);\r
- wp.length = sizeof(WINDOWPLACEMENT);\r
- wp.flags = 0;\r
- wp.showCmd = SW_SHOW;\r
- wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;\r
- wp.rcNormalPosition.left = wpConsole.x;\r
- wp.rcNormalPosition.right = wpConsole.x + wpConsole.width;\r
- wp.rcNormalPosition.top = wpConsole.y;\r
- wp.rcNormalPosition.bottom = wpConsole.y + wpConsole.height;\r
- SetWindowPlacement(hDlg, &wp);\r
- }\r
-\r
- // Allow hText to highlight URLs and send notifications on them\r
- wMask = (WORD) SendMessage(hText, EM_GETEVENTMASK, 0, 0L);\r
- SendMessage(hText, EM_SETEVENTMASK, 0, wMask | ENM_LINK);\r
- SendMessage(hText, EM_AUTOURLDETECT, TRUE, 0L);\r
- SetWindowLongPtr(hText, GWLP_USERDATA, 79); // initialize the text window's width\r
-\r
- return FALSE;\r
-\r
- case WM_SETFOCUS:\r
- SetFocus(hInput);\r
- return 0;\r
-\r
- case WM_CLOSE:\r
- ExitEvent(0);\r
- /* not reached */\r
- break;\r
-\r
- case WM_SIZE:\r
- if (IsIconic(hDlg)) break;\r
- newSizeX = LOWORD(lParam);\r
- newSizeY = HIWORD(lParam);\r
- if (sizeX != newSizeX || sizeY != newSizeY) {\r
- RECT rectText, rectInput;\r
- POINT pt;\r
- int newTextHeight, newTextWidth;\r
- GetWindowRect(hText, &rectText);\r
- newTextWidth = rectText.right - rectText.left + newSizeX - sizeX;\r
- newTextHeight = rectText.bottom - rectText.top + newSizeY - sizeY;\r
- if (newTextHeight < 0) {\r
- newSizeY += -newTextHeight;\r
- newTextHeight = 0;\r
- }\r
- SetWindowPos(hText, NULL, 0, 0,\r
- newTextWidth, newTextHeight, SWP_NOZORDER|SWP_NOMOVE);\r
- GetWindowRect(hInput, &rectInput); /* gives screen coords */\r
- pt.x = rectInput.left;\r
- pt.y = rectInput.top + newSizeY - sizeY;\r
- ScreenToClient(hDlg, &pt);\r
- SetWindowPos(hInput, NULL, \r
- pt.x, pt.y, /* needs client coords */ \r
- rectInput.right - rectInput.left + newSizeX - sizeX,\r
- rectInput.bottom - rectInput.top, SWP_NOZORDER);\r
- }\r
- sizeX = newSizeX;\r
- sizeY = newSizeY;\r
- break;\r
-\r
- case WM_GETMINMAXINFO:\r
- /* Prevent resizing window too small */\r
- mmi = (MINMAXINFO *) lParam;\r
- mmi->ptMinTrackSize.x = 100;\r
- mmi->ptMinTrackSize.y = 100;\r
- break;\r
-\r
- /* [AS] Snapping */\r
- case WM_ENTERSIZEMOVE:\r
- return OnEnterSizeMove( &sd, hDlg, wParam, lParam );\r
-\r
- case WM_SIZING:\r
- return OnSizing( &sd, hDlg, wParam, lParam );\r
-\r
- case WM_MOVING:\r
- return OnMoving( &sd, hDlg, wParam, lParam );\r
-\r
- case WM_EXITSIZEMOVE:\r
- UpdateICSWidth(hText);\r
- return OnExitSizeMove( &sd, hDlg, wParam, lParam );\r
- }\r
-\r
- return DefWindowProc(hDlg, message, wParam, lParam);\r
-}\r
-\r
-\r
-VOID\r
-ConsoleCreate()\r
-{\r
- HWND hCons;\r
- if (hwndConsole) return;\r
- hCons = CreateDialog(hInst, szConsoleName, 0, NULL);\r
- SendMessage(hCons, WM_INITDIALOG, 0, 0);\r
-}\r
-\r
-\r
-VOID\r
-ConsoleOutput(char* data, int length, int forceVisible)\r
-{\r
- HWND hText;\r
- int trim, exlen;\r
- char *p, *q;\r
- char buf[CO_MAX+1];\r
- POINT pEnd;\r
- RECT rect;\r
- static int delayLF = 0;\r
- CHARRANGE savesel, sel;\r
-\r
- if (hwndConsole == NULL || length > CO_MAX-100 || length == 0) return;\r
- p = data;\r
- q = buf;\r
- if (delayLF) {\r
- *q++ = '\r';\r
- *q++ = '\n';\r
- delayLF = 0;\r
- }\r
- while (length--) {\r
- if (*p == '\n') {\r
- if (*++p) {\r
- *q++ = '\r';\r
- *q++ = '\n';\r
- } else {\r
- delayLF = 1;\r
- }\r
- } else if (*p == '\007') {\r
- MyPlaySound(&sounds[(int)SoundBell]);\r
- p++;\r
- } else {\r
- *q++ = *p++;\r
- }\r
- }\r
- *q = NULLCHAR;\r
- hText = GetDlgItem(hwndConsole, OPT_ConsoleText);\r
- SendMessage(hText, EM_HIDESELECTION, TRUE, FALSE);\r
- /* Save current selection */\r
- SendMessage(hText, EM_EXGETSEL, 0, (LPARAM)&savesel);\r
- exlen = GetWindowTextLength(hText);\r
- /* Find out whether current end of text is visible */\r
- SendMessage(hText, EM_GETRECT, 0, (LPARAM) &rect);\r
- SendMessage(hText, EM_POSFROMCHAR, (WPARAM) &pEnd, exlen);\r
- /* Trim existing text if it's too long */\r
- if (exlen + (q - buf) > CO_MAX) {\r
- trim = (CO_TRIM > (q - buf)) ? CO_TRIM : (q - buf);\r
- sel.cpMin = 0;\r
- sel.cpMax = trim;\r
- SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- SendMessage(hText, EM_REPLACESEL, 0, (LPARAM)"");\r
- exlen -= trim;\r
- savesel.cpMin -= trim;\r
- savesel.cpMax -= trim;\r
- if (exlen < 0) exlen = 0;\r
- if (savesel.cpMin < 0) savesel.cpMin = 0;\r
- if (savesel.cpMax < savesel.cpMin) savesel.cpMax = savesel.cpMin;\r
- }\r
- /* Append the new text */\r
- sel.cpMin = exlen;\r
- sel.cpMax = exlen;\r
- SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- SendMessage(hText, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&consoleCF);\r
- SendMessage(hText, EM_REPLACESEL, 0, (LPARAM) buf);\r
- if (forceVisible || exlen == 0 ||\r
- (rect.left <= pEnd.x && pEnd.x < rect.right &&\r
- rect.top <= pEnd.y && pEnd.y < rect.bottom)) {\r
- /* Scroll to make new end of text visible if old end of text\r
- was visible or new text is an echo of user typein */\r
- sel.cpMin = 9999999;\r
- sel.cpMax = 9999999;\r
- SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- SendMessage(hText, EM_HIDESELECTION, FALSE, FALSE);\r
- SendMessage(hText, EM_SCROLLCARET, 0, 0);\r
- SendMessage(hText, EM_HIDESELECTION, TRUE, FALSE);\r
- }\r
- if (savesel.cpMax == exlen || forceVisible) {\r
- /* Move insert point to new end of text if it was at the old\r
- end of text or if the new text is an echo of user typein */\r
- sel.cpMin = 9999999;\r
- sel.cpMax = 9999999;\r
- SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- } else {\r
- /* Restore previous selection */\r
- SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&savesel);\r
- }\r
- SendMessage(hText, EM_HIDESELECTION, FALSE, FALSE);\r
-}\r
-\r
-/*---------*/\r
-\r
-\r
-void\r
-DisplayHoldingsCount(HDC hdc, int x, int y, int rightAlign, int copyNumber)\r
-{\r
- char buf[100];\r
- char *str;\r
- COLORREF oldFg, oldBg;\r
- HFONT oldFont;\r
- RECT rect;\r
-\r
- if(copyNumber > 1)\r
- snprintf(buf, sizeof(buf)/sizeof(buf[0]),"%d", copyNumber); else buf[0] = 0;\r
-\r
- oldFg = SetTextColor(hdc, RGB(255, 255, 255)); /* white */\r
- oldBg = SetBkColor(hdc, RGB(0, 0, 0)); /* black */\r
- oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);\r
-\r
- rect.left = x;\r
- rect.right = x + squareSize;\r
- rect.top = y;\r
- rect.bottom = y + squareSize;\r
- str = buf;\r
-\r
- ExtTextOut(hdc, x + MESSAGE_LINE_LEFTMARGIN\r
- + (rightAlign ? (squareSize*2)/3 : 0),\r
- y, ETO_CLIPPED|ETO_OPAQUE,\r
- &rect, str, strlen(str), NULL);\r
-\r
- (void) SetTextColor(hdc, oldFg);\r
- (void) SetBkColor(hdc, oldBg);\r
- (void) SelectObject(hdc, oldFont);\r
-}\r
-\r
-void\r
-DisplayAClock(HDC hdc, int timeRemaining, int highlight,\r
- RECT *rect, char *color, char *flagFell)\r
-{\r
- char buf[100];\r
- char *str;\r
- COLORREF oldFg, oldBg;\r
- HFONT oldFont;\r
-\r
- if (twoBoards && partnerUp) return;\r
- if (appData.clockMode) {\r
- if (tinyLayout == 2)\r
- snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%c %s %s", color[0], TimeString(timeRemaining), flagFell);\r
- else\r
- snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s:%c%s %s", color, (logoHeight>0 ? 0 : ' '), TimeString(timeRemaining), flagFell);\r
- str = buf;\r
- } else {\r
- str = color;\r
- }\r
-\r
- if (highlight) {\r
- oldFg = SetTextColor(hdc, RGB(255, 255, 255)); /* white */\r
- oldBg = SetBkColor(hdc, RGB(0, 0, 0)); /* black */\r
- } else {\r
- oldFg = SetTextColor(hdc, RGB(0, 0, 0)); /* black */\r
- oldBg = SetBkColor(hdc, RGB(255, 255, 255)); /* white */\r
- }\r
-\r
- oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);\r
-\r
- JAWS_SILENCE\r
-\r
- ExtTextOut(hdc, rect->left + MESSAGE_LINE_LEFTMARGIN,\r
- rect->top, ETO_CLIPPED|ETO_OPAQUE,\r
- rect, str, strlen(str), NULL);\r
- if(logoHeight > 0 && appData.clockMode) {\r
- RECT r;\r
- str += strlen(color)+2;\r
- r.top = rect->top + logoHeight/2;\r
- r.left = rect->left;\r
- r.right = rect->right;\r
- r.bottom = rect->bottom;\r
- ExtTextOut(hdc, rect->left + MESSAGE_LINE_LEFTMARGIN,\r
- r.top, ETO_CLIPPED|ETO_OPAQUE,\r
- &r, str, strlen(str), NULL);\r
- }\r
- (void) SetTextColor(hdc, oldFg);\r
- (void) SetBkColor(hdc, oldBg);\r
- (void) SelectObject(hdc, oldFont);\r
-}\r
-\r
-\r
-int\r
-DoReadFile(HANDLE hFile, char *buf, int count, DWORD *outCount,\r
- OVERLAPPED *ovl)\r
-{\r
- int ok, err;\r
-\r
- /* [AS] */\r
- if( count <= 0 ) {\r
- if (appData.debugMode) {\r
- fprintf( debugFP, "DoReadFile: trying to read past end of buffer, overflow = %d\n", count );\r
- }\r
-\r
- return ERROR_INVALID_USER_BUFFER;\r
- }\r
-\r
- ResetEvent(ovl->hEvent);\r
- ovl->Offset = ovl->OffsetHigh = 0;\r
- ok = ReadFile(hFile, buf, count, outCount, ovl);\r
- if (ok) {\r
- err = NO_ERROR;\r
- } else {\r
- err = GetLastError();\r
- if (err == ERROR_IO_PENDING) {\r
- ok = GetOverlappedResult(hFile, ovl, outCount, TRUE);\r
- if (ok)\r
- err = NO_ERROR;\r
- else\r
- err = GetLastError();\r
- }\r
- }\r
- return err;\r
-}\r
-\r
-int\r
-DoWriteFile(HANDLE hFile, char *buf, int count, DWORD *outCount,\r
- OVERLAPPED *ovl)\r
-{\r
- int ok, err;\r
-\r
- ResetEvent(ovl->hEvent);\r
- ovl->Offset = ovl->OffsetHigh = 0;\r
- ok = WriteFile(hFile, buf, count, outCount, ovl);\r
- if (ok) {\r
- err = NO_ERROR;\r
- } else {\r
- err = GetLastError();\r
- if (err == ERROR_IO_PENDING) {\r
- ok = GetOverlappedResult(hFile, ovl, outCount, TRUE);\r
- if (ok)\r
- err = NO_ERROR;\r
- else\r
- err = GetLastError();\r
- }\r
-\r
- }\r
- return err;\r
-}\r
-\r
-/* [AS] If input is line by line and a line exceed the buffer size, force an error */\r
-void CheckForInputBufferFull( InputSource * is )\r
-{\r
- if( is->lineByLine && (is->next - is->buf) >= INPUT_SOURCE_BUF_SIZE ) {\r
- /* Look for end of line */\r
- char * p = is->buf;\r
- \r
- while( p < is->next && *p != '\n' ) {\r
- p++;\r
- }\r
-\r
- if( p >= is->next ) {\r
- if (appData.debugMode) {\r
- fprintf( debugFP, "Input line exceeded buffer size (source id=%lu)\n", is->id );\r
- }\r
-\r
- is->error = ERROR_BROKEN_PIPE; /* [AS] Just any non-successful code! */\r
- is->count = (DWORD) -1;\r
- is->next = is->buf;\r
- }\r
- }\r
-}\r
-\r
-DWORD\r
-InputThread(LPVOID arg)\r
-{\r
- InputSource *is;\r
- OVERLAPPED ovl;\r
-\r
- is = (InputSource *) arg;\r
- ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);\r
- ovl.Internal = ovl.InternalHigh = ovl.Offset = ovl.OffsetHigh = 0;\r
- while (is->hThread != NULL) {\r
- is->error = DoReadFile(is->hFile, is->next,\r
- INPUT_SOURCE_BUF_SIZE - (is->next - is->buf),\r
- &is->count, &ovl);\r
- if (is->error == NO_ERROR) {\r
- is->next += is->count;\r
- } else {\r
- if (is->error == ERROR_BROKEN_PIPE) {\r
- /* Correct for MS brain damage. EOF reading a pipe is not an error. */\r
- is->count = 0;\r
- } else {\r
- is->count = (DWORD) -1;\r
- /* [AS] The (is->count <= 0) check below is not useful for unsigned values! */\r
- break; \r
- }\r
- }\r
-\r
- CheckForInputBufferFull( is );\r
-\r
- SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is);\r
-\r
- if( is->count == ((DWORD) -1) ) break; /* [AS] */\r
-\r
- if (is->count <= 0) break; /* Quit on EOF or error */\r
- }\r
-\r
- CloseHandle(ovl.hEvent);\r
- CloseHandle(is->hFile);\r
-\r
- if (appData.debugMode) {\r
- fprintf( debugFP, "Input thread terminated (id=%lu, error=%d, count=%ld)\n", is->id, is->error, is->count );\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-\r
-/* Windows 95 beta 2 won't let you do overlapped i/o on a console or pipe */\r
-DWORD\r
-NonOvlInputThread(LPVOID arg)\r
-{\r
- InputSource *is;\r
- char *p, *q;\r
- int i;\r
- char prev;\r
-\r
- is = (InputSource *) arg;\r
- while (is->hThread != NULL) {\r
- is->error = ReadFile(is->hFile, is->next,\r
- INPUT_SOURCE_BUF_SIZE - (is->next - is->buf),\r
- &is->count, NULL) ? NO_ERROR : GetLastError();\r
- if (is->error == NO_ERROR) {\r
- /* Change CRLF to LF */\r
- if (is->next > is->buf) {\r
- p = is->next - 1;\r
- i = is->count + 1;\r
- } else {\r
- p = is->next;\r
- i = is->count;\r
- }\r
- q = p;\r
- prev = NULLCHAR;\r
- while (i > 0) {\r
- if (prev == '\r' && *p == '\n') {\r
- *(q-1) = '\n';\r
- is->count--;\r
- } else { \r
- *q++ = *p;\r
- }\r
- prev = *p++;\r
- i--;\r
- }\r
- *q = NULLCHAR;\r
- is->next = q;\r
- } else {\r
- if (is->error == ERROR_BROKEN_PIPE) {\r
- /* Correct for MS brain damage. EOF reading a pipe is not an error. */\r
- is->count = 0; \r
- } else {\r
- is->count = (DWORD) -1;\r
- }\r
- }\r
-\r
- CheckForInputBufferFull( is );\r
-\r
- SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is);\r
-\r
- if( is->count == ((DWORD) -1) ) break; /* [AS] */\r
-\r
- if (is->count < 0) break; /* Quit on error */\r
- }\r
- CloseHandle(is->hFile);\r
- return 0;\r
-}\r
-\r
-DWORD\r
-SocketInputThread(LPVOID arg)\r
-{\r
- InputSource *is;\r
-\r
- is = (InputSource *) arg;\r
- while (is->hThread != NULL) {\r
- is->count = recv(is->sock, is->buf, INPUT_SOURCE_BUF_SIZE, 0);\r
- if ((int)is->count == SOCKET_ERROR) {\r
- is->count = (DWORD) -1;\r
- is->error = WSAGetLastError();\r
- } else {\r
- is->error = NO_ERROR;\r
- is->next += is->count;\r
- if (is->count == 0 && is->second == is) {\r
- /* End of file on stderr; quit with no message */\r
- break;\r
- }\r
- }\r
- SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is);\r
-\r
- if( is->count == ((DWORD) -1) ) break; /* [AS] */\r
-\r
- if (is->count <= 0) break; /* Quit on EOF or error */\r
- }\r
- return 0;\r
-}\r
-\r
-VOID\r
-InputEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- InputSource *is;\r
-\r
- is = (InputSource *) lParam;\r
- if (is->lineByLine) {\r
- /* Feed in lines one by one */\r
- char *p = is->buf;\r
- char *q = p;\r
- while (q < is->next) {\r
- if (*q++ == '\n') {\r
- (is->func)(is, is->closure, p, q - p, NO_ERROR);\r
- p = q;\r
- }\r
- }\r
- \r
- /* Move any partial line to the start of the buffer */\r
- q = is->buf;\r
- while (p < is->next) {\r
- *q++ = *p++;\r
- }\r
- is->next = q;\r
-\r
- if (is->error != NO_ERROR || is->count == 0) {\r
- /* Notify backend of the error. Note: If there was a partial\r
- line at the end, it is not flushed through. */\r
- (is->func)(is, is->closure, is->buf, is->count, is->error); \r
- }\r
- } else {\r
- /* Feed in the whole chunk of input at once */\r
- (is->func)(is, is->closure, is->buf, is->count, is->error);\r
- is->next = is->buf;\r
- }\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Menu enables. Used when setting various modes.\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-typedef struct {\r
- int item;\r
- int flags;\r
-} Enables;\r
-\r
-VOID\r
-GreyRevert(Boolean grey)\r
-{ // [HGM] vari: for retracting variations in local mode\r
- HMENU hmenu = GetMenu(hwndMain);\r
- EnableMenuItem(hmenu, IDM_Revert, MF_BYCOMMAND|(grey ? MF_GRAYED : MF_ENABLED));\r
- EnableMenuItem(hmenu, IDM_Annotate, MF_BYCOMMAND|(grey ? MF_GRAYED : MF_ENABLED));\r
-}\r
-\r
-VOID\r
-SetMenuEnables(HMENU hmenu, Enables *enab)\r
-{\r
- while (enab->item > 0) {\r
- (void) EnableMenuItem(hmenu, enab->item, enab->flags);\r
- enab++;\r
- }\r
-}\r
-\r
-Enables gnuEnables[] = {\r
- { IDM_MailMove, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_ReloadCMailMsg, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_IcsClient, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Accept, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Decline, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Rematch, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Adjourn, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_StopExamining, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_StopObserving, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Upload, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Revert, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Annotate, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_NewChat, MF_BYCOMMAND|MF_GRAYED },\r
-\r
-\r
- // Needed to switch from ncp to GNU mode on Engine Load\r
- { ACTION_POS, MF_BYPOSITION|MF_ENABLED },\r
- { IDM_MachineWhite, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_MachineBlack, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_TwoMachines, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Match, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_AnalysisMode, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_AnalyzeFile, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Engine1Options, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Engine2Options, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_TimeControl, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_RetractMove, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_MoveNow, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Hint, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Book, MF_BYCOMMAND|MF_ENABLED },\r
- { -1, -1 }\r
-};\r
-\r
-Enables icsEnables[] = {\r
- { IDM_MailMove, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_ReloadCMailMsg, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MachineWhite, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MachineBlack, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_TwoMachines, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Match, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MachineBoth, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_AnalysisMode, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_AnalyzeFile, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_TimeControl, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MoveNow, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Hint, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Book, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_LoadProg1, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_LoadProg2, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_IcsOptions, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Engine1Options, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Engine2Options, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Annotate, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Tourney, MF_BYCOMMAND|MF_GRAYED },\r
- { -1, -1 }\r
-};\r
-\r
-#if ZIPPY\r
-Enables zippyEnables[] = {\r
- { IDM_MoveNow, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Hint, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Book, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Engine1Options, MF_BYCOMMAND|MF_ENABLED },\r
- { -1, -1 }\r
-};\r
-#endif\r
-\r
-Enables ncpEnables[] = {\r
- { IDM_MailMove, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_ReloadCMailMsg, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MachineWhite, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MachineBlack, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_TwoMachines, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Match, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_AnalysisMode, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_AnalyzeFile, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_IcsClient, MF_BYCOMMAND|MF_GRAYED },\r
- { ACTION_POS, MF_BYPOSITION|MF_GRAYED },\r
- { IDM_Revert, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Annotate, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MoveNow, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_RetractMove, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_TimeControl, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Hint, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Book, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MachineBoth, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_NewChat, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Engine1Options, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Engine2Options, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Sounds, MF_BYCOMMAND|MF_GRAYED },\r
- { -1, -1 }\r
-};\r
-\r
-Enables trainingOnEnables[] = {\r
- { IDM_EditComment, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Comment, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Pause, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Forward, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Backward, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_ToEnd, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_ToStart, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MoveNow, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_TruncateGame, MF_BYCOMMAND|MF_GRAYED },\r
- { -1, -1 }\r
-};\r
-\r
-Enables trainingOffEnables[] = {\r
- { IDM_EditComment, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Comment, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Pause, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Forward, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Backward, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_ToEnd, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_ToStart, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_MoveNow, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_TruncateGame, MF_BYCOMMAND|MF_ENABLED },\r
- { -1, -1 }\r
-};\r
-\r
-/* These modify either ncpEnables or gnuEnables */\r
-Enables cmailEnables[] = {\r
- { IDM_MailMove, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_ReloadCMailMsg, MF_BYCOMMAND|MF_ENABLED },\r
- { ACTION_POS, MF_BYPOSITION|MF_ENABLED },\r
- { IDM_CallFlag, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Draw, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Adjourn, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Abort, MF_BYCOMMAND|MF_GRAYED },\r
- { -1, -1 }\r
-};\r
-\r
-Enables machineThinkingEnables[] = {\r
- { IDM_LoadGame, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_LoadNextGame, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_LoadPrevGame, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_ReloadGame, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_PasteGame, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_LoadPosition, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_LoadNextPosition, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_LoadPrevPosition, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_ReloadPosition, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_PastePosition, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MachineWhite, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MachineBlack, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_TwoMachines, MF_BYCOMMAND|MF_GRAYED },\r
-// { IDM_Match, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_TypeInMove, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_RetractMove, MF_BYCOMMAND|MF_GRAYED },\r
- { -1, -1 }\r
-};\r
-\r
-Enables userThinkingEnables[] = {\r
- { IDM_LoadGame, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_LoadNextGame, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_LoadPrevGame, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_ReloadGame, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_PasteGame, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_LoadPosition, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_LoadNextPosition, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_LoadPrevPosition, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_ReloadPosition, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_PastePosition, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_MachineWhite, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_MachineBlack, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_TwoMachines, MF_BYCOMMAND|MF_ENABLED },\r
-// { IDM_Match, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_TypeInMove, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_RetractMove, MF_BYCOMMAND|MF_ENABLED },\r
- { -1, -1 }\r
-};\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Front-end interface functions exported by XBoard.\r
- * Functions appear in same order as prototypes in frontend.h.\r
- * \r
-\*---------------------------------------------------------------------------*/\r
-VOID\r
-CheckMark(UINT item, int state)\r
-{\r
- if(item) CheckMenuItem(GetMenu(hwndMain), item, MF_BYCOMMAND|state);\r
-}\r
-\r
-VOID\r
-ModeHighlight()\r
-{\r
- static UINT prevChecked = 0;\r
- static int prevPausing = 0;\r
- UINT nowChecked;\r
-\r
- if (pausing != prevPausing) {\r
- prevPausing = pausing;\r
- (void) CheckMenuItem(GetMenu(hwndMain), IDM_Pause,\r
- MF_BYCOMMAND|(pausing ? MF_CHECKED : MF_UNCHECKED));\r
- if (hwndPause) SetWindowText(hwndPause, pausing ? "C" : "P");\r
- }\r
-\r
- switch (gameMode) {\r
- case BeginningOfGame:\r
- if (appData.icsActive)\r
- nowChecked = IDM_IcsClient;\r
- else if (appData.noChessProgram)\r
- nowChecked = IDM_EditGame;\r
- else\r
- nowChecked = IDM_MachineBlack;\r
- break;\r
- case MachinePlaysBlack:\r
- nowChecked = IDM_MachineBlack;\r
- break;\r
- case MachinePlaysWhite:\r
- nowChecked = IDM_MachineWhite;\r
- break;\r
- case TwoMachinesPlay:\r
- nowChecked = IDM_TwoMachines;\r
- break;\r
- case AnalyzeMode:\r
- nowChecked = IDM_AnalysisMode;\r
- break;\r
- case AnalyzeFile:\r
- nowChecked = IDM_AnalyzeFile;\r
- break;\r
- case EditGame:\r
- nowChecked = IDM_EditGame;\r
- break;\r
- case PlayFromGameFile:\r
- nowChecked = IDM_LoadGame;\r
- break;\r
- case EditPosition:\r
- nowChecked = IDM_EditPosition;\r
- break;\r
- case Training:\r
- nowChecked = IDM_Training;\r
- break;\r
- case IcsPlayingWhite:\r
- case IcsPlayingBlack:\r
- case IcsObserving:\r
- case IcsIdle:\r
- nowChecked = IDM_IcsClient;\r
- break;\r
- default:\r
- case EndOfGame:\r
- nowChecked = 0;\r
- break;\r
- }\r
- if(prevChecked == IDM_TwoMachines) // [HGM] 'Machine Match' might have gotten disabled when stopping match\r
- EnableMenuItem(GetMenu(hwndMain), IDM_Match, MF_BYCOMMAND|MF_ENABLED);\r
- CheckMark(prevChecked, MF_UNCHECKED);\r
- CheckMark(nowChecked, MF_CHECKED);\r
- CheckMark(IDM_Match, matchMode && matchGame < appData.matchGames ? MF_CHECKED : MF_UNCHECKED);\r
-\r
- if (nowChecked == IDM_LoadGame || nowChecked == IDM_Training) {\r
- (void) EnableMenuItem(GetMenu(hwndMain), IDM_Training, \r
- MF_BYCOMMAND|MF_ENABLED);\r
- } else {\r
- (void) EnableMenuItem(GetMenu(hwndMain), \r
- IDM_Training, MF_BYCOMMAND|MF_GRAYED);\r
- }\r
-\r
- prevChecked = nowChecked;\r
-\r
- /* [DM] icsEngineAnalyze - Do a sceure check too */\r
- if (appData.icsActive) {\r
- if (appData.icsEngineAnalyze) {\r
- CheckMark(IDM_AnalysisMode, MF_CHECKED);\r
- } else {\r
- CheckMark(IDM_AnalysisMode, MF_UNCHECKED);\r
- }\r
- }\r
- DisplayLogos(); // [HGM] logos: mode change could have altered logos\r
-}\r
-\r
-VOID\r
-SetICSMode()\r
-{\r
- HMENU hmenu = GetMenu(hwndMain);\r
- SetMenuEnables(hmenu, icsEnables);\r
- EnableMenuItem(GetSubMenu(hmenu, OPTIONS_POS), IDM_IcsOptions,\r
- MF_BYCOMMAND|MF_ENABLED);\r
-#if ZIPPY\r
- if (appData.zippyPlay) {\r
- SetMenuEnables(hmenu, zippyEnables);\r
- if (!appData.noChessProgram) /* [DM] icsEngineAnalyze */\r
- (void) EnableMenuItem(GetMenu(hwndMain), IDM_AnalysisMode,\r
- MF_BYCOMMAND|MF_ENABLED);\r
- }\r
-#endif\r
-}\r
-\r
-VOID\r
-SetGNUMode()\r
-{\r
- SetMenuEnables(GetMenu(hwndMain), gnuEnables);\r
-}\r
-\r
-VOID\r
-SetNCPMode()\r
-{\r
- HMENU hmenu = GetMenu(hwndMain);\r
- SetMenuEnables(hmenu, ncpEnables);\r
- DrawMenuBar(hwndMain);\r
-}\r
-\r
-VOID\r
-SetCmailMode()\r
-{\r
- SetMenuEnables(GetMenu(hwndMain), cmailEnables);\r
-}\r
-\r
-VOID \r
-SetTrainingModeOn()\r
-{\r
- int i;\r
- SetMenuEnables(GetMenu(hwndMain), trainingOnEnables);\r
- for (i = 0; i < N_BUTTONS; i++) {\r
- if (buttonDesc[i].hwnd != NULL)\r
- EnableWindow(buttonDesc[i].hwnd, FALSE);\r
- }\r
- CommentPopDown();\r
-}\r
-\r
-VOID SetTrainingModeOff()\r
-{\r
- int i;\r
- SetMenuEnables(GetMenu(hwndMain), trainingOffEnables);\r
- for (i = 0; i < N_BUTTONS; i++) {\r
- if (buttonDesc[i].hwnd != NULL)\r
- EnableWindow(buttonDesc[i].hwnd, TRUE);\r
- }\r
-}\r
-\r
-\r
-VOID\r
-SetUserThinkingEnables()\r
-{\r
- SetMenuEnables(GetMenu(hwndMain), userThinkingEnables);\r
-}\r
-\r
-VOID\r
-SetMachineThinkingEnables()\r
-{\r
- HMENU hMenu = GetMenu(hwndMain);\r
- int flags = MF_BYCOMMAND|MF_ENABLED;\r
-\r
- SetMenuEnables(hMenu, machineThinkingEnables);\r
-\r
- if (gameMode == MachinePlaysBlack) {\r
- (void)EnableMenuItem(hMenu, IDM_MachineBlack, flags);\r
- } else if (gameMode == MachinePlaysWhite) {\r
- (void)EnableMenuItem(hMenu, IDM_MachineWhite, flags);\r
- } else if (gameMode == TwoMachinesPlay) {\r
- (void)EnableMenuItem(hMenu, matchMode ? IDM_Match : IDM_TwoMachines, flags); // [HGM] match\r
- }\r
-}\r
-\r
-\r
-VOID\r
-DisplayTitle(char *str)\r
-{\r
- char title[MSG_SIZ], *host;\r
- if (str[0] != NULLCHAR) {\r
- safeStrCpy(title, str, sizeof(title)/sizeof(title[0]) );\r
- } else if (appData.icsActive) {\r
- if (appData.icsCommPort[0] != NULLCHAR)\r
- host = "ICS";\r
- else \r
- host = appData.icsHost;\r
- snprintf(title, MSG_SIZ, "%s: %s", szTitle, host);\r
- } else if (appData.noChessProgram) {\r
- safeStrCpy(title, szTitle, sizeof(title)/sizeof(title[0]) );\r
- } else {\r
- safeStrCpy(title, szTitle, sizeof(title)/sizeof(title[0]) );\r
- strcat(title, ": ");\r
- strcat(title, first.tidy);\r
- }\r
- SetWindowText(hwndMain, title);\r
-}\r
-\r
-\r
-VOID\r
-DisplayMessage(char *str1, char *str2)\r
-{\r
- HDC hdc;\r
- HFONT oldFont;\r
- int remain = MESSAGE_TEXT_MAX - 1;\r
- int len;\r
-\r
- moveErrorMessageUp = FALSE; /* turned on later by caller if needed */\r
- messageText[0] = NULLCHAR;\r
- if (*str1) {\r
- len = strlen(str1);\r
- if (len > remain) len = remain;\r
- strncpy(messageText, str1, len);\r
- messageText[len] = NULLCHAR;\r
- remain -= len;\r
- }\r
- if (*str2 && remain >= 2) {\r
- if (*str1) {\r
- strcat(messageText, " ");\r
- remain -= 2;\r
- }\r
- len = strlen(str2);\r
- if (len > remain) len = remain;\r
- strncat(messageText, str2, len);\r
- }\r
- messageText[MESSAGE_TEXT_MAX - 1] = NULLCHAR;\r
- safeStrCpy(lastMsg, messageText, MSG_SIZ);\r
-\r
- if (hwndMain == NULL || IsIconic(hwndMain)) return;\r
-\r
- SAYMACHINEMOVE();\r
-\r
- hdc = GetDC(hwndMain);\r
- oldFont = SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);\r
- ExtTextOut(hdc, messageRect.left, messageRect.top, ETO_CLIPPED|ETO_OPAQUE,\r
- &messageRect, messageText, strlen(messageText), NULL);\r
- (void) SelectObject(hdc, oldFont);\r
- (void) ReleaseDC(hwndMain, hdc);\r
-}\r
-\r
-VOID\r
-DisplayError(char *str, int error)\r
-{\r
- char buf[MSG_SIZ*2], buf2[MSG_SIZ];\r
- int len;\r
-\r
- if (error == 0) {\r
- safeStrCpy(buf, str, sizeof(buf)/sizeof(buf[0]) );\r
- } else {\r
- len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,\r
- NULL, error, LANG_NEUTRAL,\r
- (LPSTR) buf2, MSG_SIZ, NULL);\r
- if (len > 0) {\r
- snprintf(buf, 2*MSG_SIZ, "%s:\n%s", str, buf2);\r
- } else {\r
- ErrorMap *em = errmap;\r
- while (em->err != 0 && em->err != error) em++;\r
- if (em->err != 0) {\r
- snprintf(buf, 2*MSG_SIZ, "%s:\n%s", str, em->msg);\r
- } else {\r
- snprintf(buf, 2*MSG_SIZ, "%s:\nError code %d", str, error);\r
- }\r
- }\r
- }\r
- \r
- ErrorPopUp(_("Error"), buf);\r
-}\r
-\r
-\r
-VOID\r
-DisplayMoveError(char *str)\r
-{\r
- fromX = fromY = -1;\r
- ClearHighlights();\r
- DrawPosition(FALSE, NULL);\r
- if (appData.popupMoveErrors) {\r
- ErrorPopUp(_("Error"), str);\r
- } else {\r
- DisplayMessage(str, "");\r
- moveErrorMessageUp = TRUE;\r
- }\r
-}\r
-\r
-VOID\r
-DisplayFatalError(char *str, int error, int exitStatus)\r
-{\r
- char buf[2*MSG_SIZ], buf2[MSG_SIZ];\r
- int len;\r
- char *label = exitStatus ? _("Fatal Error") : _("Exiting");\r
-\r
- if (error != 0) {\r
- len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,\r
- NULL, error, LANG_NEUTRAL,\r
- (LPSTR) buf2, MSG_SIZ, NULL);\r
- if (len > 0) {\r
- snprintf(buf, 2*MSG_SIZ, "%s:\n%s", str, buf2);\r
- } else {\r
- ErrorMap *em = errmap;\r
- while (em->err != 0 && em->err != error) em++;\r
- if (em->err != 0) {\r
- snprintf(buf, 2*MSG_SIZ, "%s:\n%s", str, em->msg);\r
- } else {\r
- snprintf(buf, 2*MSG_SIZ, "%s:\nError code %d", str, error);\r
- }\r
- }\r
- str = buf;\r
- }\r
- if (appData.debugMode) {\r
- fprintf(debugFP, "%s: %s\n", label, str);\r
- }\r
- if (appData.popupExitMessage) {\r
- if(appData.icsActive) SendToICS("logout\n"); // [HGM] make sure no new games will be started!\r
- (void) MessageBox(hwndMain, str, label, MB_OK|\r
- (exitStatus ? MB_ICONSTOP : MB_ICONINFORMATION));\r
- }\r
- ExitEvent(exitStatus);\r
-}\r
-\r
-\r
-VOID\r
-DisplayInformation(char *str)\r
-{\r
- (void) MessageBox(hwndMain, str, _("Information"), MB_OK|MB_ICONINFORMATION);\r
-}\r
-\r
-\r
-VOID\r
-DisplayNote(char *str)\r
-{\r
- ErrorPopUp(_("Note"), str);\r
-}\r
-\r
-\r
-typedef struct {\r
- char *title, *question, *replyPrefix;\r
- ProcRef pr;\r
-} QuestionParams;\r
-\r
-LRESULT CALLBACK\r
-QuestionDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- static QuestionParams *qp;\r
- char reply[MSG_SIZ];\r
- int len, err;\r
-\r
- switch (message) {\r
- case WM_INITDIALOG:\r
- qp = (QuestionParams *) lParam;\r
- CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER));\r
- Translate(hDlg, DLG_Question);\r
- SetWindowText(hDlg, qp->title);\r
- SetDlgItemText(hDlg, OPT_QuestionText, qp->question);\r
- SetFocus(GetDlgItem(hDlg, OPT_QuestionInput));\r
- return FALSE;\r
-\r
- case WM_COMMAND:\r
- switch (LOWORD(wParam)) {\r
- case IDOK:\r
- safeStrCpy(reply, qp->replyPrefix, sizeof(reply)/sizeof(reply[0]) );\r
- if (*reply) strcat(reply, " ");\r
- len = strlen(reply);\r
- GetDlgItemText(hDlg, OPT_QuestionInput, reply + len, sizeof(reply) - len);\r
- strcat(reply, "\n");\r
- OutputToProcess(qp->pr, reply, strlen(reply), &err);\r
- EndDialog(hDlg, TRUE);\r
- if (err) DisplayFatalError(_("Error writing to chess program"), err, 1);\r
- return TRUE;\r
- case IDCANCEL:\r
- EndDialog(hDlg, FALSE);\r
- return TRUE;\r
- default:\r
- break;\r
- }\r
- break;\r
- }\r
- return FALSE;\r
-}\r
-\r
-VOID\r
-AskQuestion(char* title, char *question, char *replyPrefix, ProcRef pr)\r
-{\r
- QuestionParams qp;\r
- FARPROC lpProc;\r
- \r
- qp.title = title;\r
- qp.question = question;\r
- qp.replyPrefix = replyPrefix;\r
- qp.pr = pr;\r
- lpProc = MakeProcInstance((FARPROC)QuestionDialog, hInst);\r
- DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_Question),\r
- hwndMain, (DLGPROC)lpProc, (LPARAM)&qp);\r
- FreeProcInstance(lpProc);\r
-}\r
-\r
-/* [AS] Pick FRC position */\r
-LRESULT CALLBACK NewGameFRC_Proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- static int * lpIndexFRC;\r
- BOOL index_is_ok;\r
- char buf[16];\r
-\r
- switch( message )\r
- {\r
- case WM_INITDIALOG:\r
- lpIndexFRC = (int *) lParam;\r
-\r
- CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER));\r
- Translate(hDlg, DLG_NewGameFRC);\r
-\r
- SendDlgItemMessage( hDlg, IDC_NFG_Edit, EM_SETLIMITTEXT, sizeof(buf)-1, 0 );\r
- SetDlgItemInt( hDlg, IDC_NFG_Edit, *lpIndexFRC, TRUE );\r
- SendDlgItemMessage( hDlg, IDC_NFG_Edit, EM_SETSEL, 0, -1 );\r
- SetFocus(GetDlgItem(hDlg, IDC_NFG_Edit));\r
-\r
- break;\r
-\r
- case WM_COMMAND:\r
- switch( LOWORD(wParam) ) {\r
- case IDOK:\r
- *lpIndexFRC = GetDlgItemInt(hDlg, IDC_NFG_Edit, &index_is_ok, TRUE );\r
- EndDialog( hDlg, 0 );\r
- shuffleOpenings = TRUE; /* [HGM] shuffle: switch shuffling on for as long as we stay in current variant */\r
- return TRUE;\r
- case IDCANCEL:\r
- EndDialog( hDlg, 1 ); \r
- return TRUE;\r
- case IDC_NFG_Edit:\r
- if( HIWORD(wParam) == EN_CHANGE ) {\r
- GetDlgItemInt(hDlg, IDC_NFG_Edit, &index_is_ok, TRUE );\r
-\r
- EnableWindow( GetDlgItem(hDlg, IDOK), index_is_ok );\r
- }\r
- return TRUE;\r
- case IDC_NFG_Random:\r
- snprintf( buf, sizeof(buf)/sizeof(buf[0]), "%d", myrandom() ); /* [HGM] shuffle: no longer limit to 960 */\r
- SetDlgItemText(hDlg, IDC_NFG_Edit, buf );\r
- return TRUE;\r
- }\r
-\r
- break;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-int NewGameFRC()\r
-{\r
- int result;\r
- int index = appData.defaultFrcPosition;\r
- FARPROC lpProc = MakeProcInstance( (FARPROC) NewGameFRC_Proc, hInst );\r
-\r
- result = DialogBoxParam( hInst, MAKEINTRESOURCE(DLG_NewGameFRC), hwndMain, (DLGPROC)lpProc, (LPARAM)&index );\r
-\r
- if( result == 0 ) {\r
- appData.defaultFrcPosition = index;\r
- }\r
-\r
- return result;\r
-}\r
-\r
-/* [AS] Game list options. Refactored by HGM */\r
-\r
-HWND gameListOptionsDialog;\r
-\r
-// low-level front-end: clear text edit / list widget\r
-void\r
-\r
-GLT_ClearList()\r
-{\r
- SendDlgItemMessage( gameListOptionsDialog, IDC_GameListTags, LB_RESETCONTENT, 0, 0 );\r
-}\r
-\r
-// low-level front-end: clear text edit / list widget\r
-void\r
-GLT_DeSelectList()\r
-{\r
- SendDlgItemMessage( gameListOptionsDialog, IDC_GameListTags, LB_SETCURSEL, 0, 0 );\r
-}\r
-\r
-// low-level front-end: append line to text edit / list widget\r
-void\r
-GLT_AddToList( char *name )\r
-{\r
- if( name != 0 ) {\r
- SendDlgItemMessage( gameListOptionsDialog, IDC_GameListTags, LB_ADDSTRING, 0, (LPARAM) name );\r
- }\r
-}\r
-\r
-// low-level front-end: get line from text edit / list widget\r
-Boolean\r
-GLT_GetFromList( int index, char *name )\r
-{\r
- if( name != 0 ) {\r
- if( SendDlgItemMessage( gameListOptionsDialog, IDC_GameListTags, LB_GETTEXT, index, (LPARAM) name ) != LB_ERR )\r
- return TRUE;\r
- }\r
- return FALSE;\r
-}\r
-\r
-void GLT_MoveSelection( HWND hDlg, int delta )\r
-{\r
- int idx1 = (int) SendDlgItemMessage( hDlg, IDC_GameListTags, LB_GETCURSEL, 0, 0 );\r
- int idx2 = idx1 + delta;\r
- int count = (int) SendDlgItemMessage( hDlg, IDC_GameListTags, LB_GETCOUNT, 0, 0 );\r
-\r
- if( idx1 >=0 && idx1 < count && idx2 >= 0 && idx2 < count ) {\r
- char buf[128];\r
-\r
- SendDlgItemMessage( hDlg, IDC_GameListTags, LB_GETTEXT, idx1, (LPARAM) buf );\r
- SendDlgItemMessage( hDlg, IDC_GameListTags, LB_DELETESTRING, idx1, 0 );\r
- SendDlgItemMessage( hDlg, IDC_GameListTags, LB_INSERTSTRING, idx2, (LPARAM) buf );\r
- SendDlgItemMessage( hDlg, IDC_GameListTags, LB_SETCURSEL, idx2, 0 );\r
- }\r
-}\r
-\r
-LRESULT CALLBACK GameListOptions_Proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- switch( message )\r
- {\r
- case WM_INITDIALOG:\r
- gameListOptionsDialog = hDlg; // [HGM] pass through global to keep out off back-end\r
- \r
- CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER));\r
- Translate(hDlg, DLG_GameListOptions);\r
-\r
- /* Initialize list */\r
- GLT_TagsToList( lpUserGLT );\r
-\r
- SetFocus( GetDlgItem(hDlg, IDC_GameListTags) );\r
-\r
- break;\r
-\r
- case WM_COMMAND:\r
- switch( LOWORD(wParam) ) {\r
- case IDOK:\r
- GLT_ParseList();\r
- EndDialog( hDlg, 0 );\r
- return TRUE;\r
- case IDCANCEL:\r
- EndDialog( hDlg, 1 );\r
- return TRUE;\r
-\r
- case IDC_GLT_Default:\r
- GLT_TagsToList( GLT_DEFAULT_TAGS );\r
- return TRUE;\r
-\r
- case IDC_GLT_Restore:\r
- GLT_TagsToList( appData.gameListTags );\r
- return TRUE;\r
-\r
- case IDC_GLT_Up:\r
- GLT_MoveSelection( hDlg, -1 );\r
- return TRUE;\r
-\r
- case IDC_GLT_Down:\r
- GLT_MoveSelection( hDlg, +1 );\r
- return TRUE;\r
- }\r
-\r
- break;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-int GameListOptions()\r
-{\r
- int result;\r
- FARPROC lpProc = MakeProcInstance( (FARPROC) GameListOptions_Proc, hInst );\r
-\r
- safeStrCpy( lpUserGLT, appData.gameListTags ,LPUSERGLT_SIZE ); \r
-\r
- result = DialogBoxParam( hInst, MAKEINTRESOURCE(DLG_GameListOptions), hwndMain, (DLGPROC)lpProc, (LPARAM)lpUserGLT );\r
-\r
- if( result == 0 ) {\r
- char *oldTags = appData.gameListTags;\r
- /* [AS] Memory leak here! */\r
- appData.gameListTags = strdup( lpUserGLT ); \r
- if(strcmp(oldTags, appData.gameListTags)) // [HGM] redo Game List when we changed something\r
- GameListToListBox(NULL, TRUE, ".", NULL, FALSE, FALSE); // "." as filter is kludge to select all\r
- }\r
-\r
- return result;\r
-}\r
-\r
-VOID\r
-DisplayIcsInteractionTitle(char *str)\r
-{\r
- char consoleTitle[MSG_SIZ];\r
-\r
- snprintf(consoleTitle, MSG_SIZ, "%s: %s", szConsoleTitle, str);\r
- SetWindowText(hwndConsole, consoleTitle);\r
-\r
- if(appData.chatBoxes) { // [HGM] chat: open chat boxes\r
- char buf[MSG_SIZ], *p = buf, *q;\r
- safeStrCpy(buf, appData.chatBoxes, sizeof(buf)/sizeof(buf[0]) );\r
- do {\r
- q = strchr(p, ';');\r
- if(q) *q++ = 0;\r
- if(*p) ChatPopUp(p);\r
- } while(p=q);\r
- }\r
-\r
- SetActiveWindow(hwndMain);\r
-}\r
-\r
-void\r
-DrawPosition(int fullRedraw, Board board)\r
-{\r
- HDCDrawPosition(NULL, (BOOLEAN) fullRedraw, board); \r
-}\r
-\r
-void NotifyFrontendLogin()\r
-{\r
- if (hwndConsole)\r
- UpdateICSWidth(GetDlgItem(hwndConsole, OPT_ConsoleText));\r
-}\r
-\r
-VOID\r
-ResetFrontEnd()\r
-{\r
- fromX = fromY = -1;\r
- if (dragInfo.pos.x != -1 || dragInfo.pos.y != -1) {\r
- dragInfo.pos.x = dragInfo.pos.y = -1;\r
- dragInfo.pos.x = dragInfo.pos.y = -1;\r
- dragInfo.lastpos = dragInfo.pos;\r
- dragInfo.start.x = dragInfo.start.y = -1;\r
- dragInfo.from = dragInfo.start;\r
- ReleaseCapture();\r
- DrawPosition(TRUE, NULL);\r
- }\r
- TagsPopDown();\r
-}\r
-\r
-\r
-VOID\r
-CommentPopUp(char *title, char *str)\r
-{\r
- HWND hwnd = GetActiveWindow();\r
- EitherCommentPopUp(currentMove, title, str, FALSE); // [HGM] vari: fake move index, rather than 0\r
- SAY(str);\r
- SetActiveWindow(hwnd);\r
-}\r
-\r
-VOID\r
-CommentPopDown(void)\r
-{\r
- CheckMenuItem(GetMenu(hwndMain), IDM_Comment, MF_UNCHECKED);\r
- if (commentDialog) {\r
- ShowWindow(commentDialog, SW_HIDE);\r
- }\r
- commentUp = FALSE;\r
-}\r
-\r
-VOID\r
-EditCommentPopUp(int index, char *title, char *str)\r
-{\r
- EitherCommentPopUp(index, title, str, TRUE);\r
-}\r
-\r
-\r
-int\r
-Roar()\r
-{\r
- MyPlaySound(&sounds[(int)SoundRoar]);\r
- return 1;\r
-}\r
-\r
-VOID\r
-RingBell()\r
-{\r
- MyPlaySound(&sounds[(int)SoundMove]);\r
-}\r
-\r
-VOID PlayIcsWinSound()\r
-{\r
- MyPlaySound(&sounds[(int)SoundIcsWin]);\r
-}\r
-\r
-VOID PlayIcsLossSound()\r
-{\r
- MyPlaySound(&sounds[(int)SoundIcsLoss]);\r
-}\r
-\r
-VOID PlayIcsDrawSound()\r
-{\r
- MyPlaySound(&sounds[(int)SoundIcsDraw]);\r
-}\r
-\r
-VOID PlayIcsUnfinishedSound()\r
-{\r
- MyPlaySound(&sounds[(int)SoundIcsUnfinished]);\r
-}\r
-\r
-VOID\r
-PlayAlarmSound()\r
-{\r
- MyPlaySound(&sounds[(int)SoundAlarm]);\r
-}\r
-\r
-VOID\r
-PlayTellSound()\r
-{\r
- MyPlaySound(&textAttribs[ColorTell].sound);\r
-}\r
-\r
-\r
-VOID\r
-EchoOn()\r
-{\r
- HWND hInput;\r
- consoleEcho = TRUE;\r
- hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- SendMessage(hInput, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&consoleCF);\r
- SendMessage(hInput, EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor);\r
-}\r
-\r
-\r
-VOID\r
-EchoOff()\r
-{\r
- CHARFORMAT cf;\r
- HWND hInput;\r
- consoleEcho = FALSE;\r
- hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- /* This works OK: set text and background both to the same color */\r
- cf = consoleCF;\r
- cf.crTextColor = COLOR_ECHOOFF;\r
- SendMessage(hInput, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);\r
- SendMessage(hInput, EM_SETBKGNDCOLOR, FALSE, cf.crTextColor);\r
-}\r
-\r
-/* No Raw()...? */\r
-\r
-void Colorize(ColorClass cc, int continuation)\r
-{\r
- currentColorClass = cc;\r
- consoleCF.dwMask = CFM_COLOR|CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_STRIKEOUT;\r
- consoleCF.crTextColor = textAttribs[cc].color;\r
- consoleCF.dwEffects = textAttribs[cc].effects;\r
- if (!continuation) MyPlaySound(&textAttribs[cc].sound);\r
-}\r
-\r
-char *\r
-UserName()\r
-{\r
- static char buf[MSG_SIZ];\r
- DWORD bufsiz = MSG_SIZ;\r
-\r
- if(appData.userName != NULL && appData.userName[0] != 0) { \r
- return appData.userName; /* [HGM] username: prefer name selected by user over his system login */\r
- }\r
- if (!GetUserName(buf, &bufsiz)) {\r
- /*DisplayError("Error getting user name", GetLastError());*/\r
- safeStrCpy(buf, _("User"), sizeof(buf)/sizeof(buf[0]) );\r
- }\r
- return buf;\r
-}\r
-\r
-char *\r
-HostName()\r
-{\r
- static char buf[MSG_SIZ];\r
- DWORD bufsiz = MSG_SIZ;\r
-\r
- if (!GetComputerName(buf, &bufsiz)) {\r
- /*DisplayError("Error getting host name", GetLastError());*/\r
- safeStrCpy(buf, _("Unknown"), sizeof(buf)/sizeof(buf[0]) );\r
- }\r
- return buf;\r
-}\r
-\r
-\r
-int\r
-ClockTimerRunning()\r
-{\r
- return clockTimerEvent != 0;\r
-}\r
-\r
-int\r
-StopClockTimer()\r
-{\r
- if (clockTimerEvent == 0) return FALSE;\r
- KillTimer(hwndMain, clockTimerEvent);\r
- clockTimerEvent = 0;\r
- return TRUE;\r
-}\r
-\r
-void\r
-StartClockTimer(long millisec)\r
-{\r
- clockTimerEvent = SetTimer(hwndMain, (UINT) CLOCK_TIMER_ID,\r
- (UINT) millisec, NULL);\r
-}\r
-\r
-void\r
-DisplayWhiteClock(long timeRemaining, int highlight)\r
-{\r
- HDC hdc;\r
- char *flag = whiteFlag && gameMode == TwoMachinesPlay ? "(!)" : "";\r
-\r
- if(appData.noGUI) return;\r
- hdc = GetDC(hwndMain);\r
- if (!IsIconic(hwndMain)) {\r
- DisplayAClock(hdc, timeRemaining, highlight, \r
- flipClock ? &blackRect : &whiteRect, _("White"), flag);\r
- }\r
- if (highlight && iconCurrent == iconBlack) {\r
- iconCurrent = iconWhite;\r
- PostMessage(hwndMain, WM_SETICON, (WPARAM) TRUE, (LPARAM) iconCurrent);\r
- if (IsIconic(hwndMain)) {\r
- DrawIcon(hdc, 2, 2, iconCurrent);\r
- }\r
- }\r
- (void) ReleaseDC(hwndMain, hdc);\r
- if (hwndConsole)\r
- PostMessage(hwndConsole, WM_SETICON, (WPARAM) TRUE, (LPARAM) iconCurrent);\r
-}\r
-\r
-void\r
-DisplayBlackClock(long timeRemaining, int highlight)\r
-{\r
- HDC hdc;\r
- char *flag = blackFlag && gameMode == TwoMachinesPlay ? "(!)" : "";\r
-\r
-\r
- if(appData.noGUI) return;\r
- hdc = GetDC(hwndMain);\r
- if (!IsIconic(hwndMain)) {\r
- DisplayAClock(hdc, timeRemaining, highlight, \r
- flipClock ? &whiteRect : &blackRect, _("Black"), flag);\r
- }\r
- if (highlight && iconCurrent == iconWhite) {\r
- iconCurrent = iconBlack;\r
- PostMessage(hwndMain, WM_SETICON, (WPARAM) TRUE, (LPARAM) iconCurrent);\r
- if (IsIconic(hwndMain)) {\r
- DrawIcon(hdc, 2, 2, iconCurrent);\r
- }\r
- }\r
- (void) ReleaseDC(hwndMain, hdc);\r
- if (hwndConsole)\r
- PostMessage(hwndConsole, WM_SETICON, (WPARAM) TRUE, (LPARAM) iconCurrent);\r
-}\r
-\r
-\r
-int\r
-LoadGameTimerRunning()\r
-{\r
- return loadGameTimerEvent != 0;\r
-}\r
-\r
-int\r
-StopLoadGameTimer()\r
-{\r
- if (loadGameTimerEvent == 0) return FALSE;\r
- KillTimer(hwndMain, loadGameTimerEvent);\r
- loadGameTimerEvent = 0;\r
- return TRUE;\r
-}\r
-\r
-void\r
-StartLoadGameTimer(long millisec)\r
-{\r
- loadGameTimerEvent = SetTimer(hwndMain, (UINT) LOAD_GAME_TIMER_ID,\r
- (UINT) millisec, NULL);\r
-}\r
-\r
-void\r
-AutoSaveGame()\r
-{\r
- char *defName;\r
- FILE *f;\r
- char fileTitle[MSG_SIZ];\r
-\r
- defName = DefaultFileName(appData.oldSaveStyle ? "gam" : "pgn");\r
- f = OpenFileDialog(hwndMain, "a", defName,\r
- appData.oldSaveStyle ? "gam" : "pgn",\r
- GAME_FILT, \r
- _("Save Game to File"), NULL, fileTitle, NULL);\r
- if (f != NULL) {\r
- SaveGame(f, 0, "");\r
- fclose(f);\r
- }\r
-}\r
-\r
-\r
-void\r
-ScheduleDelayedEvent(DelayedEventCallback cb, long millisec)\r
-{\r
- if (delayedTimerEvent != 0) {\r
- if (appData.debugMode && cb != delayedTimerCallback) { // [HGM] alive: not too much debug\r
- fprintf(debugFP, "ScheduleDelayedEvent: event already scheduled\n");\r
- }\r
- KillTimer(hwndMain, delayedTimerEvent);\r
- delayedTimerEvent = 0;\r
- if(delayedTimerCallback != cb) // [HGM] alive: do not "flush" same event, just postpone it\r
- delayedTimerCallback();\r
- }\r
- delayedTimerCallback = cb;\r
- delayedTimerEvent = SetTimer(hwndMain, (UINT) DELAYED_TIMER_ID,\r
- (UINT) millisec, NULL);\r
-}\r
-\r
-DelayedEventCallback\r
-GetDelayedEvent()\r
-{\r
- if (delayedTimerEvent) {\r
- return delayedTimerCallback;\r
- } else {\r
- return NULL;\r
- }\r
-}\r
-\r
-void\r
-CancelDelayedEvent()\r
-{\r
- if (delayedTimerEvent) {\r
- KillTimer(hwndMain, delayedTimerEvent);\r
- delayedTimerEvent = 0;\r
- }\r
-}\r
-\r
-DWORD GetWin32Priority(int nice)\r
-{ // [HGM] nice: translate Unix nice() value to indows priority class. (Code stolen from Polyglot 1.4w11)\r
-/*\r
-REALTIME_PRIORITY_CLASS 0x00000100\r
-HIGH_PRIORITY_CLASS 0x00000080\r
-ABOVE_NORMAL_PRIORITY_CLASS 0x00008000\r
-NORMAL_PRIORITY_CLASS 0x00000020\r
-BELOW_NORMAL_PRIORITY_CLASS 0x00004000\r
-IDLE_PRIORITY_CLASS 0x00000040\r
-*/\r
- if (nice < -15) return 0x00000080;\r
- if (nice < 0) return 0x00008000;\r
-\r
- if (nice == 0) return 0x00000020;\r
- if (nice < 15) return 0x00004000;\r
- return 0x00000040;\r
-}\r
-\r
-void RunCommand(char *cmdLine)\r
-{\r
- /* Now create the child process. */\r
- STARTUPINFO siStartInfo;\r
- PROCESS_INFORMATION piProcInfo;\r
-\r
- siStartInfo.cb = sizeof(STARTUPINFO);\r
- siStartInfo.lpReserved = NULL;\r
- siStartInfo.lpDesktop = NULL;\r
- siStartInfo.lpTitle = NULL;\r
- siStartInfo.dwFlags = STARTF_USESTDHANDLES;\r
- siStartInfo.cbReserved2 = 0;\r
- siStartInfo.lpReserved2 = NULL;\r
- siStartInfo.hStdInput = NULL;\r
- siStartInfo.hStdOutput = NULL;\r
- siStartInfo.hStdError = NULL;\r
-\r
- CreateProcess(NULL,\r
- cmdLine, /* command line */\r
- NULL, /* process security attributes */\r
- NULL, /* primary thread security attrs */\r
- TRUE, /* handles are inherited */\r
- DETACHED_PROCESS|CREATE_NEW_PROCESS_GROUP,\r
- NULL, /* use parent's environment */\r
- NULL,\r
- &siStartInfo, /* STARTUPINFO pointer */\r
- &piProcInfo); /* receives PROCESS_INFORMATION */\r
-\r
- CloseHandle(piProcInfo.hThread);\r
-}\r
-\r
-/* Start a child process running the given program.\r
- The process's standard output can be read from "from", and its\r
- standard input can be written to "to".\r
- Exit with fatal error if anything goes wrong.\r
- Returns an opaque pointer that can be used to destroy the process\r
- later.\r
-*/\r
-int\r
-StartChildProcess(char *cmdLine, char *dir, ProcRef *pr)\r
-{\r
-#define BUFSIZE 4096\r
-\r
- HANDLE hChildStdinRd, hChildStdinWr,\r
- hChildStdoutRd, hChildStdoutWr;\r
- HANDLE hChildStdinWrDup, hChildStdoutRdDup;\r
- SECURITY_ATTRIBUTES saAttr;\r
- BOOL fSuccess;\r
- PROCESS_INFORMATION piProcInfo;\r
- STARTUPINFO siStartInfo;\r
- ChildProc *cp;\r
- char buf[MSG_SIZ];\r
- DWORD err;\r
-\r
- if (appData.debugMode) {\r
- fprintf(debugFP, "StartChildProcess (dir=\"%s\") %s\n", dir, cmdLine);\r
- }\r
-\r
- *pr = NoProc;\r
-\r
- /* Set the bInheritHandle flag so pipe handles are inherited. */\r
- saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);\r
- saAttr.bInheritHandle = TRUE;\r
- saAttr.lpSecurityDescriptor = NULL;\r
-\r
- /*\r
- * The steps for redirecting child's STDOUT:\r
- * 1. Create anonymous pipe to be STDOUT for child.\r
- * 2. Create a noninheritable duplicate of read handle,\r
- * and close the inheritable read handle.\r
- */\r
-\r
- /* Create a pipe for the child's STDOUT. */\r
- if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) {\r
- return GetLastError();\r
- }\r
-\r
- /* Duplicate the read handle to the pipe, so it is not inherited. */\r
- fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,\r
- GetCurrentProcess(), &hChildStdoutRdDup, 0,\r
- FALSE, /* not inherited */\r
- DUPLICATE_SAME_ACCESS);\r
- if (! fSuccess) {\r
- return GetLastError();\r
- }\r
- CloseHandle(hChildStdoutRd);\r
-\r
- /*\r
- * The steps for redirecting child's STDIN:\r
- * 1. Create anonymous pipe to be STDIN for child.\r
- * 2. Create a noninheritable duplicate of write handle,\r
- * and close the inheritable write handle.\r
- */\r
-\r
- /* Create a pipe for the child's STDIN. */\r
- if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) {\r
- return GetLastError();\r
- }\r
-\r
- /* Duplicate the write handle to the pipe, so it is not inherited. */\r
- fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,\r
- GetCurrentProcess(), &hChildStdinWrDup, 0,\r
- FALSE, /* not inherited */\r
- DUPLICATE_SAME_ACCESS);\r
- if (! fSuccess) {\r
- return GetLastError();\r
- }\r
- CloseHandle(hChildStdinWr);\r
-\r
- /* Arrange to (1) look in dir for the child .exe file, and\r
- * (2) have dir be the child's working directory. Interpret\r
- * dir relative to the directory WinBoard loaded from. */\r
- GetCurrentDirectory(MSG_SIZ, buf);\r
- SetCurrentDirectory(installDir);\r
- SetCurrentDirectory(dir);\r
-\r
- /* Now create the child process. */\r
-\r
- siStartInfo.cb = sizeof(STARTUPINFO);\r
- siStartInfo.lpReserved = NULL;\r
- siStartInfo.lpDesktop = NULL;\r
- siStartInfo.lpTitle = NULL;\r
- siStartInfo.dwFlags = STARTF_USESTDHANDLES;\r
- siStartInfo.cbReserved2 = 0;\r
- siStartInfo.lpReserved2 = NULL;\r
- siStartInfo.hStdInput = hChildStdinRd;\r
- siStartInfo.hStdOutput = hChildStdoutWr;\r
- siStartInfo.hStdError = hChildStdoutWr;\r
-\r
- fSuccess = CreateProcess(NULL,\r
- cmdLine, /* command line */\r
- NULL, /* process security attributes */\r
- NULL, /* primary thread security attrs */\r
- TRUE, /* handles are inherited */\r
- DETACHED_PROCESS|CREATE_NEW_PROCESS_GROUP,\r
- NULL, /* use parent's environment */\r
- NULL,\r
- &siStartInfo, /* STARTUPINFO pointer */\r
- &piProcInfo); /* receives PROCESS_INFORMATION */\r
-\r
- err = GetLastError();\r
- SetCurrentDirectory(buf); /* return to prev directory */\r
- if (! fSuccess) {\r
- return err;\r
- }\r
-\r
- if (appData.niceEngines){ // [HGM] nice: adjust engine proc priority\r
- if(appData.debugMode) fprintf(debugFP, "nice engine proc to %d\n", appData.niceEngines);\r
- SetPriorityClass(piProcInfo.hProcess, GetWin32Priority(appData.niceEngines));\r
- }\r
-\r
- /* Close the handles we don't need in the parent */\r
- CloseHandle(piProcInfo.hThread);\r
- CloseHandle(hChildStdinRd);\r
- CloseHandle(hChildStdoutWr);\r
-\r
- /* Prepare return value */\r
- cp = (ChildProc *) calloc(1, sizeof(ChildProc));\r
- cp->kind = CPReal;\r
- cp->hProcess = piProcInfo.hProcess;\r
- cp->pid = piProcInfo.dwProcessId;\r
- cp->hFrom = hChildStdoutRdDup;\r
- cp->hTo = hChildStdinWrDup;\r
-\r
- *pr = (void *) cp;\r
-\r
- /* Klaus Friedel says that this Sleep solves a problem under Windows\r
- 2000 where engines sometimes don't see the initial command(s)\r
- from WinBoard and hang. I don't understand how that can happen,\r
- but the Sleep is harmless, so I've put it in. Others have also\r
- reported what may be the same problem, so hopefully this will fix\r
- it for them too. */\r
- Sleep(500);\r
-\r
- return NO_ERROR;\r
-}\r
-\r
-\r
-void\r
-DestroyChildProcess(ProcRef pr, int/*boolean*/ signal)\r
-{\r
- ChildProc *cp; int result;\r
-\r
- cp = (ChildProc *) pr;\r
- if (cp == NULL) return;\r
-\r
- switch (cp->kind) {\r
- case CPReal:\r
- /* TerminateProcess is considered harmful, so... */\r
- CloseHandle(cp->hTo); /* Closing this will give the child an EOF and hopefully kill it */\r
- if (cp->hFrom) CloseHandle(cp->hFrom); /* if NULL, InputThread will close it */\r
- /* The following doesn't work because the chess program\r
- doesn't "have the same console" as WinBoard. Maybe\r
- we could arrange for this even though neither WinBoard\r
- nor the chess program uses a console for stdio? */\r
- /*!!if (signal) GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, cp->pid);*/\r
-\r
- /* [AS] Special termination modes for misbehaving programs... */\r
- if( signal & 8 ) { \r
- result = TerminateProcess( cp->hProcess, 0 );\r
-\r
- if ( appData.debugMode) {\r
- fprintf( debugFP, "Terminating process %lu, result=%d\n", cp->pid, result );\r
- }\r
- }\r
- else if( signal & 4 ) {\r
- DWORD dw = WaitForSingleObject( cp->hProcess, appData.delayAfterQuit*1000 + 50 ); // Wait 3 seconds at most\r
-\r
- if( dw != WAIT_OBJECT_0 ) {\r
- result = TerminateProcess( cp->hProcess, 0 );\r
-\r
- if ( appData.debugMode) {\r
- fprintf( debugFP, "Process %lu still alive after timeout, killing... result=%d\n", cp->pid, result );\r
- }\r
-\r
- }\r
- }\r
-\r
- CloseHandle(cp->hProcess);\r
- break;\r
-\r
- case CPComm:\r
- if (cp->hFrom) CloseHandle(cp->hFrom);\r
- break;\r
-\r
- case CPSock:\r
- closesocket(cp->sock);\r
- WSACleanup();\r
- break;\r
-\r
- case CPRcmd:\r
- if (signal) send(cp->sock2, "\017", 1, 0); /* 017 = 15 = SIGTERM */\r
- closesocket(cp->sock);\r
- closesocket(cp->sock2);\r
- WSACleanup();\r
- break;\r
- }\r
- free(cp);\r
-}\r
-\r
-void\r
-InterruptChildProcess(ProcRef pr)\r
-{\r
- ChildProc *cp;\r
-\r
- cp = (ChildProc *) pr;\r
- if (cp == NULL) return;\r
- switch (cp->kind) {\r
- case CPReal:\r
- /* The following doesn't work because the chess program\r
- doesn't "have the same console" as WinBoard. Maybe\r
- we could arrange for this even though neither WinBoard\r
- nor the chess program uses a console for stdio */\r
- /*!!GenerateConsoleCtrlEvent(CTRL_C_EVENT, cp->pid);*/\r
- break;\r
-\r
- case CPComm:\r
- case CPSock:\r
- /* Can't interrupt */\r
- break;\r
-\r
- case CPRcmd:\r
- send(cp->sock2, "\002", 1, 0); /* 2 = SIGINT */\r
- break;\r
- }\r
-}\r
-\r
-\r
-int\r
-OpenTelnet(char *host, char *port, ProcRef *pr)\r
-{\r
- char cmdLine[MSG_SIZ];\r
-\r
- if (port[0] == NULLCHAR) {\r
- snprintf(cmdLine, MSG_SIZ, "%s %s", appData.telnetProgram, host);\r
- } else {\r
- snprintf(cmdLine, MSG_SIZ, "%s %s %s", appData.telnetProgram, host, port);\r
- }\r
- return StartChildProcess(cmdLine, "", pr);\r
-}\r
-\r
-\r
-/* Code to open TCP sockets */\r
-\r
-int\r
-OpenTCP(char *host, char *port, ProcRef *pr)\r
-{\r
- ChildProc *cp;\r
- int err;\r
- SOCKET s;\r
-\r
- struct sockaddr_in sa, mysa;\r
- struct hostent FAR *hp;\r
- unsigned short uport;\r
- WORD wVersionRequested;\r
- WSADATA wsaData;\r
-\r
- /* Initialize socket DLL */\r
- wVersionRequested = MAKEWORD(1, 1);\r
- err = WSAStartup(wVersionRequested, &wsaData);\r
- if (err != 0) return err;\r
-\r
- /* Make socket */\r
- if ((s = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {\r
- err = WSAGetLastError();\r
- WSACleanup();\r
- return err;\r
- }\r
-\r
- /* Bind local address using (mostly) don't-care values.\r
- */\r
- memset((char *) &mysa, 0, sizeof(struct sockaddr_in));\r
- mysa.sin_family = AF_INET;\r
- mysa.sin_addr.s_addr = INADDR_ANY;\r
- uport = (unsigned short) 0;\r
- mysa.sin_port = htons(uport);\r
- if (bind(s, (struct sockaddr *) &mysa, sizeof(struct sockaddr_in))\r
- == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- WSACleanup();\r
- return err;\r
- }\r
-\r
- /* Resolve remote host name */\r
- memset((char *) &sa, 0, sizeof(struct sockaddr_in));\r
- if (!(hp = gethostbyname(host))) {\r
- unsigned int b0, b1, b2, b3;\r
-\r
- err = WSAGetLastError();\r
-\r
- if (sscanf(host, "%u.%u.%u.%u", &b0, &b1, &b2, &b3) == 4) {\r
- hp = (struct hostent *) calloc(1, sizeof(struct hostent));\r
- hp->h_addrtype = AF_INET;\r
- hp->h_length = 4;\r
- hp->h_addr_list = (char **) calloc(2, sizeof(char *));\r
- hp->h_addr_list[0] = (char *) malloc(4);\r
- hp->h_addr_list[0][0] = (char) b0;\r
- hp->h_addr_list[0][1] = (char) b1;\r
- hp->h_addr_list[0][2] = (char) b2;\r
- hp->h_addr_list[0][3] = (char) b3;\r
- } else {\r
- WSACleanup();\r
- return err;\r
- }\r
- }\r
- sa.sin_family = hp->h_addrtype;\r
- uport = (unsigned short) atoi(port);\r
- sa.sin_port = htons(uport);\r
- memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);\r
-\r
- /* Make connection */\r
- if (connect(s, (struct sockaddr *) &sa,\r
- sizeof(struct sockaddr_in)) == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- WSACleanup();\r
- return err;\r
- }\r
-\r
- /* Prepare return value */\r
- cp = (ChildProc *) calloc(1, sizeof(ChildProc));\r
- cp->kind = CPSock;\r
- cp->sock = s;\r
- *pr = (ProcRef *) cp;\r
-\r
- return NO_ERROR;\r
-}\r
-\r
-int\r
-OpenCommPort(char *name, ProcRef *pr)\r
-{\r
- HANDLE h;\r
- COMMTIMEOUTS ct;\r
- ChildProc *cp;\r
- char fullname[MSG_SIZ];\r
-\r
- if (*name != '\\')\r
- snprintf(fullname, MSG_SIZ, "\\\\.\\%s", name);\r
- else\r
- safeStrCpy(fullname, name, sizeof(fullname)/sizeof(fullname[0]) );\r
-\r
- h = CreateFile(name, GENERIC_READ | GENERIC_WRITE,\r
- 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);\r
- if (h == (HANDLE) -1) {\r
- return GetLastError();\r
- }\r
- hCommPort = h;\r
-\r
- if (!SetCommState(h, (LPDCB) &dcb)) return GetLastError();\r
-\r
- /* Accumulate characters until a 100ms pause, then parse */\r
- ct.ReadIntervalTimeout = 100;\r
- ct.ReadTotalTimeoutMultiplier = 0;\r
- ct.ReadTotalTimeoutConstant = 0;\r
- ct.WriteTotalTimeoutMultiplier = 0;\r
- ct.WriteTotalTimeoutConstant = 0;\r
- if (!SetCommTimeouts(h, (LPCOMMTIMEOUTS) &ct)) return GetLastError();\r
-\r
- /* Prepare return value */\r
- cp = (ChildProc *) calloc(1, sizeof(ChildProc));\r
- cp->kind = CPComm;\r
- cp->hFrom = h;\r
- cp->hTo = h;\r
- *pr = (ProcRef *) cp;\r
-\r
- return NO_ERROR;\r
-}\r
-\r
-int\r
-OpenLoopback(ProcRef *pr)\r
-{\r
- DisplayFatalError(_("Not implemented"), 0, 1);\r
- return NO_ERROR;\r
-}\r
-\r
-\r
-int\r
-OpenRcmd(char* host, char* user, char* cmd, ProcRef* pr)\r
-{\r
- ChildProc *cp;\r
- int err;\r
- SOCKET s, s2, s3;\r
- struct sockaddr_in sa, mysa;\r
- struct hostent FAR *hp;\r
- unsigned short uport;\r
- WORD wVersionRequested;\r
- WSADATA wsaData;\r
- int fromPort;\r
- char stderrPortStr[MSG_SIZ];\r
-\r
- /* Initialize socket DLL */\r
- wVersionRequested = MAKEWORD(1, 1);\r
- err = WSAStartup(wVersionRequested, &wsaData);\r
- if (err != 0) return err;\r
-\r
- /* Resolve remote host name */\r
- memset((char *) &sa, 0, sizeof(struct sockaddr_in));\r
- if (!(hp = gethostbyname(host))) {\r
- unsigned int b0, b1, b2, b3;\r
-\r
- err = WSAGetLastError();\r
-\r
- if (sscanf(host, "%u.%u.%u.%u", &b0, &b1, &b2, &b3) == 4) {\r
- hp = (struct hostent *) calloc(1, sizeof(struct hostent));\r
- hp->h_addrtype = AF_INET;\r
- hp->h_length = 4;\r
- hp->h_addr_list = (char **) calloc(2, sizeof(char *));\r
- hp->h_addr_list[0] = (char *) malloc(4);\r
- hp->h_addr_list[0][0] = (char) b0;\r
- hp->h_addr_list[0][1] = (char) b1;\r
- hp->h_addr_list[0][2] = (char) b2;\r
- hp->h_addr_list[0][3] = (char) b3;\r
- } else {\r
- WSACleanup();\r
- return err;\r
- }\r
- }\r
- sa.sin_family = hp->h_addrtype;\r
- uport = (unsigned short) 514;\r
- sa.sin_port = htons(uport);\r
- memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);\r
-\r
- /* Bind local socket to unused "privileged" port address\r
- */\r
- s = INVALID_SOCKET;\r
- memset((char *) &mysa, 0, sizeof(struct sockaddr_in));\r
- mysa.sin_family = AF_INET;\r
- mysa.sin_addr.s_addr = INADDR_ANY;\r
- for (fromPort = 1023;; fromPort--) {\r
- if (fromPort < 0) {\r
- WSACleanup();\r
- return WSAEADDRINUSE;\r
- }\r
- if (s == INVALID_SOCKET) {\r
- if ((s = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {\r
- err = WSAGetLastError();\r
- WSACleanup();\r
- return err;\r
- }\r
- }\r
- uport = (unsigned short) fromPort;\r
- mysa.sin_port = htons(uport);\r
- if (bind(s, (struct sockaddr *) &mysa, sizeof(struct sockaddr_in))\r
- == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- if (err == WSAEADDRINUSE) continue;\r
- WSACleanup();\r
- return err;\r
- }\r
- if (connect(s, (struct sockaddr *) &sa,\r
- sizeof(struct sockaddr_in)) == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- if (err == WSAEADDRINUSE) {\r
- closesocket(s);\r
- s = -1;\r
- continue;\r
- }\r
- WSACleanup();\r
- return err;\r
- }\r
- break;\r
- }\r
-\r
- /* Bind stderr local socket to unused "privileged" port address\r
- */\r
- s2 = INVALID_SOCKET;\r
- memset((char *) &mysa, 0, sizeof(struct sockaddr_in));\r
- mysa.sin_family = AF_INET;\r
- mysa.sin_addr.s_addr = INADDR_ANY;\r
- for (fromPort = 1023;; fromPort--) {\r
- if (fromPort == prevStderrPort) continue; // don't reuse port\r
- if (fromPort < 0) {\r
- (void) closesocket(s);\r
- WSACleanup();\r
- return WSAEADDRINUSE;\r
- }\r
- if (s2 == INVALID_SOCKET) {\r
- if ((s2 = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {\r
- err = WSAGetLastError();\r
- closesocket(s);\r
- WSACleanup();\r
- return err;\r
- }\r
- }\r
- uport = (unsigned short) fromPort;\r
- mysa.sin_port = htons(uport);\r
- if (bind(s2, (struct sockaddr *) &mysa, sizeof(struct sockaddr_in))\r
- == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- if (err == WSAEADDRINUSE) continue;\r
- (void) closesocket(s);\r
- WSACleanup();\r
- return err;\r
- }\r
- if (listen(s2, 1) == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- if (err == WSAEADDRINUSE) {\r
- closesocket(s2);\r
- s2 = INVALID_SOCKET;\r
- continue;\r
- }\r
- (void) closesocket(s);\r
- (void) closesocket(s2);\r
- WSACleanup();\r
- return err;\r
- }\r
- break;\r
- }\r
- prevStderrPort = fromPort; // remember port used\r
- snprintf(stderrPortStr, MSG_SIZ, "%d", fromPort);\r
-\r
- if (send(s, stderrPortStr, strlen(stderrPortStr) + 1, 0) == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- (void) closesocket(s);\r
- (void) closesocket(s2);\r
- WSACleanup();\r
- return err;\r
- }\r
-\r
- if (send(s, UserName(), strlen(UserName()) + 1, 0) == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- (void) closesocket(s);\r
- (void) closesocket(s2);\r
- WSACleanup();\r
- return err;\r
- }\r
- if (*user == NULLCHAR) user = UserName();\r
- if (send(s, user, strlen(user) + 1, 0) == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- (void) closesocket(s);\r
- (void) closesocket(s2);\r
- WSACleanup();\r
- return err;\r
- }\r
- if (send(s, cmd, strlen(cmd) + 1, 0) == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- (void) closesocket(s);\r
- (void) closesocket(s2);\r
- WSACleanup();\r
- return err;\r
- }\r
-\r
- if ((s3 = accept(s2, NULL, NULL)) == INVALID_SOCKET) {\r
- err = WSAGetLastError();\r
- (void) closesocket(s);\r
- (void) closesocket(s2);\r
- WSACleanup();\r
- return err;\r
- }\r
- (void) closesocket(s2); /* Stop listening */\r
-\r
- /* Prepare return value */\r
- cp = (ChildProc *) calloc(1, sizeof(ChildProc));\r
- cp->kind = CPRcmd;\r
- cp->sock = s;\r
- cp->sock2 = s3;\r
- *pr = (ProcRef *) cp;\r
-\r
- return NO_ERROR;\r
-}\r
-\r
-\r
-InputSourceRef\r
-AddInputSource(ProcRef pr, int lineByLine,\r
- InputCallback func, VOIDSTAR closure)\r
-{\r
- InputSource *is, *is2 = NULL;\r
- ChildProc *cp = (ChildProc *) pr;\r
-\r
- is = (InputSource *) calloc(1, sizeof(InputSource));\r
- is->lineByLine = lineByLine;\r
- is->func = func;\r
- is->closure = closure;\r
- is->second = NULL;\r
- is->next = is->buf;\r
- if (pr == NoProc) {\r
- is->kind = CPReal;\r
- consoleInputSource = is;\r
- } else {\r
- is->kind = cp->kind;\r
- /* \r
- [AS] Try to avoid a race condition if the thread is given control too early:\r
- we create all threads suspended so that the is->hThread variable can be\r
- safely assigned, then let the threads start with ResumeThread.\r
- */\r
- switch (cp->kind) {\r
- case CPReal:\r
- is->hFile = cp->hFrom;\r
- cp->hFrom = NULL; /* now owned by InputThread */\r
- is->hThread =\r
- CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) NonOvlInputThread,\r
- (LPVOID) is, CREATE_SUSPENDED, &is->id);\r
- break;\r
-\r
- case CPComm:\r
- is->hFile = cp->hFrom;\r
- cp->hFrom = NULL; /* now owned by InputThread */\r
- is->hThread =\r
- CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) InputThread,\r
- (LPVOID) is, CREATE_SUSPENDED, &is->id);\r
- break;\r
-\r
- case CPSock:\r
- is->sock = cp->sock;\r
- is->hThread =\r
- CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SocketInputThread,\r
- (LPVOID) is, CREATE_SUSPENDED, &is->id);\r
- break;\r
-\r
- case CPRcmd:\r
- is2 = (InputSource *) calloc(1, sizeof(InputSource));\r
- *is2 = *is;\r
- is->sock = cp->sock;\r
- is->second = is2;\r
- is2->sock = cp->sock2;\r
- is2->second = is2;\r
- is->hThread =\r
- CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SocketInputThread,\r
- (LPVOID) is, CREATE_SUSPENDED, &is->id);\r
- is2->hThread =\r
- CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SocketInputThread,\r
- (LPVOID) is2, CREATE_SUSPENDED, &is2->id);\r
- break;\r
- }\r
-\r
- if( is->hThread != NULL ) {\r
- ResumeThread( is->hThread );\r
- }\r
-\r
- if( is2 != NULL && is2->hThread != NULL ) {\r
- ResumeThread( is2->hThread );\r
- }\r
- }\r
-\r
- return (InputSourceRef) is;\r
-}\r
-\r
-void\r
-RemoveInputSource(InputSourceRef isr)\r
-{\r
- InputSource *is;\r
-\r
- is = (InputSource *) isr;\r
- is->hThread = NULL; /* tell thread to stop */\r
- CloseHandle(is->hThread);\r
- if (is->second != NULL) {\r
- is->second->hThread = NULL;\r
- CloseHandle(is->second->hThread);\r
- }\r
-}\r
-\r
-int no_wrap(char *message, int count)\r
-{\r
- ConsoleOutput(message, count, FALSE);\r
- return count;\r
-}\r
-\r
-int\r
-OutputToProcess(ProcRef pr, char *message, int count, int *outError)\r
-{\r
- DWORD dOutCount;\r
- int outCount = SOCKET_ERROR;\r
- ChildProc *cp = (ChildProc *) pr;\r
- static OVERLAPPED ovl;\r
-\r
- static int line = 0;\r
-\r
- if (pr == NoProc)\r
- {\r
- if (appData.noJoin || !appData.useInternalWrap)\r
- return no_wrap(message, count);\r
- else\r
- {\r
- int width = get_term_width();\r
- int len = wrap(NULL, message, count, width, &line);\r
- char *msg = malloc(len);\r
- int dbgchk;\r
-\r
- if (!msg)\r
- return no_wrap(message, count);\r
- else\r
- {\r
- dbgchk = wrap(msg, message, count, width, &line);\r
- if (dbgchk != len && appData.debugMode)\r
- fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len);\r
- ConsoleOutput(msg, len, FALSE);\r
- free(msg);\r
- return len;\r
- }\r
- }\r
- }\r
-\r
- if (ovl.hEvent == NULL) {\r
- ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);\r
- }\r
- ovl.Internal = ovl.InternalHigh = ovl.Offset = ovl.OffsetHigh = 0;\r
-\r
- switch (cp->kind) {\r
- case CPSock:\r
- case CPRcmd:\r
- outCount = send(cp->sock, message, count, 0);\r
- if (outCount == SOCKET_ERROR) {\r
- *outError = WSAGetLastError();\r
- } else {\r
- *outError = NO_ERROR;\r
- }\r
- break;\r
-\r
- case CPReal:\r
- if (WriteFile(((ChildProc *)pr)->hTo, message, count,\r
- &dOutCount, NULL)) {\r
- *outError = NO_ERROR;\r
- outCount = (int) dOutCount;\r
- } else {\r
- *outError = GetLastError();\r
- }\r
- break;\r
-\r
- case CPComm:\r
- *outError = DoWriteFile(((ChildProc *)pr)->hTo, message, count,\r
- &dOutCount, &ovl);\r
- if (*outError == NO_ERROR) {\r
- outCount = (int) dOutCount;\r
- }\r
- break;\r
- }\r
- return outCount;\r
-}\r
-\r
-void\r
-DoSleep(int n)\r
-{\r
- if(n != 0) Sleep(n);\r
-}\r
-\r
-int\r
-OutputToProcessDelayed(ProcRef pr, char *message, int count, int *outError,\r
- long msdelay)\r
-{\r
- /* Ignore delay, not implemented for WinBoard */\r
- return OutputToProcess(pr, message, count, outError);\r
-}\r
-\r
-\r
-void\r
-CmailSigHandlerCallBack(InputSourceRef isr, VOIDSTAR closure,\r
- char *buf, int count, int error)\r
-{\r
- DisplayFatalError(_("Not implemented"), 0, 1);\r
-}\r
-\r
-/* see wgamelist.c for Game List functions */\r
-/* see wedittags.c for Edit Tags functions */\r
-\r
-\r
-int\r
-ICSInitScript()\r
-{\r
- FILE *f;\r
- char buf[MSG_SIZ];\r
- char *dummy;\r
-\r
- if (SearchPath(installDir, appData.icsLogon, NULL, MSG_SIZ, buf, &dummy)) {\r
- f = fopen(buf, "r");\r
- if (f != NULL) {\r
- ProcessICSInitScript(f);\r
- fclose(f);\r
- return TRUE;\r
- }\r
- }\r
- return FALSE;\r
-}\r
-\r
-\r
-VOID\r
-StartAnalysisClock()\r
-{\r
- if (analysisTimerEvent) return;\r
- analysisTimerEvent = SetTimer(hwndMain, (UINT) ANALYSIS_TIMER_ID,\r
- (UINT) 2000, NULL);\r
-}\r
-\r
-VOID\r
-SetHighlights(int fromX, int fromY, int toX, int toY)\r
-{\r
- highlightInfo.sq[0].x = fromX;\r
- highlightInfo.sq[0].y = fromY;\r
- highlightInfo.sq[1].x = toX;\r
- highlightInfo.sq[1].y = toY;\r
-}\r
-\r
-VOID\r
-ClearHighlights()\r
-{\r
- highlightInfo.sq[0].x = highlightInfo.sq[0].y = \r
- highlightInfo.sq[1].x = highlightInfo.sq[1].y = -1;\r
-}\r
-\r
-VOID\r
-SetPremoveHighlights(int fromX, int fromY, int toX, int toY)\r
-{\r
- premoveHighlightInfo.sq[0].x = fromX;\r
- premoveHighlightInfo.sq[0].y = fromY;\r
- premoveHighlightInfo.sq[1].x = toX;\r
- premoveHighlightInfo.sq[1].y = toY;\r
-}\r
-\r
-VOID\r
-ClearPremoveHighlights()\r
-{\r
- premoveHighlightInfo.sq[0].x = premoveHighlightInfo.sq[0].y = \r
- premoveHighlightInfo.sq[1].x = premoveHighlightInfo.sq[1].y = -1;\r
-}\r
-\r
-VOID\r
-ShutDownFrontEnd()\r
-{\r
- if (saveSettingsOnExit) SaveSettings(settingsFileName);\r
- DeleteClipboardTempFiles();\r
-}\r
-\r
-void\r
-BoardToTop()\r
-{\r
- if (IsIconic(hwndMain))\r
- ShowWindow(hwndMain, SW_RESTORE);\r
-\r
- SetActiveWindow(hwndMain);\r
-}\r
-\r
-/*\r
- * Prototypes for animation support routines\r
- */\r
-static void ScreenSquare(int column, int row, POINT * pt);\r
-static void Tween( POINT * start, POINT * mid, POINT * finish, int factor,\r
- POINT frames[], int * nFrames);\r
-\r
-\r
-#define kFactor 4\r
-\r
-void\r
-AnimateAtomicCapture(Board board, int fromX, int fromY, int toX, int toY)\r
-{ // [HGM] atomic: animate blast wave\r
- int i;\r
-\r
- explodeInfo.fromX = fromX;\r
- explodeInfo.fromY = fromY;\r
- explodeInfo.toX = toX;\r
- explodeInfo.toY = toY;\r
- for(i=1; i<4*kFactor; i++) {\r
- explodeInfo.radius = (i*180)/(4*kFactor-1);\r
- DrawPosition(FALSE, board);\r
- Sleep(appData.animSpeed);\r
- }\r
- explodeInfo.radius = 0;\r
- DrawPosition(TRUE, board);\r
-}\r
-\r
-void\r
-AnimateMove(board, fromX, fromY, toX, toY)\r
- Board board;\r
- int fromX;\r
- int fromY;\r
- int toX;\r
- int toY;\r
-{\r
- ChessSquare piece, victim = EmptySquare, victim2 = EmptySquare;\r
- int x = toX, y = toY, x2 = kill2X;\r
- POINT start, finish, mid;\r
- POINT frames[kFactor * 2 + 1];\r
- int nFrames, n;\r
-\r
- if(killX >= 0 && IS_LION(board[fromY][fromX])) Roar();\r
-\r
- if (!appData.animate) return;\r
- if (doingSizing) return;\r
- if (fromY < 0 || fromX < 0) return;\r
- piece = board[fromY][fromX];\r
- if (piece >= EmptySquare) return;\r
-\r
- if(x2 >= 0) toX = kill2X, toY = kill2Y, victim = board[killY][killX], victim2 = board[kill2Y][kill2X]; else\r
- if(killX >= 0) toX = killX, toY = killY, victim = board[killY][killX]; // [HGM] lion: first to kill square\r
-\r
- animInfo.from.x = fromX;\r
- animInfo.from.y = fromY;\r
-\r
-again:\r
-\r
- ScreenSquare(fromX, fromY, &start);\r
- ScreenSquare(toX, toY, &finish);\r
-\r
- /* All moves except knight jumps move in straight line */\r
- if (!(abs(fromX-toX) == 1 && abs(fromY-toY) == 2 || abs(fromX-toX) == 2 && abs(fromY-toY) == 1)) {\r
- mid.x = start.x + (finish.x - start.x) / 2;\r
- mid.y = start.y + (finish.y - start.y) / 2;\r
- } else {\r
- /* Knight: make straight movement then diagonal */\r
- if (abs(toY - fromY) < abs(toX - fromX)) {\r
- mid.x = start.x + (finish.x - start.x) / 2;\r
- mid.y = start.y;\r
- } else {\r
- mid.x = start.x;\r
- mid.y = start.y + (finish.y - start.y) / 2;\r
- }\r
- }\r
- \r
- /* Don't use as many frames for very short moves */\r
- if (abs(toY - fromY) + abs(toX - fromX) <= 2)\r
- Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);\r
- else\r
- Tween(&start, &mid, &finish, kFactor, frames, &nFrames);\r
-\r
- animInfo.to.x = toX;\r
- animInfo.to.y = toY;\r
- animInfo.lastpos = start;\r
- animInfo.piece = piece;\r
- for (n = 0; n < nFrames; n++) {\r
- animInfo.pos = frames[n];\r
- DrawPosition(FALSE, board);\r
- animInfo.lastpos = animInfo.pos;\r
- Sleep(appData.animSpeed);\r
- }\r
- animInfo.pos = finish;\r
- DrawPosition(FALSE, board);\r
-\r
- if(toX == x2 && toY == kill2Y) {\r
- fromX = toX; fromY = toY; toX = killX; toY = killY; x2 = -1;\r
- board[kill2Y][kill2X] = EmptySquare; goto again;\r
- } // second leg\r
- if(toX != x || toY != y) {\r
- fromX = toX; fromY = toY; toX = x; toY = y;\r
- board[killY][killX] = EmptySquare; goto again;\r
- } // second leg\r
-\r
-if(victim2 != EmptySquare) board[kill2Y][kill2X] = victim2;\r
-if(victim != EmptySquare) board[killY][killX] = victim;\r
-\r
- animInfo.piece = EmptySquare;\r
- Explode(board, fromX, fromY, toX, toY);\r
-}\r
-\r
-/* Convert board position to corner of screen rect and color */\r
-\r
-static void\r
-ScreenSquare(column, row, pt)\r
- int column; int row; POINT * pt;\r
-{\r
- if (flipView) {\r
- pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap) + border;\r
- pt->y = lineGap + row * (squareSize + lineGap) + border;\r
- } else {\r
- pt->x = lineGap + column * (squareSize + lineGap) + border;\r
- pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap) + border;\r
- }\r
-}\r
-\r
-/* Generate a series of frame coords from start->mid->finish.\r
- The movement rate doubles until the half way point is\r
- reached, then halves back down to the final destination,\r
- which gives a nice slow in/out effect. The algorithmn\r
- may seem to generate too many intermediates for short\r
- moves, but remember that the purpose is to attract the\r
- viewers attention to the piece about to be moved and\r
- then to where it ends up. Too few frames would be less\r
- noticeable. */\r
-\r
-static void\r
-Tween(start, mid, finish, factor, frames, nFrames)\r
- POINT * start; POINT * mid;\r
- POINT * finish; int factor;\r
- POINT frames[]; int * nFrames;\r
-{\r
- int n, fraction = 1, count = 0;\r
-\r
- /* Slow in, stepping 1/16th, then 1/8th, ... */\r
- for (n = 0; n < factor; n++)\r
- fraction *= 2;\r
- for (n = 0; n < factor; n++) {\r
- frames[count].x = start->x + (mid->x - start->x) / fraction;\r
- frames[count].y = start->y + (mid->y - start->y) / fraction;\r
- count ++;\r
- fraction = fraction / 2;\r
- }\r
- \r
- /* Midpoint */\r
- frames[count] = *mid;\r
- count ++;\r
- \r
- /* Slow out, stepping 1/2, then 1/4, ... */\r
- fraction = 2;\r
- for (n = 0; n < factor; n++) {\r
- frames[count].x = finish->x - (finish->x - mid->x) / fraction;\r
- frames[count].y = finish->y - (finish->y - mid->y) / fraction;\r
- count ++;\r
- fraction = fraction * 2;\r
- }\r
- *nFrames = count;\r
-}\r
-\r
-void\r
-SettingsPopUp(ChessProgramState *cps)\r
-{ // [HGM] wrapper needed because handles must not be passed through back-end\r
- EngineOptionsPopup(savedHwnd, cps);\r
-}\r
-\r
-int flock(int fid, int code)\r
-{\r
- HANDLE hFile = (HANDLE) _get_osfhandle(fid);\r
- OVERLAPPED ov;\r
- ov.hEvent = NULL;\r
- ov.Offset = 0;\r
- ov.OffsetHigh = 0;\r
- switch(code) {\r
- case 1: LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, 1024, 0, &ov); break; // LOCK_SH\r
-\r
- case 2: LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, 1024, 0, &ov); break; // LOCK_EX\r
- case 3: UnlockFileEx(hFile, 0, 1024, 0, &ov); break; // LOCK_UN\r
- default: return -1;\r
- }\r
- return 0;\r
-}\r
-\r
-char *\r
-Col2Text (int n)\r
-{\r
- static int i=0;\r
- static char col[8][20];\r
- COLORREF color = *(COLORREF *) colorVariable[n];\r
- i = i+1 & 7;\r
- snprintf(col[i], 20, "#%02lx%02lx%02lx", color&0xff, (color>>8)&0xff, (color>>16)&0xff);\r
- return col[i];\r
-}\r
-\r
-void\r
-ActivateTheme (int new)\r
-{ // Redo initialization of features depending on options that can occur in themes\r
- InitTextures();\r
- if(new) InitDrawingColors();\r
- fontBitmapSquareSize = 0; // request creation of new font pieces\r
- InitDrawingSizes(boardSize, 0);\r
- InvalidateRect(hwndMain, NULL, TRUE);\r
-}\r