PageRenderTime 69ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/winboard/winboard.c

#
C | 1811 lines | 1509 code | 172 blank | 130 comment | 237 complexity | fcca44cd368835cd3a7213560b114829 MD5 | raw file
Possible License(s): GPL-3.0, MPL-2.0-no-copyleft-exception

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * WinBoard.c -- Windows NT front end to XBoard
  3. *
  4. * Copyright 1991 by Digital Equipment Corporation, Maynard,
  5. * Massachusetts.
  6. *
  7. * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
  8. * 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
  9. *
  10. * Enhancements Copyright 2005 Alessandro Scotti
  11. *
  12. * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,
  13. * which was written and is copyrighted by Wayne Christopher.
  14. *
  15. * The following terms apply to Digital Equipment Corporation's copyright
  16. * interest in XBoard:
  17. * ------------------------------------------------------------------------
  18. * All Rights Reserved
  19. *
  20. * Permission to use, copy, modify, and distribute this software and its
  21. * documentation for any purpose and without fee is hereby granted,
  22. * provided that the above copyright notice appear in all copies and that
  23. * both that copyright notice and this permission notice appear in
  24. * supporting documentation, and that the name of Digital not be
  25. * used in advertising or publicity pertaining to distribution of the
  26. * software without specific, written prior permission.
  27. *
  28. * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  29. * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  30. * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  31. * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  32. * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  33. * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  34. * SOFTWARE.
  35. * ------------------------------------------------------------------------
  36. *
  37. * The following terms apply to the enhanced version of XBoard
  38. * distributed by the Free Software Foundation:
  39. * ------------------------------------------------------------------------
  40. *
  41. * GNU XBoard is free software: you can redistribute it and/or modify
  42. * it under the terms of the GNU General Public License as published by
  43. * the Free Software Foundation, either version 3 of the License, or (at
  44. * your option) any later version.
  45. *
  46. * GNU XBoard is distributed in the hope that it will be useful, but
  47. * WITHOUT ANY WARRANTY; without even the implied warranty of
  48. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  49. * General Public License for more details.
  50. *
  51. * You should have received a copy of the GNU General Public License
  52. * along with this program. If not, see http://www.gnu.org/licenses/. *
  53. *
  54. *------------------------------------------------------------------------
  55. ** See the file ChangeLog for a revision history. */
  56. #include "config.h"
  57. #include <windows.h>
  58. #include <winuser.h>
  59. #include <winsock.h>
  60. #include <commctrl.h>
  61. #include <stdio.h>
  62. #include <stdlib.h>
  63. #include <time.h>
  64. #include <malloc.h>
  65. #include <sys/stat.h>
  66. #include <fcntl.h>
  67. #include <math.h>
  68. #include <commdlg.h>
  69. #include <dlgs.h>
  70. #include <richedit.h>
  71. #include <mmsystem.h>
  72. #include <ctype.h>
  73. #include <io.h>
  74. #if __GNUC__
  75. #include <errno.h>
  76. #include <string.h>
  77. #endif
  78. #include "common.h"
  79. #include "frontend.h"
  80. #include "backend.h"
  81. #include "winboard.h"
  82. #include "moves.h"
  83. #include "wclipbrd.h"
  84. #include "woptions.h"
  85. #include "wsockerr.h"
  86. #include "defaults.h"
  87. #include "help.h"
  88. #include "wsnap.h"
  89. //void InitEngineUCI( const char * iniDir, ChessProgramState * cps );
  90. int myrandom(void);
  91. void mysrandom(unsigned int seed);
  92. extern int whiteFlag, blackFlag;
  93. Boolean flipClock = FALSE;
  94. extern HANDLE chatHandle[];
  95. extern int ics_type;
  96. int MySearchPath P((char *installDir, char *name, char *fullname));
  97. int MyGetFullPathName P((char *name, char *fullname));
  98. void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);
  99. VOID NewVariantPopup(HWND hwnd);
  100. int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,
  101. /*char*/int promoChar));
  102. void DisplayMove P((int moveNumber));
  103. Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen));
  104. void ChatPopUp P((char *s));
  105. typedef struct {
  106. ChessSquare piece;
  107. POINT pos; /* window coordinates of current pos */
  108. POINT lastpos; /* window coordinates of last pos - used for clipping */
  109. POINT from; /* board coordinates of the piece's orig pos */
  110. POINT to; /* board coordinates of the piece's new pos */
  111. } AnimInfo;
  112. static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };
  113. typedef struct {
  114. POINT start; /* window coordinates of start pos */
  115. POINT pos; /* window coordinates of current pos */
  116. POINT lastpos; /* window coordinates of last pos - used for clipping */
  117. POINT from; /* board coordinates of the piece's orig pos */
  118. ChessSquare piece;
  119. } DragInfo;
  120. static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, EmptySquare };
  121. typedef struct {
  122. POINT sq[2]; /* board coordinates of from, to squares */
  123. } HighlightInfo;
  124. static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} };
  125. static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };
  126. static HighlightInfo partnerHighlightInfo = { {{-1, -1}, {-1, -1}} };
  127. static HighlightInfo oldPartnerHighlight = { {{-1, -1}, {-1, -1}} };
  128. typedef struct { // [HGM] atomic
  129. int fromX, fromY, toX, toY, radius;
  130. } ExplodeInfo;
  131. static ExplodeInfo explodeInfo;
  132. /* Window class names */
  133. char szAppName[] = "WinBoard";
  134. char szConsoleName[] = "WBConsole";
  135. /* Title bar text */
  136. char szTitle[] = "WinBoard";
  137. char szConsoleTitle[] = "I C S Interaction";
  138. char *programName;
  139. char *settingsFileName;
  140. Boolean saveSettingsOnExit;
  141. char installDir[MSG_SIZ];
  142. int errorExitStatus;
  143. BoardSize boardSize;
  144. Boolean chessProgram;
  145. //static int boardX, boardY;
  146. int minX, minY; // [HGM] placement: volatile limits on upper-left corner
  147. int squareSize, lineGap, minorSize;
  148. static int winW, winH;
  149. static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo
  150. static int logoHeight = 0;
  151. static char messageText[MESSAGE_TEXT_MAX];
  152. static int clockTimerEvent = 0;
  153. static int loadGameTimerEvent = 0;
  154. static int analysisTimerEvent = 0;
  155. static DelayedEventCallback delayedTimerCallback;
  156. static int delayedTimerEvent = 0;
  157. static int buttonCount = 2;
  158. char *icsTextMenuString;
  159. char *icsNames;
  160. char *firstChessProgramNames;
  161. char *secondChessProgramNames;
  162. #define PALETTESIZE 256
  163. HINSTANCE hInst; /* current instance */
  164. Boolean alwaysOnTop = FALSE;
  165. RECT boardRect;
  166. COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
  167. blackPieceColor, highlightSquareColor, premoveHighlightColor;
  168. HPALETTE hPal;
  169. ColorClass currentColorClass;
  170. static HWND savedHwnd;
  171. HWND hCommPort = NULL; /* currently open comm port */
  172. static HWND hwndPause; /* pause button */
  173. static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */
  174. static HBRUSH lightSquareBrush, darkSquareBrush,
  175. blackSquareBrush, /* [HGM] for band between board and holdings */
  176. explodeBrush, /* [HGM] atomic */
  177. markerBrush, /* [HGM] markers */
  178. whitePieceBrush, blackPieceBrush, iconBkgndBrush /*, outlineBrush*/;
  179. static POINT gridEndpoints[(BOARD_RANKS + BOARD_FILES + 2) * 2];
  180. static DWORD gridVertexCounts[BOARD_RANKS + BOARD_FILES + 2];
  181. static HPEN gridPen = NULL;
  182. static HPEN highlightPen = NULL;
  183. static HPEN premovePen = NULL;
  184. static NPLOGPALETTE pLogPal;
  185. static BOOL paletteChanged = FALSE;
  186. static HICON iconWhite, iconBlack, iconCurrent;
  187. static int doingSizing = FALSE;
  188. static int lastSizing = 0;
  189. static int prevStderrPort;
  190. static HBITMAP userLogo;
  191. static HBITMAP liteBackTexture = NULL;
  192. static HBITMAP darkBackTexture = NULL;
  193. static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
  194. static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
  195. static int backTextureSquareSize = 0;
  196. static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_RANKS][BOARD_FILES];
  197. #if __GNUC__ && !defined(_winmajor)
  198. #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */
  199. #else
  200. #if defined(_winmajor)
  201. #define oldDialog (_winmajor < 4)
  202. #else
  203. #define oldDialog 0
  204. #endif
  205. #endif
  206. #define INTERNATIONAL
  207. #ifdef INTERNATIONAL
  208. # define _(s) T_(s)
  209. # define N_(s) s
  210. #else
  211. # define _(s) s
  212. # define N_(s) s
  213. # define T_(s) s
  214. # define Translate(x, y)
  215. # define LoadLanguageFile(s)
  216. #endif
  217. #ifdef INTERNATIONAL
  218. Boolean barbaric; // flag indicating if translation is needed
  219. // list of item numbers used in each dialog (used to alter language at run time)
  220. #define ABOUTBOX -1 /* not sure why these are needed */
  221. #define ABOUTBOX2 -1
  222. int dialogItems[][42] = {
  223. { ABOUTBOX, IDOK, OPT_MESS, 400 },
  224. { DLG_TimeControl, IDC_Babble, OPT_TCUseMoves, OPT_TCUseInc, OPT_TCUseFixed,
  225. OPT_TCtext1, OPT_TCtext2, OPT_TCitext1, OPT_TCitext2, OPT_TCftext, GPB_Factors, IDC_Factor1, IDC_Factor2, IDOK, IDCANCEL },
  226. { DLG_LoadOptions, OPT_Autostep, OPT_AStext1, OPT_Exact, OPT_Subset, OPT_Struct, OPT_Material, OPT_Range, OPT_Difference,
  227. OPT_elo1t, OPT_elo2t, OPT_datet, OPT_Stretch, OPT_Stretcht, OPT_Reversed, OPT_SearchMode, OPT_Mirror, OPT_thresholds, IDOK, IDCANCEL },
  228. { DLG_SaveOptions, OPT_Autosave, OPT_AVPrompt, OPT_AVToFile, OPT_AVBrowse,
  229. 801, OPT_PGN, OPT_Old, OPT_OutOfBookInfo, IDOK, IDCANCEL },
  230. { 1536, 1090, IDC_Directories, 1089, 1091, IDOK, IDCANCEL, 1038, IDC_IndexNr, 1037 },
  231. { DLG_CommPort, IDOK, IDCANCEL, IDC_Port, IDC_Rate, IDC_Bits, IDC_Parity,
  232. IDC_Stop, IDC_Flow, OPT_SerialHelp },
  233. { DLG_EditComment, IDOK, OPT_CancelComment, OPT_ClearComment, OPT_EditComment },
  234. { DLG_PromotionKing, PB_Chancellor, PB_Archbishop, PB_Queen, PB_Rook,
  235. PB_Bishop, PB_Knight, PB_King, IDCANCEL, IDC_Yes, IDC_No, IDC_Centaur },
  236. { ABOUTBOX2, IDC_ChessBoard },
  237. { DLG_GameList, OPT_GameListLoad, OPT_GameListPrev, OPT_GameListNext,
  238. OPT_GameListClose, IDC_GameListDoFilter },
  239. { DLG_EditTags, IDOK, OPT_TagsCancel, OPT_EditTags },
  240. { DLG_Error, IDOK },
  241. { DLG_Colorize, IDOK, IDCANCEL, OPT_ChooseColor, OPT_Bold, OPT_Italic,
  242. OPT_Underline, OPT_Strikeout, OPT_Sample },
  243. { DLG_Question, IDOK, IDCANCEL, OPT_QuestionText },
  244. { DLG_Startup, IDC_Welcome, OPT_ChessEngine, OPT_ChessServer, OPT_View,
  245. IDC_SPECIFY_ENG_STATIC, IDC_SPECIFY_SERVER_STATIC, OPT_AnyAdditional,
  246. IDOK, IDCANCEL, IDM_HELPCONTENTS },
  247. { DLG_IndexNumber, IDC_Index },
  248. { DLG_TypeInMove, IDOK, IDCANCEL },
  249. { DLG_TypeInName, IDOK, IDCANCEL },
  250. { DLG_Sound, IDC_Event, OPT_NoSound, OPT_DefaultBeep, OPT_BuiltInSound,
  251. OPT_WavFile, OPT_BrowseSound, OPT_DefaultSounds, IDOK, IDCANCEL, OPT_PlaySound },
  252. { DLG_GeneralOptions, IDOK, IDCANCEL, OPT_AlwaysOnTop, OPT_HighlightLastMove,
  253. OPT_AlwaysQueen, OPT_PeriodicUpdates, OPT_AnimateDragging, OPT_PonderNextMove,
  254. OPT_AnimateMoving, OPT_PopupExitMessage, OPT_AutoFlag, OPT_PopupMoveErrors,
  255. OPT_AutoFlipView, OPT_ShowButtonBar, OPT_AutoRaiseBoard, OPT_ShowCoordinates,
  256. OPT_Blindfold, OPT_ShowThinking, OPT_HighlightDragging, OPT_TestLegality,
  257. OPT_SaveExtPGN, OPT_HideThinkFromHuman, OPT_ExtraInfoInMoveHistory,
  258. OPT_HighlightMoveArrow, OPT_AutoLogo ,OPT_SmartMove },
  259. { DLG_IcsOptions, IDOK, IDCANCEL, OPT_AutoComment, OPT_AutoKibitz, OPT_AutoObserve,
  260. OPT_GetMoveList, OPT_LocalLineEditing, OPT_QuietPlay, OPT_SeekGraph, OPT_AutoRefresh,
  261. OPT_BgObserve, OPT_DualBoard, OPT_Premove, OPT_PremoveWhite, OPT_PremoveBlack,
  262. OPT_SmartMove, OPT_IcsAlarm, IDC_Sec, OPT_ChooseShoutColor, OPT_ChooseSShoutColor,
  263. OPT_ChooseChannel1Color, OPT_ChooseChannelColor, OPT_ChooseKibitzColor,
  264. OPT_ChooseTellColor, OPT_ChooseChallengeColor, OPT_ChooseRequestColor,
  265. OPT_ChooseSeekColor, OPT_ChooseNormalColor, OPT_ChooseBackgroundColor,
  266. OPT_DefaultColors, OPT_DontColorize, IDC_Boxes, GPB_Colors, GPB_Premove,
  267. GPB_General, GPB_Alarm },
  268. { DLG_BoardOptions, IDOK, IDCANCEL, OPT_SizeTiny, OPT_SizeTeeny, OPT_SizeDinky,
  269. OPT_SizePetite, OPT_SizeSlim, OPT_SizeSmall, OPT_SizeMediocre, OPT_SizeMiddling,
  270. OPT_SizeAverage, OPT_SizeModerate, OPT_SizeMedium, OPT_SizeBulky, OPT_SizeLarge,
  271. OPT_SizeBig, OPT_SizeHuge, OPT_SizeGiant, OPT_SizeColossal, OPT_SizeTitanic,
  272. OPT_ChooseLightSquareColor, OPT_ChooseDarkSquareColor, OPT_ChooseWhitePieceColor,
  273. OPT_ChooseBlackPieceColor, OPT_ChooseHighlightSquareColor, OPT_ChoosePremoveHighlightColor,
  274. OPT_Monochrome, OPT_AllWhite, OPT_UpsideDown, OPT_DefaultBoardColors, GPB_Colors,
  275. IDC_Light, IDC_Dark, IDC_White, IDC_Black, IDC_High, IDC_PreHigh, GPB_Size, OPT_Bitmaps, OPT_PieceFont, OPT_Grid },
  276. { DLG_NewVariant, IDOK, IDCANCEL, OPT_VariantNormal, OPT_VariantFRC, OPT_VariantWildcastle,
  277. OPT_VariantNocastle, OPT_VariantLosers, OPT_VariantGiveaway, OPT_VariantSuicide,
  278. OPT_Variant3Check, OPT_VariantTwoKings, OPT_VariantAtomic, OPT_VariantCrazyhouse,
  279. OPT_VariantBughouse, OPT_VariantTwilight, OPT_VariantShogi, OPT_VariantSuper,
  280. OPT_VariantKnightmate, OPT_VariantBerolina, OPT_VariantCylinder, OPT_VariantFairy,
  281. OPT_VariantMakruk, OPT_VariantGothic, OPT_VariantCapablanca, OPT_VariantJanus,
  282. OPT_VariantCRC, OPT_VariantFalcon, OPT_VariantCourier, OPT_VariantGreat, OPT_VariantSChess,
  283. OPT_VariantShatranj, OPT_VariantXiangqi, GPB_Variant, GPB_Board, IDC_Height,
  284. IDC_Width, IDC_Hand, IDC_Pieces, IDC_Def },
  285. { DLG_Fonts, IDOK, IDCANCEL, OPT_ChooseClockFont, OPT_ChooseMessageFont,
  286. OPT_ChooseCoordFont, OPT_ChooseTagFont, OPT_ChooseCommentsFont, OPT_ChooseConsoleFont, OPT_ChooseMoveHistoryFont, OPT_DefaultFonts,
  287. OPT_ClockFont, OPT_MessageFont, OPT_CoordFont, OPT_EditTagsFont, OPT_ChoosePieceFont, OPT_MessageFont8,
  288. OPT_SampleGameListFont, OPT_ChooseGameListFont, OPT_MessageFont7,
  289. OPT_CommentsFont, OPT_MessageFont5, GPB_Current, GPB_All, OPT_MessageFont6 },
  290. { DLG_NewGameFRC, IDC_NFG_Label, IDC_NFG_Random, IDOK, IDCANCEL },
  291. { DLG_GameListOptions, IDC_GLT, IDC_GLT_Up, IDC_GLT_Down, IDC_GLT_Restore,
  292. IDC_GLT_Default, IDOK, IDCANCEL, IDC_GLT_RestoreTo },
  293. { DLG_MoveHistory },
  294. { DLG_EvalGraph },
  295. { DLG_EngineOutput, IDC_EngineLabel1, IDC_Engine1_NPS, IDC_EngineLabel2, IDC_Engine2_NPS },
  296. { DLG_Chat, IDC_Partner, IDC_Clear, IDC_Send, },
  297. { DLG_EnginePlayOptions, IDC_EpPonder, IDC_EpShowThinking, IDC_EpHideThinkingHuman,
  298. IDC_EpPeriodicUpdates, GPB_Adjudications, IDC_Draw, IDC_Moves, IDC_Threshold,
  299. IDC_Centi, IDC_TestClaims, IDC_DetectMates, IDC_MaterialDraws, IDC_TrivialDraws,
  300. GPB_Apply, IDC_Rule, IDC_Repeats, IDC_ScoreAbs1, IDC_ScoreAbs2, IDOK, IDCANCEL },
  301. { DLG_OptionsUCI, IDC_PolyDir, IDC_BrowseForPolyglotDir, IDC_Hash, IDC_Path,
  302. IDC_BrowseForEGTB, IDC_Cache, IDC_UseBook, IDC_BrowseForBook, IDC_CPU, IDC_OwnBook1,
  303. IDC_OwnBook2, IDC_Depth, IDC_Variation, IDC_DefGames, IDOK, IDCANCEL },
  304. { 0 }
  305. };
  306. static char languageBuf[70000], *foreign[1000], *english[1000], *languageFile[MSG_SIZ];
  307. static int lastChecked;
  308. static char oldLanguage[MSG_SIZ], *menuText[10][30];
  309. extern int tinyLayout;
  310. extern char * menuBarText[][10];
  311. void
  312. LoadLanguageFile(char *name)
  313. { //load the file with translations, and make a list of the strings to be translated, and their translations
  314. FILE *f;
  315. int i=0, j=0, n=0, k;
  316. char buf[MSG_SIZ];
  317. if(!name || name[0] == NULLCHAR) return;
  318. snprintf(buf, MSG_SIZ, "%s%s", name, strchr(name, '.') ? "" : ".lng"); // auto-append lng extension
  319. appData.language = oldLanguage;
  320. if(!strcmp(buf, oldLanguage)) { barbaric = 1; return; } // this language already loaded; just switch on
  321. if((f = fopen(buf, "r")) == NULL) return;
  322. while((k = fgetc(f)) != EOF) {
  323. if(i >= sizeof(languageBuf)) { DisplayError("Language file too big", 0); return; }
  324. languageBuf[i] = k;
  325. if(k == '\n') {
  326. if(languageBuf[n] == '"' && languageBuf[i-1] == '"') {
  327. char *p;
  328. if(p = strstr(languageBuf + n + 1, "\" === \"")) {
  329. if(p > languageBuf+n+2 && p+8 < languageBuf+i) {
  330. if(j >= sizeof(english)) { DisplayError("Too many translated strings", 0); return; }
  331. english[j] = languageBuf + n + 1; *p = 0;
  332. foreign[j++] = p + 7; languageBuf[i-1] = 0;
  333. //if(appData.debugMode) fprintf(debugFP, "translation: replace '%s' by '%s'\n", english[j-1], foreign[j-1]);
  334. }
  335. }
  336. }
  337. n = i + 1;
  338. } else if(i > 0 && languageBuf[i-1] == '\\') {
  339. switch(k) {
  340. case 'n': k = '\n'; break;
  341. case 'r': k = '\r'; break;
  342. case 't': k = '\t'; break;
  343. }
  344. languageBuf[--i] = k;
  345. }
  346. i++;
  347. }
  348. fclose(f);
  349. barbaric = (j != 0);
  350. safeStrCpy(oldLanguage, buf, sizeof(oldLanguage)/sizeof(oldLanguage[0]) );
  351. }
  352. char *
  353. T_(char *s)
  354. { // return the translation of the given string
  355. // efficiency can be improved a lot...
  356. int i=0;
  357. static char buf[MSG_SIZ];
  358. //if(appData.debugMode) fprintf(debugFP, "T_(%s)\n", s);
  359. if(!barbaric) return s;
  360. if(!s) return ""; // sanity
  361. while(english[i]) {
  362. if(!strcmp(s, english[i])) return foreign[i];
  363. if(english[i][0] == '%' && strstr(s, english[i]+1) == s) { // allow translation of strings with variable ending
  364. snprintf(buf, MSG_SIZ, "%s%s", foreign[i], s + strlen(english[i]+1)); // keep unmatched portion
  365. return buf;
  366. }
  367. i++;
  368. }
  369. return s;
  370. }
  371. void
  372. Translate(HWND hDlg, int dialogID)
  373. { // translate all text items in the given dialog
  374. int i=0, j, k;
  375. char buf[MSG_SIZ], *s;
  376. if(!barbaric) return;
  377. while(dialogItems[i][0] && dialogItems[i][0] != dialogID) i++; // find the dialog description
  378. if(dialogItems[i][0] != dialogID) return; // unknown dialog, should not happen
  379. GetWindowText( hDlg, buf, MSG_SIZ );
  380. s = T_(buf);
  381. if(strcmp(buf, s)) SetWindowText(hDlg, s); // replace by translated string (if different)
  382. for(j=1; k=dialogItems[i][j]; j++) { // translate all listed dialog items
  383. GetDlgItemText(hDlg, k, buf, MSG_SIZ);
  384. if(strlen(buf) == 0) continue;
  385. s = T_(buf);
  386. if(strcmp(buf, s)) SetDlgItemText(hDlg, k, s); // replace by translated string (if different)
  387. }
  388. }
  389. HMENU
  390. TranslateOneMenu(int i, HMENU subMenu)
  391. {
  392. int j;
  393. static MENUITEMINFO info;
  394. info.cbSize = sizeof(MENUITEMINFO);
  395. info.fMask = MIIM_STATE | MIIM_TYPE;
  396. for(j=GetMenuItemCount(subMenu)-1; j>=0; j--){
  397. char buf[MSG_SIZ];
  398. info.dwTypeData = buf;
  399. info.cch = sizeof(buf);
  400. GetMenuItemInfo(subMenu, j, TRUE, &info);
  401. if(i < 10) {
  402. if(menuText[i][j]) safeStrCpy(buf, menuText[i][j], sizeof(buf)/sizeof(buf[0]) );
  403. else menuText[i][j] = strdup(buf); // remember original on first change
  404. }
  405. if(buf[0] == NULLCHAR) continue;
  406. info.dwTypeData = T_(buf);
  407. info.cch = strlen(buf)+1;
  408. SetMenuItemInfo(subMenu, j, TRUE, &info);
  409. }
  410. return subMenu;
  411. }
  412. void
  413. TranslateMenus(int addLanguage)
  414. {
  415. int i;
  416. WIN32_FIND_DATA fileData;
  417. HANDLE hFind;
  418. #define IDM_English 1970
  419. if(1) {
  420. HMENU mainMenu = GetMenu(hwndMain);
  421. for (i=GetMenuItemCount(mainMenu)-1; i>=0; i--) {
  422. HMENU subMenu = GetSubMenu(mainMenu, i);
  423. ModifyMenu(mainMenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP|EnableMenuItem(mainMenu, i, MF_BYPOSITION),
  424. (UINT) subMenu, T_(menuBarText[tinyLayout][i]));
  425. TranslateOneMenu(i, subMenu);
  426. }
  427. DrawMenuBar(hwndMain);
  428. }
  429. if(!addLanguage) return;
  430. if((hFind = FindFirstFile("*.LNG", &fileData)) != INVALID_HANDLE_VALUE) {
  431. HMENU mainMenu = GetMenu(hwndMain);
  432. HMENU subMenu = GetSubMenu(mainMenu, GetMenuItemCount(mainMenu)-1);
  433. AppendMenu(subMenu, MF_SEPARATOR, (UINT_PTR) 0, NULL);
  434. AppendMenu(subMenu, MF_ENABLED|MF_STRING|(barbaric?MF_UNCHECKED:MF_CHECKED), (UINT_PTR) IDM_English, (LPCTSTR) "English");
  435. i = 0; lastChecked = IDM_English;
  436. do {
  437. char *p, *q = fileData.cFileName;
  438. int checkFlag = MF_UNCHECKED;
  439. languageFile[i] = strdup(q);
  440. if(barbaric && !strcmp(oldLanguage, q)) {
  441. checkFlag = MF_CHECKED;
  442. lastChecked = IDM_English + i + 1;
  443. CheckMenuItem(mainMenu, IDM_English, MF_BYCOMMAND|MF_UNCHECKED);
  444. }
  445. *q = ToUpper(*q); while(*++q) *q = ToLower(*q);
  446. p = strstr(fileData.cFileName, ".lng");
  447. if(p) *p = 0;
  448. AppendMenu(subMenu, MF_ENABLED|MF_STRING|checkFlag, (UINT_PTR) IDM_English + ++i, (LPCTSTR) fileData.cFileName);
  449. } while(FindNextFile(hFind, &fileData));
  450. FindClose(hFind);
  451. }
  452. }
  453. #endif
  454. #define IDM_RecentEngines 3000
  455. void
  456. RecentEngineMenu (char *s)
  457. {
  458. if(appData.icsActive) return;
  459. if(appData.recentEngines > 0 && *s) { // feature is on, and list non-empty
  460. HMENU mainMenu = GetMenu(hwndMain);
  461. HMENU subMenu = GetSubMenu(mainMenu, 5); // Engine menu
  462. int i=IDM_RecentEngines;
  463. recentEngines = strdup(appData.recentEngineList); // remember them as they are in menu
  464. AppendMenu(subMenu, MF_SEPARATOR, (UINT_PTR) 0, NULL);
  465. while(*s) {
  466. char *p = strchr(s, '\n');
  467. if(p == NULL) return; // malformed!
  468. *p = NULLCHAR;
  469. AppendMenu(subMenu, MF_ENABLED|MF_STRING|MF_UNCHECKED, (UINT_PTR) i++, (LPCTSTR) s);
  470. *p = '\n';
  471. s = p+1;
  472. }
  473. }
  474. }
  475. typedef struct {
  476. char *name;
  477. int squareSize;
  478. int lineGap;
  479. int smallLayout;
  480. int tinyLayout;
  481. int cliWidth, cliHeight;
  482. } SizeInfo;
  483. SizeInfo sizeInfo[] =
  484. {
  485. { "tiny", 21, 0, 1, 1, 0, 0 },
  486. { "teeny", 25, 1, 1, 1, 0, 0 },
  487. { "dinky", 29, 1, 1, 1, 0, 0 },
  488. { "petite", 33, 1, 1, 1, 0, 0 },
  489. { "slim", 37, 2, 1, 0, 0, 0 },
  490. { "small", 40, 2, 1, 0, 0, 0 },
  491. { "mediocre", 45, 2, 1, 0, 0, 0 },
  492. { "middling", 49, 2, 0, 0, 0, 0 },
  493. { "average", 54, 2, 0, 0, 0, 0 },
  494. { "moderate", 58, 3, 0, 0, 0, 0 },
  495. { "medium", 64, 3, 0, 0, 0, 0 },
  496. { "bulky", 72, 3, 0, 0, 0, 0 },
  497. { "large", 80, 3, 0, 0, 0, 0 },
  498. { "big", 87, 3, 0, 0, 0, 0 },
  499. { "huge", 95, 3, 0, 0, 0, 0 },
  500. { "giant", 108, 3, 0, 0, 0, 0 },
  501. { "colossal", 116, 4, 0, 0, 0, 0 },
  502. { "titanic", 129, 4, 0, 0, 0, 0 },
  503. { NULL, 0, 0, 0, 0, 0, 0 }
  504. };
  505. #define MF(x) {x, {{0,}, 0. }, {0, }, 0}
  506. MyFont fontRec[NUM_SIZES][NUM_FONTS] =
  507. {
  508. { 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) },
  509. { 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) },
  510. { 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) },
  511. { 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) },
  512. { 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) },
  513. { 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) },
  514. { 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) },
  515. { 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) },
  516. { 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) },
  517. { 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) },
  518. { 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) },
  519. { 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) },
  520. { 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) },
  521. { 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) },
  522. { 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) },
  523. { 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) },
  524. { 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) },
  525. { 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) },
  526. };
  527. MyFont *font[NUM_SIZES][NUM_FONTS];
  528. typedef struct {
  529. char *label;
  530. int id;
  531. HWND hwnd;
  532. WNDPROC wndproc;
  533. } MyButtonDesc;
  534. #define BUTTON_WIDTH (tinyLayout ? 16 : 32)
  535. #define N_BUTTONS 5
  536. MyButtonDesc buttonDesc[N_BUTTONS] =
  537. {
  538. {"<<", IDM_ToStart, NULL, NULL},
  539. {"<", IDM_Backward, NULL, NULL},
  540. {"P", IDM_Pause, NULL, NULL},
  541. {">", IDM_Forward, NULL, NULL},
  542. {">>", IDM_ToEnd, NULL, NULL},
  543. };
  544. int tinyLayout = 0, smallLayout = 0;
  545. #define MENU_BAR_ITEMS 9
  546. char *menuBarText[2][MENU_BAR_ITEMS+1] = {
  547. { N_("&File"), N_("&Edit"), N_("&View"), N_("&Mode"), N_("&Action"), N_("E&ngine"), N_("&Options"), N_("&Help"), NULL },
  548. { N_("&F"), N_("&E"), N_("&V"), N_("&M"), N_("&A"), N_("&N"), N_("&O"), N_("&H"), NULL },
  549. };
  550. MySound sounds[(int)NSoundClasses];
  551. MyTextAttribs textAttribs[(int)NColorClasses];
  552. MyColorizeAttribs colorizeAttribs[] = {
  553. { (COLORREF)0, 0, N_("Shout Text") },
  554. { (COLORREF)0, 0, N_("SShout/CShout") },
  555. { (COLORREF)0, 0, N_("Channel 1 Text") },
  556. { (COLORREF)0, 0, N_("Channel Text") },
  557. { (COLORREF)0, 0, N_("Kibitz Text") },
  558. { (COLORREF)0, 0, N_("Tell Text") },
  559. { (COLORREF)0, 0, N_("Challenge Text") },
  560. { (COLORREF)0, 0, N_("Request Text") },
  561. { (COLORREF)0, 0, N_("Seek Text") },
  562. { (COLORREF)0, 0, N_("Normal Text") },
  563. { (COLORREF)0, 0, N_("None") }
  564. };
  565. static char *commentTitle;
  566. static char *commentText;
  567. static int commentIndex;
  568. static Boolean editComment = FALSE;
  569. char errorTitle[MSG_SIZ];
  570. char errorMessage[2*MSG_SIZ];
  571. HWND errorDialog = NULL;
  572. BOOLEAN moveErrorMessageUp = FALSE;
  573. BOOLEAN consoleEcho = TRUE;
  574. CHARFORMAT consoleCF;
  575. COLORREF consoleBackgroundColor;
  576. char *programVersion;
  577. #define CPReal 1
  578. #define CPComm 2
  579. #define CPSock 3
  580. #define CPRcmd 4
  581. typedef int CPKind;
  582. typedef struct {
  583. CPKind kind;
  584. HANDLE hProcess;
  585. DWORD pid;
  586. HANDLE hTo;
  587. HANDLE hFrom;
  588. SOCKET sock;
  589. SOCKET sock2; /* stderr socket for OpenRcmd */
  590. } ChildProc;
  591. #define INPUT_SOURCE_BUF_SIZE 4096
  592. typedef struct _InputSource {
  593. CPKind kind;
  594. HANDLE hFile;
  595. SOCKET sock;
  596. int lineByLine;
  597. HANDLE hThread;
  598. DWORD id;
  599. char buf[INPUT_SOURCE_BUF_SIZE];
  600. char *next;
  601. DWORD count;
  602. int error;
  603. InputCallback func;
  604. struct _InputSource *second; /* for stderr thread on CPRcmd */
  605. VOIDSTAR closure;
  606. } InputSource;
  607. InputSource *consoleInputSource;
  608. DCB dcb;
  609. /* forward */
  610. VOID ConsoleOutput(char* data, int length, int forceVisible);
  611. VOID ConsoleCreate();
  612. LRESULT CALLBACK
  613. ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  614. VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
  615. VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
  616. VOID ParseCommSettings(char *arg, DCB *dcb);
  617. LRESULT CALLBACK
  618. StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  619. VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
  620. void ParseIcsTextMenu(char *icsTextMenuString);
  621. VOID PopUpNameDialog(char firstchar);
  622. VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
  623. /* [AS] */
  624. int NewGameFRC();
  625. int GameListOptions();
  626. int dummy; // [HGM] for obsolete args
  627. HWND hwndMain = NULL; /* root window*/
  628. HWND hwndConsole = NULL;
  629. HWND commentDialog = NULL;
  630. HWND moveHistoryDialog = NULL;
  631. HWND evalGraphDialog = NULL;
  632. HWND engineOutputDialog = NULL;
  633. HWND gameListDialog = NULL;
  634. HWND editTagsDialog = NULL;
  635. int commentUp = FALSE;
  636. WindowPlacement wpMain;
  637. WindowPlacement wpConsole;
  638. WindowPlacement wpComment;
  639. WindowPlacement wpMoveHistory;
  640. WindowPlacement wpEvalGraph;
  641. WindowPlacement wpEngineOutput;
  642. WindowPlacement wpGameList;
  643. WindowPlacement wpTags;
  644. VOID EngineOptionsPopup(); // [HGM] settings
  645. VOID GothicPopUp(char *title, VariantClass variant);
  646. /*
  647. * Setting "frozen" should disable all user input other than deleting
  648. * the window. We do this while engines are initializing themselves.
  649. */
  650. static int frozen = 0;
  651. static int oldMenuItemState[MENU_BAR_ITEMS];
  652. void FreezeUI()
  653. {
  654. HMENU hmenu;
  655. int i;
  656. if (frozen) return;
  657. frozen = 1;
  658. hmenu = GetMenu(hwndMain);
  659. for (i=0; i<MENU_BAR_ITEMS; i++) {
  660. oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
  661. }
  662. DrawMenuBar(hwndMain);
  663. }
  664. /* Undo a FreezeUI */
  665. void ThawUI()
  666. {
  667. HMENU hmenu;
  668. int i;
  669. if (!frozen) return;
  670. frozen = 0;
  671. hmenu = GetMenu(hwndMain);
  672. for (i=0; i<MENU_BAR_ITEMS; i++) {
  673. EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
  674. }
  675. DrawMenuBar(hwndMain);
  676. }
  677. /*static*/ int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them
  678. /* JAWS preparation patch (WinBoard for the sight impaired). Define required insertions as empty */
  679. #ifdef JAWS
  680. #include "jaws.c"
  681. #else
  682. #define JAWS_INIT
  683. #define JAWS_ARGS
  684. #define JAWS_ALT_INTERCEPT
  685. #define JAWS_KBUP_NAVIGATION
  686. #define JAWS_KBDOWN_NAVIGATION
  687. #define JAWS_MENU_ITEMS
  688. #define JAWS_SILENCE
  689. #define JAWS_REPLAY
  690. #define JAWS_ACCEL
  691. #define JAWS_COPYRIGHT
  692. #define JAWS_DELETE(X) X
  693. #define SAYMACHINEMOVE()
  694. #define SAY(X)
  695. #endif
  696. /*---------------------------------------------------------------------------*\
  697. *
  698. * WinMain
  699. *
  700. \*---------------------------------------------------------------------------*/
  701. int APIENTRY
  702. WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  703. LPSTR lpCmdLine, int nCmdShow)
  704. {
  705. MSG msg;
  706. HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
  707. // INITCOMMONCONTROLSEX ex;
  708. debugFP = stderr;
  709. LoadLibrary("RICHED32.DLL");
  710. consoleCF.cbSize = sizeof(CHARFORMAT);
  711. if (!InitApplication(hInstance)) {
  712. return (FALSE);
  713. }
  714. if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
  715. return (FALSE);
  716. }
  717. JAWS_INIT
  718. TranslateMenus(1);
  719. // InitCommonControlsEx(&ex);
  720. InitCommonControls();
  721. hAccelMain = LoadAccelerators (hInstance, szAppName);
  722. hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
  723. hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
  724. /* Acquire and dispatch messages until a WM_QUIT message is received. */
  725. while (GetMessage(&msg, /* message structure */
  726. NULL, /* handle of window receiving the message */
  727. 0, /* lowest message to examine */
  728. 0)) /* highest message to examine */
  729. {
  730. if(msg.message == WM_CHAR && msg.wParam == '\t') {
  731. // [HGM] navigate: switch between all windows with tab
  732. HWND e1 = NULL, e2 = NULL, mh = NULL, hInput = NULL, hText = NULL;
  733. int i, currentElement = 0;
  734. // first determine what element of the chain we come from (if any)
  735. if(appData.icsActive) {
  736. hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);
  737. hText = GetDlgItem(hwndConsole, OPT_ConsoleText);
  738. }
  739. if(engineOutputDialog && EngineOutputIsUp()) {
  740. e1 = GetDlgItem(engineOutputDialog, IDC_EngineMemo1);
  741. e2 = GetDlgItem(engineOutputDialog, IDC_EngineMemo2);
  742. }
  743. if(moveHistoryDialog && MoveHistoryIsUp()) {
  744. mh = GetDlgItem(moveHistoryDialog, IDC_MoveHistory);
  745. }
  746. if(msg.hwnd == hwndMain) currentElement = 7 ; else
  747. if(msg.hwnd == engineOutputDialog) currentElement = 2; else
  748. if(msg.hwnd == e1) currentElement = 2; else
  749. if(msg.hwnd == e2) currentElement = 3; else
  750. if(msg.hwnd == moveHistoryDialog) currentElement = 4; else
  751. if(msg.hwnd == mh) currentElement = 4; else
  752. if(msg.hwnd == evalGraphDialog) currentElement = 6; else
  753. if(msg.hwnd == hText) currentElement = 5; else
  754. if(msg.hwnd == hInput) currentElement = 6; else
  755. for (i = 0; i < N_BUTTONS; i++) {
  756. if (buttonDesc[i].hwnd == msg.hwnd) { currentElement = 1; break; }
  757. }
  758. // determine where to go to
  759. if(currentElement) { HWND h = NULL; int direction = GetKeyState(VK_SHIFT) < 0 ? -1 : 1;
  760. do {
  761. currentElement = (currentElement + direction) % 7;
  762. switch(currentElement) {
  763. case 0:
  764. h = hwndMain; break; // passing this case always makes the loop exit
  765. case 1:
  766. h = buttonDesc[0].hwnd; break; // could be NULL
  767. case 2:
  768. if(!EngineOutputIsUp()) continue; // skip closed auxiliary windows
  769. h = e1; break;
  770. case 3:
  771. if(!EngineOutputIsUp()) continue;
  772. h = e2; break;
  773. case 4:
  774. if(!MoveHistoryIsUp()) continue;
  775. h = mh; break;
  776. // case 6: // input to eval graph does not seem to get here!
  777. // if(!EvalGraphIsUp()) continue;
  778. // h = evalGraphDialog; break;
  779. case 5:
  780. if(!appData.icsActive) continue;
  781. SAY("display");
  782. h = hText; break;
  783. case 6:
  784. if(!appData.icsActive) continue;
  785. SAY("input");
  786. h = hInput; break;
  787. }
  788. } while(h == 0);
  789. if(currentElement > 4 && IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);
  790. if(currentElement < 5 && IsIconic(hwndMain)) ShowWindow(hwndMain, SW_RESTORE); // all open together
  791. SetFocus(h);
  792. continue; // this message now has been processed
  793. }
  794. }
  795. if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
  796. !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
  797. !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
  798. !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
  799. !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
  800. !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
  801. !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
  802. !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) && JAWS_ACCEL
  803. !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
  804. !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
  805. int done = 0, i; // [HGM] chat: dispatch cat-box messages
  806. for(i=0; i<MAX_CHAT; i++)
  807. if(chatHandle[i] && IsDialogMessage(chatHandle[i], &msg)) {
  808. done = 1; break;
  809. }
  810. if(done) continue; // [HGM] chat: end patch
  811. TranslateMessage(&msg); /* Translates virtual key codes */
  812. DispatchMessage(&msg); /* Dispatches message to window */
  813. }
  814. }
  815. return (msg.wParam); /* Returns the value from PostQuitMessage */
  816. }
  817. /*---------------------------------------------------------------------------*\
  818. *
  819. * Initialization functions
  820. *
  821. \*---------------------------------------------------------------------------*/
  822. void
  823. SetUserLogo()
  824. { // update user logo if necessary
  825. static char oldUserName[MSG_SIZ], dir[MSG_SIZ], *curName;
  826. if(appData.autoLogo) {
  827. curName = UserName();
  828. if(strcmp(curName, oldUserName)) {
  829. GetCurrentDirectory(MSG_SIZ, dir);
  830. SetCurrentDirectory(installDir);
  831. snprintf(oldUserName, MSG_SIZ, "logos\\%s.bmp", curName);
  832. userLogo = LoadImage( 0, oldUserName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
  833. safeStrCpy(oldUserName, curName, sizeof(oldUserName)/sizeof(oldUserName[0]) );
  834. if(userLogo == NULL)
  835. userLogo = LoadImage( 0, "logos\\dummy.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
  836. SetCurrentDirectory(dir); /* return to prev directory */
  837. }
  838. }
  839. }
  840. BOOL
  841. InitApplication(HINSTANCE hInstance)
  842. {
  843. WNDCLASS wc;
  844. /* Fill in window class structure with parameters that describe the */
  845. /* main window. */
  846. wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
  847. wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
  848. wc.cbClsExtra = 0; /* No per-class extra data. */
  849. wc.cbWndExtra = 0; /* No per-window extra data. */
  850. wc.hInstance = hInstance; /* Owner of this class */
  851. wc.hIcon = LoadIcon(hInstance, "icon_white");
  852. wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
  853. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
  854. wc.lpszMenuName = szAppName; /* Menu name from .RC */
  855. wc.lpszClassName = szAppName; /* Name to register as */
  856. /* Register the window class and return success/failure code. */
  857. if (!RegisterClass(&wc)) return FALSE;
  858. wc.style = CS_HREDRAW | CS_VREDRAW;
  859. wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
  860. wc.cbClsExtra = 0;
  861. wc.cbWndExtra = DLGWINDOWEXTRA;
  862. wc.hInstance = hInstance;
  863. wc.hIcon = LoadIcon(hInstance, "icon_white");
  864. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  865. wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
  866. wc.lpszMenuName = NULL;
  867. wc.lpszClassName = szConsoleName;
  868. if (!RegisterClass(&wc)) return FALSE;
  869. return TRUE;
  870. }
  871. /* Set by InitInstance, used by EnsureOnScreen */
  872. int screenHeight, screenWidth;
  873. void
  874. EnsureOnScreen(int *x, int *y, int minX, int minY)
  875. {
  876. // int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
  877. /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
  878. if (*x > screenWidth - 32) *x = 0;
  879. if (*y > screenHeight - 32) *y = 0;
  880. if (*x < minX) *x = minX;
  881. if (*y < minY) *y = minY;
  882. }
  883. VOID
  884. LoadLogo(ChessProgramState *cps, int n, Boolean ics)
  885. {
  886. char buf[MSG_SIZ], dir[MSG_SIZ];
  887. GetCurrentDirectory(MSG_SIZ, dir);
  888. SetCurrentDirectory(installDir);
  889. if( appData.logo[n] && appData.logo[n][0] != NULLCHAR) {
  890. cps->programLogo = LoadImage( 0, appData.logo[n], IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
  891. if (cps->programLogo == NULL && appData.debugMode) {
  892. fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.logo[n] );
  893. }
  894. } else if(appData.autoLogo) {
  895. if(ics) { // [HGM] logo: in ICS mode second can be used for ICS
  896. sprintf(buf, "logos\\%s.bmp", appData.icsHost);
  897. cps->programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
  898. } else
  899. if(appData.directory[n] && appData.directory[n][0]) {
  900. SetCurrentDirectory(appData.directory[n]);
  901. cps->programLogo = LoadImage( 0, "logo.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
  902. }
  903. }
  904. SetCurrentDirectory(dir); /* return to prev directory */
  905. }
  906. VOID
  907. InitTextures()
  908. {
  909. ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );
  910. backTextureSquareSize = 0; // kludge to force recalculation of texturemode
  911. if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {
  912. liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
  913. liteBackTextureMode = appData.liteBackTextureMode;
  914. if (liteBackTexture == NULL && appData.debugMode) {
  915. fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );
  916. }
  917. }
  918. if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {
  919. darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
  920. darkBackTextureMode = appData.darkBackTextureMode;
  921. if (darkBackTexture == NULL && appData.debugMode) {
  922. fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );
  923. }
  924. }
  925. }
  926. BOOL
  927. InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
  928. {
  929. HWND hwnd; /* Main window handle. */
  930. int ibs;
  931. WINDOWPLACEMENT wp;
  932. char *filepart;
  933. hInst = hInstance; /* Store instance handle in our global variable */
  934. programName = szAppName;
  935. if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
  936. *filepart = NULLCHAR;
  937. } else {
  938. GetCurrentDirectory(MSG_SIZ, installDir);
  939. }
  940. gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise
  941. screenWidth = screenHeight = 1000; // [HGM] placement: kludge to allow calling EnsureOnScreen from InitAppData
  942. InitAppData(lpCmdLine); /* Get run-time parameters */
  943. /* xboard, and older WinBoards, controlled the move sound with the
  944. appData.ringBellAfterMoves option. In the current WinBoard, we
  945. always turn the option on (so that the backend will call us),
  946. then let the user turn the sound off by setting it to silence if
  947. desired. To accommodate old winboard.ini files saved by old
  948. versions of WinBoard, we also turn off the sound if the option
  949. was initially set to false. [HGM] taken out of InitAppData */
  950. if (!appData.ringBellAfterMoves) {
  951. sounds[(int)SoundMove].name = strdup("");
  952. appData.ringBellAfterMoves = TRUE;
  953. }
  954. if (appData.debugMode) {
  955. debugFP = fopen(appData.nameOfDebugFile, "w");
  956. setbuf(debugFP, NULL);
  957. }
  958. LoadLanguageFile(appData.language);
  959. InitBackEnd1();
  960. // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()
  961. // InitEngineUCI( installDir, &second );
  962. /* Create a main window for this application instance. */
  963. hwnd = CreateWindow(szAppName, szTitle,
  964. (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
  965. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
  966. NULL, NULL, hInstance, NULL);
  967. hwndMain = hwnd;
  968. /* If window could not be created, return "failure" */
  969. if (!hwnd) {
  970. return (FALSE);
  971. }
  972. /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */
  973. LoadLogo(&first, 0, FALSE);
  974. LoadLogo(&second, 1, appData.icsActive);
  975. SetUserLogo();
  976. iconWhite = LoadIcon(hInstance, "icon_white");
  977. iconBlack = LoadIcon(hInstance, "icon_black");
  978. iconCurrent = iconWhite;
  979. InitDrawingColors();
  980. screenHeight = GetSystemMetrics(SM_CYSCREEN);
  981. screenWidth = GetSystemMetrics(SM_CXSCREEN);
  982. for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
  983. /* Compute window size for each board size, and use the largest
  984. size that fits on this screen as the default. */
  985. InitDrawingSizes((BoardSize)(ibs+1000), 0);
  986. if (boardSize == (BoardSize)-1 &&
  987. winH <= screenHeight
  988. - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10
  989. && winW <= screenWidth) {
  990. boardSize = (BoardSize)ibs;
  991. }
  992. }
  993. InitDrawingSizes(boardSize, 0);
  994. RecentEngineMenu(appData.recentEngineList);
  995. InitMenuChecks();
  996. buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
  997. /* [AS] Load textures if specified */
  998. InitTextures();
  999. mysrandom( (unsigned) time(NULL) );
  1000. /* [AS] Restore layout */
  1001. if( wpMoveHistory.visible ) {
  1002. MoveHistoryPopUp();
  1003. }
  1004. if( wpEvalGraph.visible ) {
  1005. EvalGraphPopUp();
  1006. }
  1007. if( wpEngineOutput.visible ) {
  1008. EngineOutputPopUp();
  1009. }
  1010. /* Make the window visible; update its client area; and return "success" */
  1011. EnsureOnScreen(&wpMain.x, &wpMain.y, minX, minY);
  1012. wp.length = sizeof(WINDOWPLACEMENT);
  1013. wp.flags = 0;
  1014. wp.showCmd = nCmdShow;
  1015. wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
  1016. wp.rcNormalPosition.left = wpMain.x;
  1017. wp.rcNormalPosition.right = wpMain.x + wpMain.width;
  1018. wp.rcNormalPosition.top = wpMain.y;
  1019. wp.rcNormalPosition.bottom = wpMain.y + wpMain.height;
  1020. SetWindowPlacement(hwndMain, &wp);
  1021. InitBackEnd2(); // [HGM] moved until after all windows placed, to save correct position if fatal error on engine start
  1022. if(!appData.noGUI) SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
  1023. 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
  1024. if (hwndConsole) {
  1025. #if AOT_CONSOLE
  1026. SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
  1027. 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
  1028. #endif
  1029. ShowWindow(hwndConsole, nCmdShow);
  1030. SetActiveWindow(hwndConsole);
  1031. }
  1032. if(!appData.noGUI) UpdateWindow(hwnd); else ShowWindow(hwnd, SW_MINIMIZE);
  1033. if(gameListDialog) SetFocus(gameListDialog); // [HGM] jaws: for if we clicked multi-game game file
  1034. return TRUE;
  1035. }
  1036. VOID
  1037. InitMenuChecks()
  1038. {
  1039. HMENU hmenu = GetMenu(hwndMain);
  1040. (void) EnableMenuItem(hmenu, IDM_CommPort,
  1041. MF_BYCOMMAND|((appData.icsActive &&
  1042. *appData.icsCommPort != NULLCHAR) ?
  1043. MF_ENABLED : MF_GRAYED));
  1044. (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,
  1045. MF_BYCOMMAND|(saveSettingsOnExit ?
  1046. MF_CHECKED : MF_UNCHECKED));
  1047. }
  1048. //---------------------------------------------------------------------------------------------------------
  1049. #define ICS_TEXT_MENU_SIZE (IDM_CommandXLast - IDM_CommandX + 1)
  1050. #define XBOARD FALSE
  1051. #define OPTCHAR "/"
  1052. #define SEPCHAR "="
  1053. #define TOPLEVEL 0
  1054. #include "args.h"
  1055. // front-end part of option handling
  1056. VOID
  1057. LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
  1058. {
  1059. HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
  1060. lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);
  1061. DeleteDC(hdc);
  1062. lf->lfWidth = 0;
  1063. lf->lfEscapement = 0;
  1064. lf->lfOrientation = 0;
  1065. lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;
  1066. lf->lfItalic = mfp->italic;
  1067. lf->lfUnderline = mfp->underline;
  1068. lf->lfStrikeOut = mfp->strikeout;
  1069. lf->lfCharSet = mfp->charset;
  1070. lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
  1071. lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
  1072. lf->lfQuality = DEFAULT_QUALITY;
  1073. lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
  1074. safeStrCpy(lf->lfFaceName, mfp->faceName, sizeof(lf->lfFaceName)/sizeof(lf->lfFaceName[0]) );
  1075. }
  1076. void
  1077. CreateFontInMF(MyFont *mf)
  1078. {
  1079. LFfromMFP(&mf->lf, &mf->mfp);
  1080. if (mf->hf) DeleteObject(mf->hf);
  1081. mf->hf = CreateFontIndirect(&mf->lf);
  1082. }
  1083. // [HGM] This platform-dependent table provides the location for storing the color info
  1084. void *
  1085. colorVariable[] = {
  1086. &whitePieceColor,
  1087. &blackPieceColor,
  1088. &lightSquareColor,
  1089. &darkSquareColor,
  1090. &highlightSquareColor,
  1091. &premoveHighlightColor,
  1092. NULL,
  1093. &consoleBackgroundColor,
  1094. &appData.fontForeColorWhite,
  1095. &appData.fontBackColorWhite,
  1096. &appData.fontForeColorBlack,
  1097. &appData.fontBackColorBlack,
  1098. &appData.evalHistColorWhite,
  1099. &appData.evalHistColorBlack,
  1100. &appData.highlightArrowColor,
  1101. };
  1102. /* Command line font name parser. NULL name means do nothing.
  1103. Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"
  1104. For backward compatibility, syntax without the colon is also
  1105. accepted, but font names with digits in them won't work in that case.
  1106. */
  1107. VOID
  1108. ParseFontName(char *name, MyFontParams *mfp)
  1109. {
  1110. char *p, *q;
  1111. if (name == NULL) return;
  1112. p = name;
  1113. q = strchr(p, ':');
  1114. if (q) {
  1115. if (q - p >= sizeof(mfp->faceName))
  1116. ExitArgError(_("Font name too long:"), name, TRUE);
  1117. memcpy(mfp->faceName, p, q - p);
  1118. mfp->faceName[q - p] = NULLCHAR;
  1119. p = q + 1;
  1120. } else {
  1121. q = mfp->faceName;
  1122. while (*p && !isdigit(*p)) {
  1123. *q++ = *p++;
  1124. if (q - mfp->faceName >= sizeof(mfp->faceName))
  1125. ExitArgError(_("Font name too long:"), name, TRUE);
  1126. }
  1127. while (q > mfp->faceName && q[-1] == ' ') q--;
  1128. *q = NULLCHAR;
  1129. }
  1130. if (!*p) ExitArgError(_("Font point size missing:"), name, TRUE);
  1131. mfp->pointSize = (float) atof(p);
  1132. mfp->bold = (strchr(p, 'b') != NULL);
  1133. mfp->italic = (strchr(p, 'i') != NULL);
  1134. mfp->underline = (strchr(p, 'u') != NULL);
  1135. mfp->strikeout = (strchr(p, 's') != NULL);
  1136. mfp->charset = DEFAULT_CHARSET;
  1137. q = strchr(p, 'c');
  1138. if (q)
  1139. mfp->charset = (BYTE) atoi(q+1);
  1140. }
  1141. void
  1142. ParseFont(char *name, int number)
  1143. { // wrapper to shield back-end from 'font'
  1144. ParseFontName(name, &font[boardSize][number]->mfp);
  1145. }
  1146. void
  1147. SetFontDefaults()
  1148. { // in WB we have a 2D array of fonts; this initializes their description
  1149. int i, j;
  1150. /* Point font array elements to structures and
  1151. parse default font names */
  1152. for (i=0; i<NUM_FONTS; i++) {
  1153. for (j=0; j<NUM_SIZES; j++) {
  1154. font[j][i] = &fontRec[j][i];
  1155. ParseFontName(font[j][i]->def, &font[j][i]->mfp);
  1156. }
  1157. }
  1158. }
  1159. void
  1160. CreateFonts()
  1161. { // here we create the actual fonts from the selected descriptions
  1162. int i, j;
  1163. for (i=0; i<NUM_FONTS; i++) {

Large files files are truncated, but you can click here to view the full file