2 * WinBoard.c -- Windows NT front end to XBoard
\r
3 * $Id: winboard.c,v 2.3 2003/11/25 05:25:20 mann Exp $
\r
5 * Copyright 1991 by Digital Equipment Corporation, Maynard,
\r
6 * Massachusetts. Enhancements Copyright
\r
7 * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software
\r
10 * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,
\r
11 * which was written and is copyrighted by Wayne Christopher.
\r
13 * The following terms apply to Digital Equipment Corporation's copyright
\r
14 * interest in XBoard:
\r
15 * ------------------------------------------------------------------------
\r
16 * All Rights Reserved
\r
18 * Permission to use, copy, modify, and distribute this software and its
\r
19 * documentation for any purpose and without fee is hereby granted,
\r
20 * provided that the above copyright notice appear in all copies and that
\r
21 * both that copyright notice and this permission notice appear in
\r
22 * supporting documentation, and that the name of Digital not be
\r
23 * used in advertising or publicity pertaining to distribution of the
\r
24 * software without specific, written prior permission.
\r
26 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
\r
27 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
\r
28 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
\r
29 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
\r
30 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
\r
31 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
\r
33 * ------------------------------------------------------------------------
\r
35 * The following terms apply to the enhanced version of XBoard
\r
36 * distributed by the Free Software Foundation:
\r
37 * ------------------------------------------------------------------------
\r
39 * GNU XBoard is free software: you can redistribute it and/or modify
\r
40 * it under the terms of the GNU General Public License as published by
\r
41 * the Free Software Foundation, either version 3 of the License, or (at
\r
42 * your option) any later version.
\r
44 * GNU XBoard is distributed in the hope that it will be useful, but
\r
45 * WITHOUT ANY WARRANTY; without even the implied warranty of
\r
46 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
47 * General Public License for more details.
\r
49 * You should have received a copy of the GNU General Public License
\r
50 * along with this program. If not, see http://www.gnu.org/licenses/. *
\r
52 *------------------------------------------------------------------------
\r
53 ** See the file ChangeLog for a revision history. */
\r
57 #include <windows.h>
\r
58 #include <winuser.h>
\r
59 #include <winsock.h>
\r
60 #include <commctrl.h>
\r
66 #include <sys/stat.h>
\r
69 #include <commdlg.h>
\r
71 #include <richedit.h>
\r
72 #include <mmsystem.h>
\r
81 #include "winboard.h"
\r
82 #include "frontend.h"
\r
83 #include "backend.h"
\r
85 #include "wclipbrd.h"
\r
86 #include "wgamelist.h"
\r
87 #include "wedittags.h"
\r
88 #include "woptions.h"
\r
89 #include "wsockerr.h"
\r
90 #include "defaults.h"
\r
94 //void InitEngineUCI( const char * iniDir, ChessProgramState * cps );
\r
97 void mysrandom(unsigned int seed);
\r
99 extern int whiteFlag, blackFlag;
\r
100 Boolean flipClock = FALSE;
\r
102 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);
\r
103 VOID NewVariantPopup(HWND hwnd);
\r
104 int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,
\r
105 /*char*/int promoChar));
\r
108 ChessSquare piece;
\r
109 POINT pos; /* window coordinates of current pos */
\r
110 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
111 POINT from; /* board coordinates of the piece's orig pos */
\r
112 POINT to; /* board coordinates of the piece's new pos */
\r
115 static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };
\r
118 POINT start; /* window coordinates of start pos */
\r
119 POINT pos; /* window coordinates of current pos */
\r
120 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
121 POINT from; /* board coordinates of the piece's orig pos */
\r
124 static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} };
\r
127 POINT sq[2]; /* board coordinates of from, to squares */
\r
130 static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} };
\r
131 static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };
\r
133 /* Window class names */
\r
134 char szAppName[] = "WinBoard";
\r
135 char szConsoleName[] = "WBConsole";
\r
137 /* Title bar text */
\r
138 char szTitle[] = "WinBoard";
\r
139 char szConsoleTitle[] = "ICS Interaction";
\r
142 char *settingsFileName;
\r
143 BOOLEAN saveSettingsOnExit;
\r
144 char installDir[MSG_SIZ];
\r
146 BoardSize boardSize;
\r
147 BOOLEAN chessProgram;
\r
148 static int boardX, boardY, consoleX, consoleY, consoleW, consoleH;
\r
149 static int squareSize, lineGap, minorSize;
\r
150 static int winWidth, winHeight;
\r
151 static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo
\r
152 static int logoHeight = 0;
\r
153 static char messageText[MESSAGE_TEXT_MAX];
\r
154 static int clockTimerEvent = 0;
\r
155 static int loadGameTimerEvent = 0;
\r
156 static int analysisTimerEvent = 0;
\r
157 static DelayedEventCallback delayedTimerCallback;
\r
158 static int delayedTimerEvent = 0;
\r
159 static int buttonCount = 2;
\r
160 char *icsTextMenuString;
\r
162 char *firstChessProgramNames;
\r
163 char *secondChessProgramNames;
\r
165 #define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */
\r
167 #define PALETTESIZE 256
\r
169 HINSTANCE hInst; /* current instance */
\r
170 HWND hwndMain = NULL; /* root window*/
\r
171 HWND hwndConsole = NULL;
\r
172 BOOLEAN alwaysOnTop = FALSE;
\r
174 COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
\r
175 blackPieceColor, highlightSquareColor, premoveHighlightColor;
\r
177 ColorClass currentColorClass;
\r
179 HWND hCommPort = NULL; /* currently open comm port */
\r
180 static HWND hwndPause; /* pause button */
\r
181 static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */
\r
182 static HBRUSH lightSquareBrush, darkSquareBrush,
\r
183 blackSquareBrush, /* [HGM] for band between board and holdings */
\r
184 whitePieceBrush, blackPieceBrush, iconBkgndBrush /*, outlineBrush*/;
\r
185 static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];
\r
186 static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];
\r
187 static HPEN gridPen = NULL;
\r
188 static HPEN highlightPen = NULL;
\r
189 static HPEN premovePen = NULL;
\r
190 static NPLOGPALETTE pLogPal;
\r
191 static BOOL paletteChanged = FALSE;
\r
192 static HICON iconWhite, iconBlack, iconCurrent;
\r
193 static int doingSizing = FALSE;
\r
194 static int lastSizing = 0;
\r
195 static int prevStderrPort;
\r
197 /* [AS] Support for background textures */
\r
198 #define BACK_TEXTURE_MODE_DISABLED 0
\r
199 #define BACK_TEXTURE_MODE_PLAIN 1
\r
200 #define BACK_TEXTURE_MODE_FULL_RANDOM 2
\r
202 static HBITMAP liteBackTexture = NULL;
\r
203 static HBITMAP darkBackTexture = NULL;
\r
204 static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
205 static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
206 static int backTextureSquareSize = 0;
\r
207 static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_SIZE][BOARD_SIZE];
\r
209 #if __GNUC__ && !defined(_winmajor)
\r
210 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */
\r
212 #define oldDialog (_winmajor < 4)
\r
215 char *defaultTextAttribs[] =
\r
217 COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,
\r
218 COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,
\r
228 int cliWidth, cliHeight;
\r
231 SizeInfo sizeInfo[] =
\r
233 { "tiny", 21, 0, 1, 1, 0, 0 },
\r
234 { "teeny", 25, 1, 1, 1, 0, 0 },
\r
235 { "dinky", 29, 1, 1, 1, 0, 0 },
\r
236 { "petite", 33, 1, 1, 1, 0, 0 },
\r
237 { "slim", 37, 2, 1, 0, 0, 0 },
\r
238 { "small", 40, 2, 1, 0, 0, 0 },
\r
239 { "mediocre", 45, 2, 1, 0, 0, 0 },
\r
240 { "middling", 49, 2, 0, 0, 0, 0 },
\r
241 { "average", 54, 2, 0, 0, 0, 0 },
\r
242 { "moderate", 58, 3, 0, 0, 0, 0 },
\r
243 { "medium", 64, 3, 0, 0, 0, 0 },
\r
244 { "bulky", 72, 3, 0, 0, 0, 0 },
\r
245 { "large", 80, 3, 0, 0, 0, 0 },
\r
246 { "big", 87, 3, 0, 0, 0, 0 },
\r
247 { "huge", 95, 3, 0, 0, 0, 0 },
\r
248 { "giant", 108, 3, 0, 0, 0, 0 },
\r
249 { "colossal", 116, 4, 0, 0, 0, 0 },
\r
250 { "titanic", 129, 4, 0, 0, 0, 0 },
\r
251 { NULL, 0, 0, 0, 0, 0, 0 }
\r
254 #define MF(x) {x, {{0,}, 0. }, {0, }, 0}
\r
255 MyFont fontRec[NUM_SIZES][NUM_FONTS] =
\r
257 { 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) },
\r
258 { 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) },
\r
259 { 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) },
\r
260 { 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) },
\r
261 { 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) },
\r
262 { 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) },
\r
263 { 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) },
\r
264 { 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) },
\r
265 { 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) },
\r
266 { 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) },
\r
267 { 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) },
\r
268 { 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) },
\r
269 { 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) },
\r
270 { 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) },
\r
271 { 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) },
\r
272 { 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) },
\r
273 { 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) },
\r
274 { 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) },
\r
277 MyFont *font[NUM_SIZES][NUM_FONTS];
\r
286 #define BUTTON_WIDTH (tinyLayout ? 16 : 32)
\r
287 #define N_BUTTONS 5
\r
289 MyButtonDesc buttonDesc[N_BUTTONS] =
\r
291 {"<<", IDM_ToStart, NULL, NULL},
\r
292 {"<", IDM_Backward, NULL, NULL},
\r
293 {"P", IDM_Pause, NULL, NULL},
\r
294 {">", IDM_Forward, NULL, NULL},
\r
295 {">>", IDM_ToEnd, NULL, NULL},
\r
298 int tinyLayout = 0, smallLayout = 0;
\r
299 #define MENU_BAR_ITEMS 6
\r
300 char *menuBarText[2][MENU_BAR_ITEMS+1] = {
\r
301 { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },
\r
302 { "&F", "&M", "&A", "&S", "&O", "&H", NULL },
\r
306 MySound sounds[(int)NSoundClasses];
\r
307 MyTextAttribs textAttribs[(int)NColorClasses];
\r
309 MyColorizeAttribs colorizeAttribs[] = {
\r
310 { (COLORREF)0, 0, "Shout Text" },
\r
311 { (COLORREF)0, 0, "SShout/CShout" },
\r
312 { (COLORREF)0, 0, "Channel 1 Text" },
\r
313 { (COLORREF)0, 0, "Channel Text" },
\r
314 { (COLORREF)0, 0, "Kibitz Text" },
\r
315 { (COLORREF)0, 0, "Tell Text" },
\r
316 { (COLORREF)0, 0, "Challenge Text" },
\r
317 { (COLORREF)0, 0, "Request Text" },
\r
318 { (COLORREF)0, 0, "Seek Text" },
\r
319 { (COLORREF)0, 0, "Normal Text" },
\r
320 { (COLORREF)0, 0, "None" }
\r
325 static char *commentTitle;
\r
326 static char *commentText;
\r
327 static int commentIndex;
\r
328 static Boolean editComment = FALSE;
\r
329 HWND commentDialog = NULL;
\r
330 BOOLEAN commentDialogUp = FALSE;
\r
331 static int commentX, commentY, commentH, commentW;
\r
333 static char *analysisTitle;
\r
334 static char *analysisText;
\r
335 HWND analysisDialog = NULL;
\r
336 BOOLEAN analysisDialogUp = FALSE;
\r
337 static int analysisX, analysisY, analysisH, analysisW;
\r
339 char errorTitle[MSG_SIZ];
\r
340 char errorMessage[2*MSG_SIZ];
\r
341 HWND errorDialog = NULL;
\r
342 BOOLEAN moveErrorMessageUp = FALSE;
\r
343 BOOLEAN consoleEcho = TRUE;
\r
344 CHARFORMAT consoleCF;
\r
345 COLORREF consoleBackgroundColor;
\r
347 char *programVersion;
\r
353 typedef int CPKind;
\r
362 SOCKET sock2; /* stderr socket for OpenRcmd */
\r
365 #define INPUT_SOURCE_BUF_SIZE 4096
\r
367 typedef struct _InputSource {
\r
374 char buf[INPUT_SOURCE_BUF_SIZE];
\r
378 InputCallback func;
\r
379 struct _InputSource *second; /* for stderr thread on CPRcmd */
\r
383 InputSource *consoleInputSource;
\r
388 VOID ConsoleOutput(char* data, int length, int forceVisible);
\r
389 VOID ConsoleCreate();
\r
391 ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
392 VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
\r
393 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
\r
394 VOID ParseCommSettings(char *arg, DCB *dcb);
\r
396 StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
397 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
\r
398 void ParseIcsTextMenu(char *icsTextMenuString);
\r
399 VOID PopUpMoveDialog(char firstchar);
\r
400 VOID PopUpNameDialog(char firstchar);
\r
401 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
\r
405 int GameListOptions();
\r
407 HWND moveHistoryDialog = NULL;
\r
408 BOOLEAN moveHistoryDialogUp = FALSE;
\r
410 WindowPlacement wpMoveHistory;
\r
412 HWND evalGraphDialog = NULL;
\r
413 BOOLEAN evalGraphDialogUp = FALSE;
\r
415 WindowPlacement wpEvalGraph;
\r
417 HWND engineOutputDialog = NULL;
\r
418 BOOLEAN engineOutputDialogUp = FALSE;
\r
420 WindowPlacement wpEngineOutput;
\r
422 VOID MoveHistoryPopUp();
\r
423 VOID MoveHistoryPopDown();
\r
424 VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
425 BOOL MoveHistoryIsUp();
\r
427 VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
428 VOID EvalGraphPopUp();
\r
429 VOID EvalGraphPopDown();
\r
430 BOOL EvalGraphIsUp();
\r
432 VOID EngineOutputPopUp();
\r
433 VOID EngineOutputPopDown();
\r
434 BOOL EngineOutputIsUp();
\r
435 VOID EngineOutputUpdate( FrontEndProgramStats * stats );
\r
437 VOID GothicPopUp(char *title, VariantClass variant);
\r
439 * Setting "frozen" should disable all user input other than deleting
\r
440 * the window. We do this while engines are initializing themselves.
\r
442 static int frozen = 0;
\r
443 static int oldMenuItemState[MENU_BAR_ITEMS];
\r
449 if (frozen) return;
\r
451 hmenu = GetMenu(hwndMain);
\r
452 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
453 oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
\r
455 DrawMenuBar(hwndMain);
\r
458 /* Undo a FreezeUI */
\r
464 if (!frozen) return;
\r
466 hmenu = GetMenu(hwndMain);
\r
467 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
468 EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
\r
470 DrawMenuBar(hwndMain);
\r
473 /*---------------------------------------------------------------------------*\
\r
477 \*---------------------------------------------------------------------------*/
\r
480 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
\r
481 LPSTR lpCmdLine, int nCmdShow)
\r
484 HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
\r
485 // INITCOMMONCONTROLSEX ex;
\r
489 LoadLibrary("RICHED32.DLL");
\r
490 consoleCF.cbSize = sizeof(CHARFORMAT);
\r
492 if (!InitApplication(hInstance)) {
\r
495 if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
\r
499 // InitCommonControlsEx(&ex);
\r
500 InitCommonControls();
\r
502 hAccelMain = LoadAccelerators (hInstance, szAppName);
\r
503 hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
\r
504 hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
\r
506 /* Acquire and dispatch messages until a WM_QUIT message is received. */
\r
508 while (GetMessage(&msg, /* message structure */
\r
509 NULL, /* handle of window receiving the message */
\r
510 0, /* lowest message to examine */
\r
511 0)) /* highest message to examine */
\r
513 if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
\r
514 !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
\r
515 !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
\r
516 !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
\r
517 !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
\r
518 !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
\r
519 !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
\r
520 !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) &&
\r
521 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
\r
522 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
\r
523 TranslateMessage(&msg); /* Translates virtual key codes */
\r
524 DispatchMessage(&msg); /* Dispatches message to window */
\r
529 return (msg.wParam); /* Returns the value from PostQuitMessage */
\r
532 /*---------------------------------------------------------------------------*\
\r
534 * Initialization functions
\r
536 \*---------------------------------------------------------------------------*/
\r
539 InitApplication(HINSTANCE hInstance)
\r
543 /* Fill in window class structure with parameters that describe the */
\r
546 wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
\r
547 wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
\r
548 wc.cbClsExtra = 0; /* No per-class extra data. */
\r
549 wc.cbWndExtra = 0; /* No per-window extra data. */
\r
550 wc.hInstance = hInstance; /* Owner of this class */
\r
551 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
552 wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
\r
553 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
\r
554 wc.lpszMenuName = szAppName; /* Menu name from .RC */
\r
555 wc.lpszClassName = szAppName; /* Name to register as */
\r
557 /* Register the window class and return success/failure code. */
\r
558 if (!RegisterClass(&wc)) return FALSE;
\r
560 wc.style = CS_HREDRAW | CS_VREDRAW;
\r
561 wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
\r
563 wc.cbWndExtra = DLGWINDOWEXTRA;
\r
564 wc.hInstance = hInstance;
\r
565 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
566 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
\r
567 wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
\r
568 wc.lpszMenuName = NULL;
\r
569 wc.lpszClassName = szConsoleName;
\r
571 if (!RegisterClass(&wc)) return FALSE;
\r
576 /* Set by InitInstance, used by EnsureOnScreen */
\r
577 int screenHeight, screenWidth;
\r
580 EnsureOnScreen(int *x, int *y)
\r
582 // int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
\r
583 /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
\r
584 if (*x > screenWidth - 32) *x = 0;
\r
585 if (*y > screenHeight - 32) *y = 0;
\r
586 if (*x < 0) *x = 0;
\r
587 if (*y < 0) *y = 0;
\r
588 // if (*x < 10) *x = 10;
\r
589 // if (*y < gap) *y = gap;
\r
593 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
\r
595 HWND hwnd; /* Main window handle. */
\r
597 WINDOWPLACEMENT wp;
\r
600 hInst = hInstance; /* Store instance handle in our global variable */
\r
602 if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
\r
603 *filepart = NULLCHAR;
\r
605 GetCurrentDirectory(MSG_SIZ, installDir);
\r
607 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise
\r
608 InitAppData(lpCmdLine); /* Get run-time parameters */
\r
609 if (appData.debugMode) {
\r
610 debugFP = fopen(appData.nameOfDebugFile, "w");
\r
611 setbuf(debugFP, NULL);
\r
616 // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()
\r
617 // InitEngineUCI( installDir, &second );
\r
619 /* Create a main window for this application instance. */
\r
620 hwnd = CreateWindow(szAppName, szTitle,
\r
621 (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
\r
622 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
\r
623 NULL, NULL, hInstance, NULL);
\r
626 /* If window could not be created, return "failure" */
\r
631 /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */
\r
632 if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {
\r
633 first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
635 if (first.programLogo == NULL && appData.debugMode) {
\r
636 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );
\r
638 } else if(appData.autoLogo) {
\r
639 if(appData.firstDirectory && appData.firstDirectory[0]) {
\r
641 sprintf(buf, "%s/logo.bmp", appData.firstDirectory);
\r
642 first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
646 if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {
\r
647 second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
649 if (second.programLogo == NULL && appData.debugMode) {
\r
650 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );
\r
652 } else if(appData.autoLogo) {
\r
653 if(appData.secondDirectory && appData.secondDirectory[0]) {
\r
655 sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);
\r
656 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
660 iconWhite = LoadIcon(hInstance, "icon_white");
\r
661 iconBlack = LoadIcon(hInstance, "icon_black");
\r
662 iconCurrent = iconWhite;
\r
663 InitDrawingColors();
\r
664 screenHeight = GetSystemMetrics(SM_CYSCREEN);
\r
665 screenWidth = GetSystemMetrics(SM_CXSCREEN);
\r
666 for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
\r
667 /* Compute window size for each board size, and use the largest
\r
668 size that fits on this screen as the default. */
\r
669 InitDrawingSizes((BoardSize)ibs, 0);
\r
670 if (boardSize == (BoardSize)-1 &&
\r
671 winHeight <= screenHeight
\r
672 - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10
\r
673 && winWidth <= screenWidth) {
\r
674 boardSize = (BoardSize)ibs;
\r
678 InitDrawingSizes(boardSize, 0);
\r
680 buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
\r
682 /* [AS] Load textures if specified */
\r
683 ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );
\r
685 if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {
\r
686 liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
687 liteBackTextureMode = appData.liteBackTextureMode;
\r
689 if (liteBackTexture == NULL && appData.debugMode) {
\r
690 fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );
\r
694 if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {
\r
695 darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
696 darkBackTextureMode = appData.darkBackTextureMode;
\r
698 if (darkBackTexture == NULL && appData.debugMode) {
\r
699 fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );
\r
703 mysrandom( (unsigned) time(NULL) );
\r
705 /* [AS] Restore layout */
\r
706 if( wpMoveHistory.visible ) {
\r
707 MoveHistoryPopUp();
\r
710 if( wpEvalGraph.visible ) {
\r
714 if( wpEngineOutput.visible ) {
\r
715 EngineOutputPopUp();
\r
720 /* Make the window visible; update its client area; and return "success" */
\r
721 EnsureOnScreen(&boardX, &boardY);
\r
722 wp.length = sizeof(WINDOWPLACEMENT);
\r
724 wp.showCmd = nCmdShow;
\r
725 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
\r
726 wp.rcNormalPosition.left = boardX;
\r
727 wp.rcNormalPosition.right = boardX + winWidth;
\r
728 wp.rcNormalPosition.top = boardY;
\r
729 wp.rcNormalPosition.bottom = boardY + winHeight;
\r
730 SetWindowPlacement(hwndMain, &wp);
\r
732 SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
733 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
736 /* [AS] Disable the FRC stuff if not playing the proper variant */
\r
737 if( gameInfo.variant != VariantFischeRandom ) {
\r
738 EnableMenuItem( GetMenu(hwndMain), IDM_NewGameFRC, MF_GRAYED );
\r
743 SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
744 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
746 ShowWindow(hwndConsole, nCmdShow);
\r
748 UpdateWindow(hwnd);
\r
756 ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
\r
757 ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
\r
758 ArgSettingsFilename
\r
766 String *pString; // ArgString
\r
767 int *pInt; // ArgInt
\r
768 float *pFloat; // ArgFloat
\r
769 Boolean *pBoolean; // ArgBoolean
\r
770 COLORREF *pColor; // ArgColor
\r
771 ColorClass cc; // ArgAttribs
\r
772 String *pFilename; // ArgFilename
\r
773 BoardSize *pBoardSize; // ArgBoardSize
\r
774 int whichFont; // ArgFont
\r
775 DCB *pDCB; // ArgCommSettings
\r
776 String *pFilename; // ArgSettingsFilename
\r
784 ArgDescriptor argDescriptors[] = {
\r
785 /* positional arguments */
\r
786 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
787 { "", ArgNone, NULL },
\r
788 /* keyword arguments */
\r
789 { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },
\r
790 { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },
\r
791 { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },
\r
792 { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },
\r
793 { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },
\r
794 { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },
\r
795 { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },
\r
796 { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },
\r
797 { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },
\r
798 { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },
\r
799 { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },
\r
800 { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },
\r
801 { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },
\r
802 { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },
\r
803 { "initString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
804 { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
805 { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },
\r
806 { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,
\r
808 { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,
\r
810 { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,
\r
812 { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },
\r
813 { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,
\r
815 { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },
\r
816 { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
817 { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
818 { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
819 { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
820 { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },
\r
821 { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },
\r
822 { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
823 { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
824 { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
825 { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
826 { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
827 { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
828 { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
829 { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
830 { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
831 { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
832 /*!!bitmapDirectory?*/
\r
833 { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
834 { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
835 { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
836 { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
837 { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },
\r
838 { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },
\r
839 { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },
\r
840 { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },
\r
841 { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },
\r
842 { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },
\r
843 { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },
\r
844 { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },
\r
845 { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
846 { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
847 { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
848 { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
849 { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
850 { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
851 { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
852 { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
853 { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
854 { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
855 { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
856 { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
857 { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },
\r
858 { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },
\r
859 { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
860 { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
861 { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },
\r
862 { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },
\r
863 { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },
\r
864 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
865 { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
866 { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
867 { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
868 { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },
\r
869 { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },
\r
870 { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },
\r
871 { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },
\r
872 { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
873 { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
874 { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
875 { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
876 { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
877 { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
878 { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
879 { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
880 { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },
\r
881 { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },
\r
882 { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
883 { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
884 { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
885 { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
886 { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },
\r
887 { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },
\r
888 { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
889 { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
890 { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },
\r
891 { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },
\r
892 { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
893 { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
894 { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },
\r
895 { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },
\r
896 { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
897 { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
898 { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
899 { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
900 { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
901 { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
902 { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },
\r
903 { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },
\r
904 { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
905 { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
906 { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },
\r
907 { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },
\r
908 { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
909 { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
910 { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },
\r
911 { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },
\r
912 { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
913 { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
914 { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },
\r
915 { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },
\r
916 { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
917 { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
918 { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },
\r
919 { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },
\r
920 { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
921 { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
922 { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },
\r
923 { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
924 { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
925 { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
926 { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors,
\r
927 FALSE }, /* only so that old WinBoard.ini files from betas can be read */
\r
928 { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },
\r
929 { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },
\r
930 { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },
\r
931 { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },
\r
932 { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },
\r
933 { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },
\r
934 { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE }, /* [AS] */
\r
935 { "boardSize", ArgBoardSize, (LPVOID) &boardSize,
\r
936 TRUE }, /* must come after all fonts */
\r
937 { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },
\r
938 { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,
\r
939 FALSE }, /* historical; kept only so old winboard.ini files will parse */
\r
940 { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },
\r
941 { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },
\r
942 { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
943 { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
944 { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },
\r
945 { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },
\r
946 { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
947 { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
948 { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },
\r
949 { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },
\r
950 { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
951 { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
952 { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },
\r
953 { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },
\r
954 { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
955 { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
956 { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },
\r
957 { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },
\r
958 { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
959 { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
960 { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },
\r
961 { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },
\r
962 { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
963 { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
964 { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },
\r
965 { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
966 { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
967 { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
969 { "cmailGameName", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
970 { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
972 { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },
\r
973 { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
974 { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
975 { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
976 { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },
\r
977 { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
978 { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
979 { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
980 { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },
\r
981 { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },
\r
982 { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
983 { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
984 { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },
\r
985 { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },
\r
986 { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
987 { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
988 { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },
\r
989 { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },
\r
990 { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
991 { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
992 { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },
\r
993 { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },
\r
994 { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
995 { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
996 { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },
\r
997 { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },
\r
998 { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
999 { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
1000 { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },
\r
1001 { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },
\r
1002 { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },
\r
1003 { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1004 { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1005 { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },
\r
1006 { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},
\r
1007 { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},
\r
1008 { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1009 { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1010 { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},
\r
1011 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1012 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1013 { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },
\r
1014 { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1015 { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1016 { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },
\r
1017 { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },
\r
1018 { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1019 { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1020 { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },
\r
1021 { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },
\r
1022 { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },
\r
1023 { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1024 { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1025 { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },
\r
1026 { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },
\r
1027 { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1028 { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1029 { "highlightLastMove", ArgBoolean,
\r
1030 (LPVOID) &appData.highlightLastMove, TRUE },
\r
1031 { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1032 { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1033 { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1034 { "highlightDragging", ArgBoolean,
\r
1035 (LPVOID) &appData.highlightDragging, TRUE },
\r
1036 { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },
\r
1037 { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1038 { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1039 { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },
\r
1040 { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },
\r
1041 { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1042 { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1043 { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },
\r
1044 { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },
\r
1045 { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },
\r
1046 { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },
\r
1047 { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },
\r
1048 { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },
\r
1049 { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },
\r
1050 { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },
\r
1051 { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },
\r
1052 { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },
\r
1053 { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },
\r
1054 { "soundShout", ArgFilename,
\r
1055 (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },
\r
1056 { "soundSShout", ArgFilename,
\r
1057 (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },
\r
1058 { "soundChannel1", ArgFilename,
\r
1059 (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },
\r
1060 { "soundChannel", ArgFilename,
\r
1061 (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },
\r
1062 { "soundKibitz", ArgFilename,
\r
1063 (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },
\r
1064 { "soundTell", ArgFilename,
\r
1065 (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },
\r
1066 { "soundChallenge", ArgFilename,
\r
1067 (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },
\r
1068 { "soundRequest", ArgFilename,
\r
1069 (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },
\r
1070 { "soundSeek", ArgFilename,
\r
1071 (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },
\r
1072 { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },
\r
1073 { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },
\r
1074 { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },
\r
1075 { "soundIcsLoss", ArgFilename,
\r
1076 (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },
\r
1077 { "soundIcsDraw", ArgFilename,
\r
1078 (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },
\r
1079 { "soundIcsUnfinished", ArgFilename,
\r
1080 (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},
\r
1081 { "soundIcsAlarm", ArgFilename,
\r
1082 (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },
\r
1083 { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },
\r
1084 { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },
\r
1085 { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1086 { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1087 { "reuseChessPrograms", ArgBoolean,
\r
1088 (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */
\r
1089 { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },
\r
1090 { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },
\r
1091 { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1092 { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1093 { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },
\r
1094 { "x", ArgInt, (LPVOID) &boardX, TRUE },
\r
1095 { "y", ArgInt, (LPVOID) &boardY, TRUE },
\r
1096 { "icsX", ArgInt, (LPVOID) &consoleX, TRUE },
\r
1097 { "icsY", ArgInt, (LPVOID) &consoleY, TRUE },
\r
1098 { "icsW", ArgInt, (LPVOID) &consoleW, TRUE },
\r
1099 { "icsH", ArgInt, (LPVOID) &consoleH, TRUE },
\r
1100 { "analysisX", ArgInt, (LPVOID) &analysisX, TRUE },
\r
1101 { "analysisY", ArgInt, (LPVOID) &analysisY, TRUE },
\r
1102 { "analysisW", ArgInt, (LPVOID) &analysisW, TRUE },
\r
1103 { "analysisH", ArgInt, (LPVOID) &analysisH, TRUE },
\r
1104 { "commentX", ArgInt, (LPVOID) &commentX, TRUE },
\r
1105 { "commentY", ArgInt, (LPVOID) &commentY, TRUE },
\r
1106 { "commentW", ArgInt, (LPVOID) &commentW, TRUE },
\r
1107 { "commentH", ArgInt, (LPVOID) &commentH, TRUE },
\r
1108 { "tagsX", ArgInt, (LPVOID) &editTagsX, TRUE },
\r
1109 { "tagsY", ArgInt, (LPVOID) &editTagsY, TRUE },
\r
1110 { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },
\r
1111 { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },
\r
1112 { "gameListX", ArgInt, (LPVOID) &gameListX, TRUE },
\r
1113 { "gameListY", ArgInt, (LPVOID) &gameListY, TRUE },
\r
1114 { "gameListW", ArgInt, (LPVOID) &gameListW, TRUE },
\r
1115 { "gameListH", ArgInt, (LPVOID) &gameListH, TRUE },
\r
1116 { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1117 { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1118 { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },
\r
1119 { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },
\r
1120 { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },
\r
1121 { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1122 { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1123 { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },
\r
1124 { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },
\r
1125 { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,
\r
1127 { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,
\r
1129 { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1130 { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1131 { "variant", ArgString, (LPVOID) &appData.variant, FALSE },
\r
1132 { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion, FALSE },
\r
1133 { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,FALSE },
\r
1134 { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },
\r
1135 { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },
\r
1136 { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1137 { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1138 /* [AS] New features */
\r
1139 { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE },
\r
1140 { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE },
\r
1141 { "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE },
\r
1142 { "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE },
\r
1143 { "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE },
\r
1144 { "darkBackTextureFile", ArgString, (LPVOID) &appData.darkBackTextureFile, TRUE },
\r
1145 { "liteBackTextureMode", ArgInt, (LPVOID) &appData.liteBackTextureMode, TRUE },
\r
1146 { "darkBackTextureMode", ArgInt, (LPVOID) &appData.darkBackTextureMode, TRUE },
\r
1147 { "renderPiecesWithFont", ArgString, (LPVOID) &appData.renderPiecesWithFont, TRUE },
\r
1148 { "fontPieceToCharTable", ArgString, (LPVOID) &appData.fontToPieceTable, TRUE },
\r
1149 { "fontPieceBackColorWhite", ArgColor, (LPVOID) &appData.fontBackColorWhite, TRUE },
\r
1150 { "fontPieceForeColorWhite", ArgColor, (LPVOID) &appData.fontForeColorWhite, TRUE },
\r
1151 { "fontPieceBackColorBlack", ArgColor, (LPVOID) &appData.fontBackColorBlack, TRUE },
\r
1152 { "fontPieceForeColorBlack", ArgColor, (LPVOID) &appData.fontForeColorBlack, TRUE },
\r
1153 { "fontPieceSize", ArgInt, (LPVOID) &appData.fontPieceSize, TRUE },
\r
1154 { "overrideLineGap", ArgInt, (LPVOID) &appData.overrideLineGap, TRUE },
\r
1155 { "adjudicateLossThreshold", ArgInt, (LPVOID) &appData.adjudicateLossThreshold, TRUE },
\r
1156 { "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE },
\r
1157 { "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE },
\r
1158 { "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1159 { "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1160 { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },
\r
1161 { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE },
\r
1162 { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE },
\r
1163 { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE },
\r
1164 { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE },
\r
1165 { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE },
\r
1166 { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE },
\r
1167 { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE },
\r
1168 { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE },
\r
1169 { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE },
\r
1170 { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE },
\r
1171 { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE },
\r
1172 { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE },
\r
1173 { "firstIsUCI", ArgBoolean, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1174 { "fUCI", ArgTrue, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1175 { "secondIsUCI", ArgBoolean, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1176 { "sUCI", ArgTrue, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1177 { "firstHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1178 { "fNoOwnBookUCI", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1179 { "firstXBook", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1180 { "secondHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1181 { "sNoOwnBookUCI", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1182 { "secondXBook", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1183 { "polyglotDir", ArgFilename, (LPVOID) &appData.polyglotDir, TRUE },
\r
1184 { "usePolyglotBook", ArgBoolean, (LPVOID) &appData.usePolyglotBook, TRUE },
\r
1185 { "polyglotBook", ArgFilename, (LPVOID) &appData.polyglotBook, TRUE },
\r
1186 { "defaultHashSize", ArgInt, (LPVOID) &appData.defaultHashSize, TRUE },
\r
1187 { "defaultCacheSizeEGTB", ArgInt, (LPVOID) &appData.defaultCacheSizeEGTB, TRUE },
\r
1188 { "defaultPathEGTB", ArgFilename, (LPVOID) &appData.defaultPathEGTB, TRUE },
\r
1190 /* [AS] Layout stuff */
\r
1191 { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },
\r
1192 { "moveHistoryX", ArgInt, (LPVOID) &wpMoveHistory.x, TRUE },
\r
1193 { "moveHistoryY", ArgInt, (LPVOID) &wpMoveHistory.y, TRUE },
\r
1194 { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },
\r
1195 { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },
\r
1197 { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },
\r
1198 { "evalGraphX", ArgInt, (LPVOID) &wpEvalGraph.x, TRUE },
\r
1199 { "evalGraphY", ArgInt, (LPVOID) &wpEvalGraph.y, TRUE },
\r
1200 { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },
\r
1201 { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },
\r
1203 { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },
\r
1204 { "engineOutputX", ArgInt, (LPVOID) &wpEngineOutput.x, TRUE },
\r
1205 { "engineOutputY", ArgInt, (LPVOID) &wpEngineOutput.y, TRUE },
\r
1206 { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },
\r
1207 { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },
\r
1209 /* [HGM] board-size, adjudication and misc. options */
\r
1210 { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE },
\r
1211 { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE },
\r
1212 { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE },
\r
1213 { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE },
\r
1214 { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE },
\r
1215 { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE },
\r
1216 { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE },
\r
1217 { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE },
\r
1218 { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE },
\r
1219 { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE },
\r
1220 { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE },
\r
1221 { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE },
\r
1222 { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE },
\r
1223 { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE },
\r
1224 { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE },
\r
1225 { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE },
\r
1226 { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE },
\r
1227 { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE },
\r
1228 { "userName", ArgString, (LPVOID) &appData.userName, FALSE },
\r
1229 { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE },
\r
1230 { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE },
\r
1231 { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE },
\r
1232 { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE },
\r
1233 { "niceEngines", ArgInt, (LPVOID) &appData.niceEngines, TRUE },
\r
1234 { "firstLogo", ArgFilename, (LPVOID) &appData.firstLogo, FALSE },
\r
1235 { "secondLogo", ArgFilename, (LPVOID) &appData.secondLogo, FALSE },
\r
1236 { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE },
\r
1237 { "firstOptions", ArgString, (LPVOID) &appData.firstOptions, FALSE },
\r
1238 { "secondOptions", ArgString, (LPVOID) &appData.secondOptions, FALSE },
\r
1241 { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },
\r
1242 { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },
\r
1243 { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1244 { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1245 { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },
\r
1246 { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },
\r
1247 { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1248 { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1249 { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },
\r
1250 { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },
\r
1251 { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },
\r
1252 { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE },
\r
1253 { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,
\r
1255 { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE },
\r
1256 { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE },
\r
1257 { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE },
\r
1258 { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1259 { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1260 { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE },
\r
1261 { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,
\r
1263 { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1264 { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1265 { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1266 { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE },
\r
1267 { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE },
\r
1268 { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1269 { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1270 { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1271 { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1272 { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE },
\r
1273 { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE },
\r
1274 { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1275 { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1276 { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },
\r
1277 { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },
\r
1278 { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },
\r
1279 /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */
\r
1280 { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },
\r
1282 /* [HGM] options for broadcasting and time odds */
\r
1283 { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },
\r
1284 { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },
\r
1285 { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },
\r
1286 { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },
\r
1287 { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },
\r
1288 { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },
\r
1289 { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },
\r
1290 { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },
\r
1291 { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },
\r
1292 { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },
\r
1293 { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE },
\r
1294 { NULL, ArgNone, NULL, FALSE }
\r
1298 /* Kludge for indirection files on command line */
\r
1299 char* lastIndirectionFilename;
\r
1300 ArgDescriptor argDescriptorIndirection =
\r
1301 { "", ArgSettingsFilename, (LPVOID) NULL, FALSE };
\r
1305 ExitArgError(char *msg, char *badArg)
\r
1307 char buf[MSG_SIZ];
\r
1309 sprintf(buf, "%s %s", msg, badArg);
\r
1310 DisplayFatalError(buf, 0, 2);
\r
1314 /* Command line font name parser. NULL name means do nothing.
\r
1315 Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"
\r
1316 For backward compatibility, syntax without the colon is also
\r
1317 accepted, but font names with digits in them won't work in that case.
\r
1320 ParseFontName(char *name, MyFontParams *mfp)
\r
1323 if (name == NULL) return;
\r
1325 q = strchr(p, ':');
\r
1327 if (q - p >= sizeof(mfp->faceName))
\r
1328 ExitArgError("Font name too long:", name);
\r
1329 memcpy(mfp->faceName, p, q - p);
\r
1330 mfp->faceName[q - p] = NULLCHAR;
\r
1333 q = mfp->faceName;
\r
1334 while (*p && !isdigit(*p)) {
\r
1336 if (q - mfp->faceName >= sizeof(mfp->faceName))
\r
1337 ExitArgError("Font name too long:", name);
\r
1339 while (q > mfp->faceName && q[-1] == ' ') q--;
\r
1342 if (!*p) ExitArgError("Font point size missing:", name);
\r
1343 mfp->pointSize = (float) atof(p);
\r
1344 mfp->bold = (strchr(p, 'b') != NULL);
\r
1345 mfp->italic = (strchr(p, 'i') != NULL);
\r
1346 mfp->underline = (strchr(p, 'u') != NULL);
\r
1347 mfp->strikeout = (strchr(p, 's') != NULL);
\r
1350 /* Color name parser.
\r
1351 X version accepts X color names, but this one
\r
1352 handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */
\r
1354 ParseColorName(char *name)
\r
1356 int red, green, blue, count;
\r
1357 char buf[MSG_SIZ];
\r
1359 count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);
\r
1361 count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d",
\r
1362 &red, &green, &blue);
\r
1365 sprintf(buf, "Can't parse color name %s", name);
\r
1366 DisplayError(buf, 0);
\r
1367 return RGB(0, 0, 0);
\r
1369 return PALETTERGB(red, green, blue);
\r
1373 void ParseAttribs(COLORREF *color, int *effects, char* argValue)
\r
1375 char *e = argValue;
\r
1379 if (*e == 'b') eff |= CFE_BOLD;
\r
1380 else if (*e == 'i') eff |= CFE_ITALIC;
\r
1381 else if (*e == 'u') eff |= CFE_UNDERLINE;
\r
1382 else if (*e == 's') eff |= CFE_STRIKEOUT;
\r
1383 else if (*e == '#' || isdigit(*e)) break;
\r
1387 *color = ParseColorName(e);
\r
1392 ParseBoardSize(char *name)
\r
1394 BoardSize bs = SizeTiny;
\r
1395 while (sizeInfo[bs].name != NULL) {
\r
1396 if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;
\r
1399 ExitArgError("Unrecognized board size value", name);
\r
1400 return bs; /* not reached */
\r
1405 StringGet(void *getClosure)
\r
1407 char **p = (char **) getClosure;
\r
1412 FileGet(void *getClosure)
\r
1415 FILE* f = (FILE*) getClosure;
\r
1418 if (c == '\r') c = getc(f); // work around DOS format files by bypassing the '\r' completely
\r
1425 /* Parse settings file named "name". If file found, return the
\r
1426 full name in fullname and return TRUE; else return FALSE */
\r
1428 ParseSettingsFile(char *name, char fullname[MSG_SIZ])
\r
1432 int ok; char buf[MSG_SIZ];
\r
1434 ok = SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy);
\r
1435 if(!ok && strchr(name, '.') == NULL) { // [HGM] append default file-name extension '.ini' when needed
\r
1436 sprintf(buf, "%s.ini", name);
\r
1437 ok = SearchPath(installDir, buf, NULL, MSG_SIZ, fullname, &dummy);
\r
1440 f = fopen(fullname, "r");
\r
1442 ParseArgs(FileGet, f);
\r
1451 ParseArgs(GetFunc get, void *cl)
\r
1453 char argName[ARG_MAX];
\r
1454 char argValue[ARG_MAX];
\r
1455 ArgDescriptor *ad;
\r
1464 while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);
\r
1465 if (ch == NULLCHAR) break;
\r
1467 /* Comment to end of line */
\r
1469 while (ch != '\n' && ch != NULLCHAR) ch = get(cl);
\r
1471 } else if (ch == '/' || ch == '-') {
\r
1474 while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&
\r
1475 ch != '\n' && ch != '\t') {
\r
1481 for (ad = argDescriptors; ad->argName != NULL; ad++)
\r
1482 if (strcmp(ad->argName, argName + 1) == 0) break;
\r
1484 if (ad->argName == NULL)
\r
1485 ExitArgError("Unrecognized argument", argName);
\r
1487 } else if (ch == '@') {
\r
1488 /* Indirection file */
\r
1489 ad = &argDescriptorIndirection;
\r
1492 /* Positional argument */
\r
1493 ad = &argDescriptors[posarg++];
\r
1494 strcpy(argName, ad->argName);
\r
1497 if (ad->argType == ArgTrue) {
\r
1498 *(Boolean *) ad->argLoc = TRUE;
\r
1501 if (ad->argType == ArgFalse) {
\r
1502 *(Boolean *) ad->argLoc = FALSE;
\r
1506 while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
\r
1507 if (ch == NULLCHAR || ch == '\n') {
\r
1508 ExitArgError("No value provided for argument", argName);
\r
1512 // Quoting with { }. No characters have to (or can) be escaped.
\r
1513 // Thus the string cannot contain a '}' character.
\r
1533 } else if (ch == '\'' || ch == '"') {
\r
1534 // Quoting with ' ' or " ", with \ as escape character.
\r
1535 // Inconvenient for long strings that may contain Windows filenames.
\r
1552 if (ch == start) {
\r
1561 if (ad->argType == ArgFilename
\r
1562 || ad->argType == ArgSettingsFilename) {
\r
1568 ExitArgError("Incomplete \\ escape in value for", argName);
\r
1592 for (i = 0; i < 3; i++) {
\r
1593 if (ch >= '0' && ch <= '7') {
\r
1594 octval = octval*8 + (ch - '0');
\r
1601 *q++ = (char) octval;
\r
1612 while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {
\r
1619 switch (ad->argType) {
\r
1621 *(int *) ad->argLoc = atoi(argValue);
\r
1625 *(float *) ad->argLoc = (float) atof(argValue);
\r
1630 *(char **) ad->argLoc = strdup(argValue);
\r
1633 case ArgSettingsFilename:
\r
1635 char fullname[MSG_SIZ];
\r
1636 if (ParseSettingsFile(argValue, fullname)) {
\r
1637 if (ad->argLoc != NULL) {
\r
1638 *(char **) ad->argLoc = strdup(fullname);
\r
1641 if (ad->argLoc != NULL) {
\r
1643 ExitArgError("Failed to open indirection file", argValue);
\r
1650 switch (argValue[0]) {
\r
1653 *(Boolean *) ad->argLoc = TRUE;
\r
1657 *(Boolean *) ad->argLoc = FALSE;
\r
1660 ExitArgError("Unrecognized boolean argument value", argValue);
\r
1666 *(COLORREF *)ad->argLoc = ParseColorName(argValue);
\r
1669 case ArgAttribs: {
\r
1670 ColorClass cc = (ColorClass)ad->argLoc;
\r
1671 ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);
\r
1675 case ArgBoardSize:
\r
1676 *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);
\r
1680 ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);
\r
1683 case ArgCommSettings:
\r
1684 ParseCommSettings(argValue, &dcb);
\r
1688 ExitArgError("Unrecognized argument", argValue);
\r
1697 LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
\r
1699 HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
\r
1700 lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);
\r
1703 lf->lfEscapement = 0;
\r
1704 lf->lfOrientation = 0;
\r
1705 lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;
\r
1706 lf->lfItalic = mfp->italic;
\r
1707 lf->lfUnderline = mfp->underline;
\r
1708 lf->lfStrikeOut = mfp->strikeout;
\r
1709 lf->lfCharSet = DEFAULT_CHARSET;
\r
1710 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
1711 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
1712 lf->lfQuality = DEFAULT_QUALITY;
\r
1713 lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
\r
1714 strcpy(lf->lfFaceName, mfp->faceName);
\r
1718 CreateFontInMF(MyFont *mf)
\r
1720 LFfromMFP(&mf->lf, &mf->mfp);
\r
1721 if (mf->hf) DeleteObject(mf->hf);
\r
1722 mf->hf = CreateFontIndirect(&mf->lf);
\r
1726 SetDefaultTextAttribs()
\r
1729 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1730 ParseAttribs(&textAttribs[cc].color,
\r
1731 &textAttribs[cc].effects,
\r
1732 defaultTextAttribs[cc]);
\r
1737 SetDefaultSounds()
\r
1741 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1742 textAttribs[cc].sound.name = strdup("");
\r
1743 textAttribs[cc].sound.data = NULL;
\r
1745 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1746 sounds[sc].name = strdup("");
\r
1747 sounds[sc].data = NULL;
\r
1749 sounds[(int)SoundBell].name = strdup(SOUND_BELL);
\r
1757 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1758 MyLoadSound(&textAttribs[cc].sound);
\r
1760 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1761 MyLoadSound(&sounds[sc]);
\r
1766 InitAppData(LPSTR lpCmdLine)
\r
1769 char buf[ARG_MAX], currDir[MSG_SIZ];
\r
1772 programName = szAppName;
\r
1774 /* Initialize to defaults */
\r
1775 lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);
\r
1776 darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);
\r
1777 whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);
\r
1778 blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);
\r
1779 highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);
\r
1780 premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);
\r
1781 consoleBackgroundColor = ParseColorName(COLOR_BKGD);
\r
1782 SetDefaultTextAttribs();
\r
1783 SetDefaultSounds();
\r
1784 appData.movesPerSession = MOVES_PER_SESSION;
\r
1785 appData.initString = INIT_STRING;
\r
1786 appData.secondInitString = INIT_STRING;
\r
1787 appData.firstComputerString = COMPUTER_STRING;
\r
1788 appData.secondComputerString = COMPUTER_STRING;
\r
1789 appData.firstChessProgram = FIRST_CHESS_PROGRAM;
\r
1790 appData.secondChessProgram = SECOND_CHESS_PROGRAM;
\r
1791 appData.firstPlaysBlack = FALSE;
\r
1792 appData.noChessProgram = FALSE;
\r
1793 chessProgram = FALSE;
\r
1794 appData.firstHost = FIRST_HOST;
\r
1795 appData.secondHost = SECOND_HOST;
\r
1796 appData.firstDirectory = FIRST_DIRECTORY;
\r
1797 appData.secondDirectory = SECOND_DIRECTORY;
\r
1798 appData.bitmapDirectory = "";
\r
1799 appData.remoteShell = REMOTE_SHELL;
\r
1800 appData.remoteUser = "";
\r
1801 appData.timeDelay = TIME_DELAY;
\r
1802 appData.timeControl = TIME_CONTROL;
\r
1803 appData.timeIncrement = TIME_INCREMENT;
\r
1804 appData.icsActive = FALSE;
\r
1805 appData.icsHost = "";
\r
1806 appData.icsPort = ICS_PORT;
\r
1807 appData.icsCommPort = ICS_COMM_PORT;
\r
1808 appData.icsLogon = ICS_LOGON;
\r
1809 appData.icsHelper = "";
\r
1810 appData.useTelnet = FALSE;
\r
1811 appData.telnetProgram = TELNET_PROGRAM;
\r
1812 appData.gateway = "";
\r
1813 appData.loadGameFile = "";
\r
1814 appData.loadGameIndex = 0;
\r
1815 appData.saveGameFile = "";
\r
1816 appData.autoSaveGames = FALSE;
\r
1817 appData.loadPositionFile = "";
\r
1818 appData.loadPositionIndex = 1;
\r
1819 appData.savePositionFile = "";
\r
1820 appData.matchMode = FALSE;
\r
1821 appData.matchGames = 0;
\r
1822 appData.monoMode = FALSE;
\r
1823 appData.debugMode = FALSE;
\r
1824 appData.clockMode = TRUE;
\r
1825 boardSize = (BoardSize) -1; /* determine by screen size */
\r
1826 appData.Iconic = FALSE; /*unused*/
\r
1827 appData.searchTime = "";
\r
1828 appData.searchDepth = 0;
\r
1829 appData.showCoords = FALSE;
\r
1830 appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/
\r
1831 appData.autoCallFlag = FALSE;
\r
1832 appData.flipView = FALSE;
\r
1833 appData.autoFlipView = TRUE;
\r
1834 appData.cmailGameName = "";
\r
1835 appData.alwaysPromoteToQueen = FALSE;
\r
1836 appData.oldSaveStyle = FALSE;
\r
1837 appData.quietPlay = FALSE;
\r
1838 appData.showThinking = FALSE;
\r
1839 appData.ponderNextMove = TRUE;
\r
1840 appData.periodicUpdates = TRUE;
\r
1841 appData.popupExitMessage = TRUE;
\r
1842 appData.popupMoveErrors = FALSE;
\r
1843 appData.autoObserve = FALSE;
\r
1844 appData.autoComment = FALSE;
\r
1845 appData.animate = TRUE;
\r
1846 appData.animSpeed = 10;
\r
1847 appData.animateDragging = TRUE;
\r
1848 appData.highlightLastMove = TRUE;
\r
1849 appData.getMoveList = TRUE;
\r
1850 appData.testLegality = TRUE;
\r
1851 appData.premove = TRUE;
\r
1852 appData.premoveWhite = FALSE;
\r
1853 appData.premoveWhiteText = "";
\r
1854 appData.premoveBlack = FALSE;
\r
1855 appData.premoveBlackText = "";
\r
1856 appData.icsAlarm = TRUE;
\r
1857 appData.icsAlarmTime = 5000;
\r
1858 appData.autoRaiseBoard = TRUE;
\r
1859 appData.localLineEditing = TRUE;
\r
1860 appData.colorize = TRUE;
\r
1861 appData.reuseFirst = TRUE;
\r
1862 appData.reuseSecond = TRUE;
\r
1863 appData.blindfold = FALSE;
\r
1864 appData.icsEngineAnalyze = FALSE;
\r
1865 memset(&dcb, 0, sizeof(DCB)); // required by VS 2002 +
\r
1866 dcb.DCBlength = sizeof(DCB);
\r
1867 dcb.BaudRate = 9600;
\r
1868 dcb.fBinary = TRUE;
\r
1869 dcb.fParity = FALSE;
\r
1870 dcb.fOutxCtsFlow = FALSE;
\r
1871 dcb.fOutxDsrFlow = FALSE;
\r
1872 dcb.fDtrControl = DTR_CONTROL_ENABLE;
\r
1873 dcb.fDsrSensitivity = FALSE;
\r
1874 dcb.fTXContinueOnXoff = TRUE;
\r
1875 dcb.fOutX = FALSE;
\r
1877 dcb.fNull = FALSE;
\r
1878 dcb.fRtsControl = RTS_CONTROL_ENABLE;
\r
1879 dcb.fAbortOnError = FALSE;
\r
1881 dcb.Parity = SPACEPARITY;
\r
1882 dcb.StopBits = ONESTOPBIT;
\r
1883 settingsFileName = SETTINGS_FILE;
\r
1884 saveSettingsOnExit = TRUE;
\r
1885 boardX = CW_USEDEFAULT;
\r
1886 boardY = CW_USEDEFAULT;
\r
1887 consoleX = CW_USEDEFAULT;
\r
1888 consoleY = CW_USEDEFAULT;
\r
1889 consoleW = CW_USEDEFAULT;
\r
1890 consoleH = CW_USEDEFAULT;
\r
1891 analysisX = CW_USEDEFAULT;
\r
1892 analysisY = CW_USEDEFAULT;
\r
1893 analysisW = CW_USEDEFAULT;
\r
1894 analysisH = CW_USEDEFAULT;
\r
1895 commentX = CW_USEDEFAULT;
\r
1896 commentY = CW_USEDEFAULT;
\r
1897 commentW = CW_USEDEFAULT;
\r
1898 commentH = CW_USEDEFAULT;
\r
1899 editTagsX = CW_USEDEFAULT;
\r
1900 editTagsY = CW_USEDEFAULT;
\r
1901 editTagsW = CW_USEDEFAULT;
\r
1902 editTagsH = CW_USEDEFAULT;
\r
1903 gameListX = CW_USEDEFAULT;
\r
1904 gameListY = CW_USEDEFAULT;
\r
1905 gameListW = CW_USEDEFAULT;
\r
1906 gameListH = CW_USEDEFAULT;
\r
1907 icsTextMenuString = ICS_TEXT_MENU_DEFAULT;
\r
1908 icsNames = ICS_NAMES;
\r
1909 firstChessProgramNames = FCP_NAMES;
\r
1910 secondChessProgramNames = SCP_NAMES;
\r
1911 appData.initialMode = "";
\r
1912 appData.variant = "normal";
\r
1913 appData.firstProtocolVersion = PROTOVER;
\r
1914 appData.secondProtocolVersion = PROTOVER;
\r
1915 appData.showButtonBar = TRUE;
\r
1917 /* [AS] New properties (see comments in header file) */
\r
1918 appData.firstScoreIsAbsolute = FALSE;
\r
1919 appData.secondScoreIsAbsolute = FALSE;
\r
1920 appData.saveExtendedInfoInPGN = FALSE;
\r
1921 appData.hideThinkingFromHuman = FALSE;
\r
1922 appData.liteBackTextureFile = "";
\r
1923 appData.liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
1924 appData.darkBackTextureFile = "";
\r
1925 appData.darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
1926 appData.renderPiecesWithFont = "";
\r
1927 appData.fontToPieceTable = "";
\r
1928 appData.fontBackColorWhite = 0;
\r
1929 appData.fontForeColorWhite = 0;
\r
1930 appData.fontBackColorBlack = 0;
\r
1931 appData.fontForeColorBlack = 0;
\r
1932 appData.fontPieceSize = 80;
\r
1933 appData.overrideLineGap = 1;
\r
1934 appData.adjudicateLossThreshold = 0;
\r
1935 appData.delayBeforeQuit = 0;
\r
1936 appData.delayAfterQuit = 0;
\r
1937 appData.nameOfDebugFile = "winboard.debug";
\r
1938 appData.pgnEventHeader = "Computer Chess Game";
\r
1939 appData.defaultFrcPosition = -1;
\r
1940 appData.gameListTags = GLT_DEFAULT_TAGS;
\r
1941 appData.saveOutOfBookInfo = TRUE;
\r
1942 appData.showEvalInMoveHistory = TRUE;
\r
1943 appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );
\r
1944 appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );
\r
1945 appData.highlightMoveWithArrow = FALSE;
\r
1946 appData.highlightArrowColor = ParseColorName( "#FFFF80" );
\r
1947 appData.useStickyWindows = TRUE;
\r
1948 appData.adjudicateDrawMoves = 0;
\r
1949 appData.autoDisplayComment = TRUE;
\r
1950 appData.autoDisplayTags = TRUE;
\r
1951 appData.firstIsUCI = FALSE;
\r
1952 appData.secondIsUCI = FALSE;
\r
1953 appData.firstHasOwnBookUCI = TRUE;
\r
1954 appData.secondHasOwnBookUCI = TRUE;
\r
1955 appData.polyglotDir = "";
\r
1956 appData.usePolyglotBook = FALSE;
\r
1957 appData.polyglotBook = "";
\r
1958 appData.defaultHashSize = 64;
\r
1959 appData.defaultCacheSizeEGTB = 4;
\r
1960 appData.defaultPathEGTB = "c:\\egtb";
\r
1961 appData.firstOptions = "";
\r
1962 appData.secondOptions = "";
\r
1964 InitWindowPlacement( &wpMoveHistory );
\r
1965 InitWindowPlacement( &wpEvalGraph );
\r
1966 InitWindowPlacement( &wpEngineOutput );
\r
1968 /* [HGM] User-selectable board size, adjudication control, miscellaneous */
\r
1969 appData.NrFiles = -1;
\r
1970 appData.NrRanks = -1;
\r
1971 appData.holdingsSize = -1;
\r
1972 appData.testClaims = FALSE;
\r
1973 appData.checkMates = FALSE;
\r
1974 appData.materialDraws= FALSE;
\r
1975 appData.trivialDraws = FALSE;
\r
1976 appData.ruleMoves = 51;
\r
1977 appData.drawRepeats = 6;
\r
1978 appData.matchPause = 10000;
\r
1979 appData.alphaRank = FALSE;
\r
1980 appData.allWhite = FALSE;
\r
1981 appData.upsideDown = FALSE;
\r
1982 appData.serverPause = 15;
\r
1983 appData.serverMovesName = NULL;
\r
1984 appData.suppressLoadMoves = FALSE;
\r
1985 appData.firstTimeOdds = 1;
\r
1986 appData.secondTimeOdds = 1;
\r
1987 appData.firstAccumulateTC = 1; // combine previous and current sessions
\r
1988 appData.secondAccumulateTC = 1;
\r
1989 appData.firstNPS = -1; // [HGM] nps: use wall-clock time
\r
1990 appData.secondNPS = -1;
\r
1991 appData.engineComments = 1;
\r
1992 appData.smpCores = 1; // [HGM] SMP: max nr of cores
\r
1993 appData.egtFormats = "";
\r
1996 appData.zippyTalk = ZIPPY_TALK;
\r
1997 appData.zippyPlay = ZIPPY_PLAY;
\r
1998 appData.zippyLines = ZIPPY_LINES;
\r
1999 appData.zippyPinhead = ZIPPY_PINHEAD;
\r
2000 appData.zippyPassword = ZIPPY_PASSWORD;
\r
2001 appData.zippyPassword2 = ZIPPY_PASSWORD2;
\r
2002 appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;
\r
2003 appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;
\r
2004 appData.zippyUseI = ZIPPY_USE_I;
\r
2005 appData.zippyBughouse = ZIPPY_BUGHOUSE;
\r
2006 appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;
\r
2007 appData.zippyGameEnd = ZIPPY_GAME_END;
\r
2008 appData.zippyGameStart = ZIPPY_GAME_START;
\r
2009 appData.zippyAdjourn = ZIPPY_ADJOURN;
\r
2010 appData.zippyAbort = ZIPPY_ABORT;
\r
2011 appData.zippyVariants = ZIPPY_VARIANTS;
\r
2012 appData.zippyMaxGames = ZIPPY_MAX_GAMES;
\r
2013 appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;
\r
2016 /* Point font array elements to structures and
\r
2017 parse default font names */
\r
2018 for (i=0; i<NUM_FONTS; i++) {
\r
2019 for (j=0; j<NUM_SIZES; j++) {
\r
2020 font[j][i] = &fontRec[j][i];
\r
2021 ParseFontName(font[j][i]->def, &font[j][i]->mfp);
\r
2025 /* Parse default settings file if any */
\r
2026 if (ParseSettingsFile(settingsFileName, buf)) {
\r
2027 settingsFileName = strdup(buf);
\r
2030 /* Parse command line */
\r
2031 ParseArgs(StringGet, &lpCmdLine);
\r
2033 /* [HGM] make sure board size is acceptable */
\r
2034 if(appData.NrFiles > BOARD_SIZE ||
\r
2035 appData.NrRanks > BOARD_SIZE )
\r
2036 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
2038 /* [HGM] After parsing the options from the .ini file, and overruling them
\r
2039 * with options from the command line, we now make an even higher priority
\r
2040 * overrule by WB options attached to the engine command line. This so that
\r
2041 * tournament managers can use WB options (such as /timeOdds) that follow
\r
2044 if(appData.firstChessProgram != NULL) {
\r
2045 char *p = StrStr(appData.firstChessProgram, "WBopt");
\r
2046 static char *f = "first";
\r
2047 char buf[MSG_SIZ], *q = buf;
\r
2048 if(p != NULL) { // engine command line contains WinBoard options
\r
2049 sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"
\r
2050 ParseArgs(StringGet, &q);
\r
2051 p[-1] = 0; // cut them offengine command line
\r
2054 // now do same for second chess program
\r
2055 if(appData.secondChessProgram != NULL) {
\r
2056 char *p = StrStr(appData.secondChessProgram, "WBopt");
\r
2057 static char *s = "second";
\r
2058 char buf[MSG_SIZ], *q = buf;
\r
2059 if(p != NULL) { // engine command line contains WinBoard options
\r
2060 sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"
\r
2061 ParseArgs(StringGet, &q);
\r
2062 p[-1] = 0; // cut them offengine command line
\r
2067 /* Propagate options that affect others */
\r
2068 if (appData.matchMode || appData.matchGames) chessProgram = TRUE;
\r
2069 if (appData.icsActive || appData.noChessProgram) {
\r
2070 chessProgram = FALSE; /* not local chess program mode */
\r
2073 /* Open startup dialog if needed */
\r
2074 if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||
\r
2075 (appData.icsActive && *appData.icsHost == NULLCHAR) ||
\r
2076 (chessProgram && (*appData.firstChessProgram == NULLCHAR ||
\r
2077 *appData.secondChessProgram == NULLCHAR))) {
\r
2080 lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);
\r
2081 DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);
\r
2082 FreeProcInstance(lpProc);
\r
2085 /* Make sure save files land in the right (?) directory */
\r
2086 if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {
\r
2087 appData.saveGameFile = strdup(buf);
\r
2089 if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {
\r
2090 appData.savePositionFile = strdup(buf);
\r
2093 /* Finish initialization for fonts and sounds */
\r
2094 for (i=0; i<NUM_FONTS; i++) {
\r
2095 for (j=0; j<NUM_SIZES; j++) {
\r
2096 CreateFontInMF(font[j][i]);
\r
2099 /* xboard, and older WinBoards, controlled the move sound with the
\r
2100 appData.ringBellAfterMoves option. In the current WinBoard, we
\r
2101 always turn the option on (so that the backend will call us),
\r
2102 then let the user turn the sound off by setting it to silence if
\r
2103 desired. To accommodate old winboard.ini files saved by old
\r
2104 versions of WinBoard, we also turn off the sound if the option
\r
2105 was initially set to false. */
\r
2106 if (!appData.ringBellAfterMoves) {
\r
2107 sounds[(int)SoundMove].name = strdup("");
\r
2108 appData.ringBellAfterMoves = TRUE;
\r
2110 GetCurrentDirectory(MSG_SIZ, currDir);
\r
2111 SetCurrentDirectory(installDir);
\r
2113 SetCurrentDirectory(currDir);
\r
2115 p = icsTextMenuString;
\r
2116 if (p[0] == '@') {
\r
2117 FILE* f = fopen(p + 1, "r");
\r
2119 DisplayFatalError(p + 1, errno, 2);
\r
2122 i = fread(buf, 1, sizeof(buf)-1, f);
\r
2124 buf[i] = NULLCHAR;
\r
2127 ParseIcsTextMenu(strdup(p));
\r
2134 HMENU hmenu = GetMenu(hwndMain);
\r
2136 (void) EnableMenuItem(hmenu, IDM_CommPort,
\r
2137 MF_BYCOMMAND|((appData.icsActive &&
\r
2138 *appData.icsCommPort != NULLCHAR) ?
\r
2139 MF_ENABLED : MF_GRAYED));
\r
2140 (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,
\r
2141 MF_BYCOMMAND|(saveSettingsOnExit ?
\r
2142 MF_CHECKED : MF_UNCHECKED));
\r
2147 SaveSettings(char* name)
\r
2150 ArgDescriptor *ad;
\r
2151 WINDOWPLACEMENT wp;
\r
2152 char dir[MSG_SIZ];
\r
2154 if (!hwndMain) return;
\r
2156 GetCurrentDirectory(MSG_SIZ, dir);
\r
2157 SetCurrentDirectory(installDir);
\r
2158 f = fopen(name, "w");
\r
2159 SetCurrentDirectory(dir);
\r
2161 DisplayError(name, errno);
\r
2164 fprintf(f, ";\n");
\r
2165 fprintf(f, "; %s %s.%s Save Settings file\n", PRODUCT, VERSION, PATCHLEVEL);
\r
2166 fprintf(f, ";\n");
\r
2167 fprintf(f, "; You can edit the values of options that are already set in this file,\n");
\r
2168 fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");
\r
2169 fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");
\r
2170 fprintf(f, ";\n");
\r
2172 wp.length = sizeof(WINDOWPLACEMENT);
\r
2173 GetWindowPlacement(hwndMain, &wp);
\r
2174 boardX = wp.rcNormalPosition.left;
\r
2175 boardY = wp.rcNormalPosition.top;
\r
2177 if (hwndConsole) {
\r
2178 GetWindowPlacement(hwndConsole, &wp);
\r
2179 consoleX = wp.rcNormalPosition.left;
\r
2180 consoleY = wp.rcNormalPosition.top;
\r
2181 consoleW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2182 consoleH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2185 if (analysisDialog) {
\r
2186 GetWindowPlacement(analysisDialog, &wp);
\r
2187 analysisX = wp.rcNormalPosition.left;
\r
2188 analysisY = wp.rcNormalPosition.top;
\r
2189 analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2190 analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2193 if (commentDialog) {
\r
2194 GetWindowPlacement(commentDialog, &wp);
\r
2195 commentX = wp.rcNormalPosition.left;
\r
2196 commentY = wp.rcNormalPosition.top;
\r
2197 commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2198 commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2201 if (editTagsDialog) {
\r
2202 GetWindowPlacement(editTagsDialog, &wp);
\r
2203 editTagsX = wp.rcNormalPosition.left;
\r
2204 editTagsY = wp.rcNormalPosition.top;
\r
2205 editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2206 editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2209 if (gameListDialog) {
\r
2210 GetWindowPlacement(gameListDialog, &wp);
\r
2211 gameListX = wp.rcNormalPosition.left;
\r
2212 gameListY = wp.rcNormalPosition.top;
\r
2213 gameListW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2214 gameListH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2217 /* [AS] Move history */
\r
2218 wpMoveHistory.visible = MoveHistoryIsUp();
\r
2220 if( moveHistoryDialog ) {
\r
2221 GetWindowPlacement(moveHistoryDialog, &wp);
\r
2222 wpMoveHistory.x = wp.rcNormalPosition.left;
\r
2223 wpMoveHistory.y = wp.rcNormalPosition.top;
\r
2224 wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2225 wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2228 /* [AS] Eval graph */
\r
2229 wpEvalGraph.visible = EvalGraphIsUp();
\r
2231 if( evalGraphDialog ) {
\r
2232 GetWindowPlacement(evalGraphDialog, &wp);
\r
2233 wpEvalGraph.x = wp.rcNormalPosition.left;
\r
2234 wpEvalGraph.y = wp.rcNormalPosition.top;
\r
2235 wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2236 wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2239 /* [AS] Engine output */
\r
2240 wpEngineOutput.visible = EngineOutputIsUp();
\r
2242 if( engineOutputDialog ) {
\r
2243 GetWindowPlacement(engineOutputDialog, &wp);
\r
2244 wpEngineOutput.x = wp.rcNormalPosition.left;
\r
2245 wpEngineOutput.y = wp.rcNormalPosition.top;
\r
2246 wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2247 wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2250 for (ad = argDescriptors; ad->argName != NULL; ad++) {
\r
2251 if (!ad->save) continue;
\r
2252 switch (ad->argType) {
\r
2255 char *p = *(char **)ad->argLoc;
\r
2256 if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {
\r
2257 /* Quote multiline values or \-containing values
\r
2258 with { } if possible */
\r
2259 fprintf(f, "/%s={%s}\n", ad->argName, p);
\r
2261 /* Else quote with " " */
\r
2262 fprintf(f, "/%s=\"", ad->argName);
\r
2264 if (*p == '\n') fprintf(f, "\n");
\r
2265 else if (*p == '\r') fprintf(f, "\\r");
\r
2266 else if (*p == '\t') fprintf(f, "\\t");
\r
2267 else if (*p == '\b') fprintf(f, "\\b");
\r
2268 else if (*p == '\f') fprintf(f, "\\f");
\r
2269 else if (*p < ' ') fprintf(f, "\\%03o", *p);
\r
2270 else if (*p == '\"') fprintf(f, "\\\"");
\r
2271 else if (*p == '\\') fprintf(f, "\\\\");
\r
2275 fprintf(f, "\"\n");
\r
2280 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);
\r
2283 fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);
\r
2286 fprintf(f, "/%s=%s\n", ad->argName,
\r
2287 (*(Boolean *)ad->argLoc) ? "true" : "false");
\r
2290 if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2293 if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2297 COLORREF color = *(COLORREF *)ad->argLoc;
\r
2298 fprintf(f, "/%s=#%02lx%02lx%02lx\n", ad->argName,
\r
2299 color&0xff, (color>>8)&0xff, (color>>16)&0xff);
\r
2304 MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];
\r
2305 fprintf(f, "/%s=\"%s%s%s%s%s#%02lx%02lx%02lx\"\n", ad->argName,
\r
2306 (ta->effects & CFE_BOLD) ? "b" : "",
\r
2307 (ta->effects & CFE_ITALIC) ? "i" : "",
\r
2308 (ta->effects & CFE_UNDERLINE) ? "u" : "",
\r
2309 (ta->effects & CFE_STRIKEOUT) ? "s" : "",
\r
2310 (ta->effects) ? " " : "",
\r
2311 ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);
\r
2315 if (strchr(*(char **)ad->argLoc, '\"')) {
\r
2316 fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);
\r
2318 fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);
\r
2321 case ArgBoardSize:
\r
2322 fprintf(f, "/%s=%s\n", ad->argName,
\r
2323 sizeInfo[*(BoardSize *)ad->argLoc].name);
\r
2328 for (bs=0; bs<NUM_SIZES; bs++) {
\r
2329 MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;
\r
2330 fprintf(f, "/size=%s ", sizeInfo[bs].name);
\r
2331 fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n",
\r
2332 ad->argName, mfp->faceName, mfp->pointSize,
\r
2333 mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",
\r
2334 mfp->bold ? "b" : "",
\r
2335 mfp->italic ? "i" : "",
\r
2336 mfp->underline ? "u" : "",
\r
2337 mfp->strikeout ? "s" : "");
\r
2341 case ArgCommSettings:
\r
2342 PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);
\r
2344 case ArgSettingsFilename: ;
\r
2352 /*---------------------------------------------------------------------------*\
\r
2354 * GDI board drawing routines
\r
2356 \*---------------------------------------------------------------------------*/
\r
2358 /* [AS] Draw square using background texture */
\r
2359 static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )
\r
2364 return; /* Should never happen! */
\r
2367 SetGraphicsMode( dst, GM_ADVANCED );
\r
2374 /* X reflection */
\r
2379 x.eDx = (FLOAT) dw + dx - 1;
\r
2382 SetWorldTransform( dst, &x );
\r
2385 /* Y reflection */
\r
2391 x.eDy = (FLOAT) dh + dy - 1;
\r
2393 SetWorldTransform( dst, &x );
\r
2401 x.eDx = (FLOAT) dx;
\r
2402 x.eDy = (FLOAT) dy;
\r
2405 SetWorldTransform( dst, &x );
\r
2409 BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );
\r
2417 SetWorldTransform( dst, &x );
\r
2419 ModifyWorldTransform( dst, 0, MWT_IDENTITY );
\r
2422 /* [AS] [HGM] Make room for more piece types, so all pieces can be different */
\r
2424 PM_WP = (int) WhitePawn,
\r
2425 PM_WN = (int) WhiteKnight,
\r
2426 PM_WB = (int) WhiteBishop,
\r
2427 PM_WR = (int) WhiteRook,
\r
2428 PM_WQ = (int) WhiteQueen,
\r
2429 PM_WF = (int) WhiteFerz,
\r
2430 PM_WW = (int) WhiteWazir,
\r
2431 PM_WE = (int) WhiteAlfil,
\r
2432 PM_WM = (int) WhiteMan,
\r
2433 PM_WO = (int) WhiteCannon,
\r
2434 PM_WU = (int) WhiteUnicorn,
\r
2435 PM_WH = (int) WhiteNightrider,
\r
2436 PM_WA = (int) WhiteAngel,
\r
2437 PM_WC = (int) WhiteMarshall,
\r
2438 PM_WAB = (int) WhiteCardinal,
\r
2439 PM_WD = (int) WhiteDragon,
\r
2440 PM_WL = (int) WhiteLance,
\r
2441 PM_WS = (int) WhiteCobra,
\r
2442 PM_WV = (int) WhiteFalcon,
\r
2443 PM_WSG = (int) WhiteSilver,
\r
2444 PM_WG = (int) WhiteGrasshopper,
\r
2445 PM_WK = (int) WhiteKing,
\r
2446 PM_BP = (int) BlackPawn,
\r
2447 PM_BN = (int) BlackKnight,
\r
2448 PM_BB = (int) BlackBishop,
\r
2449 PM_BR = (int) BlackRook,
\r
2450 PM_BQ = (int) BlackQueen,
\r
2451 PM_BF = (int) BlackFerz,
\r
2452 PM_BW = (int) BlackWazir,
\r
2453 PM_BE = (int) BlackAlfil,
\r
2454 PM_BM = (int) BlackMan,
\r
2455 PM_BO = (int) BlackCannon,
\r
2456 PM_BU = (int) BlackUnicorn,
\r
2457 PM_BH = (int) BlackNightrider,
\r
2458 PM_BA = (int) BlackAngel,
\r
2459 PM_BC = (int) BlackMarshall,
\r
2460 PM_BG = (int) BlackGrasshopper,
\r
2461 PM_BAB = (int) BlackCardinal,
\r
2462 PM_BD = (int) BlackDragon,
\r
2463 PM_BL = (int) BlackLance,
\r
2464 PM_BS = (int) BlackCobra,
\r
2465 PM_BV = (int) BlackFalcon,
\r
2466 PM_BSG = (int) BlackSilver,
\r
2467 PM_BK = (int) BlackKing
\r
2470 static HFONT hPieceFont = NULL;
\r
2471 static HBITMAP hPieceMask[(int) EmptySquare];
\r
2472 static HBITMAP hPieceFace[(int) EmptySquare];
\r
2473 static int fontBitmapSquareSize = 0;
\r
2474 static char pieceToFontChar[(int) EmptySquare] =
\r
2475 { 'p', 'n', 'b', 'r', 'q',
\r
2476 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',
\r
2477 'k', 'o', 'm', 'v', 't', 'w',
\r
2478 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',
\r
2481 extern BOOL SetCharTable( char *table, const char * map );
\r
2482 /* [HGM] moved to backend.c */
\r
2484 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )
\r
2487 BYTE r1 = GetRValue( color );
\r
2488 BYTE g1 = GetGValue( color );
\r
2489 BYTE b1 = GetBValue( color );
\r
2495 /* Create a uniform background first */
\r
2496 hbrush = CreateSolidBrush( color );
\r
2497 SetRect( &rc, 0, 0, squareSize, squareSize );
\r
2498 FillRect( hdc, &rc, hbrush );
\r
2499 DeleteObject( hbrush );
\r
2502 /* Vertical gradient, good for pawn, knight and rook, less for queen and king */
\r
2503 int steps = squareSize / 2;
\r
2506 for( i=0; i<steps; i++ ) {
\r
2507 BYTE r = r1 - (r1-r2) * i / steps;
\r
2508 BYTE g = g1 - (g1-g2) * i / steps;
\r
2509 BYTE b = b1 - (b1-b2) * i / steps;
\r
2511 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2512 SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );
\r
2513 FillRect( hdc, &rc, hbrush );
\r
2514 DeleteObject(hbrush);
\r
2517 else if( mode == 2 ) {
\r
2518 /* Diagonal gradient, good more or less for every piece */
\r
2519 POINT triangle[3];
\r
2520 HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );
\r
2521 HBRUSH hbrush_old;
\r
2522 int steps = squareSize;
\r
2525 triangle[0].x = squareSize - steps;
\r
2526 triangle[0].y = squareSize;
\r
2527 triangle[1].x = squareSize;
\r
2528 triangle[1].y = squareSize;
\r
2529 triangle[2].x = squareSize;
\r
2530 triangle[2].y = squareSize - steps;
\r
2532 for( i=0; i<steps; i++ ) {
\r
2533 BYTE r = r1 - (r1-r2) * i / steps;
\r
2534 BYTE g = g1 - (g1-g2) * i / steps;
\r
2535 BYTE b = b1 - (b1-b2) * i / steps;
\r
2537 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2538 hbrush_old = SelectObject( hdc, hbrush );
\r
2539 Polygon( hdc, triangle, 3 );
\r
2540 SelectObject( hdc, hbrush_old );
\r
2541 DeleteObject(hbrush);
\r
2546 SelectObject( hdc, hpen );
\r
2551 [AS] The method I use to create the bitmaps it a bit tricky, but it
\r
2552 seems to work ok. The main problem here is to find the "inside" of a chess
\r
2553 piece: follow the steps as explained below.
\r
2555 static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
\r
2559 COLORREF chroma = RGB(0xFF,0x00,0xFF);
\r
2563 int backColor = whitePieceColor;
\r
2564 int foreColor = blackPieceColor;
\r
2566 if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {
\r
2567 backColor = appData.fontBackColorWhite;
\r
2568 foreColor = appData.fontForeColorWhite;
\r
2570 else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {
\r
2571 backColor = appData.fontBackColorBlack;
\r
2572 foreColor = appData.fontForeColorBlack;
\r
2576 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2578 hbm_old = SelectObject( hdc, hbm );
\r
2582 rc.right = squareSize;
\r
2583 rc.bottom = squareSize;
\r
2585 /* Step 1: background is now black */
\r
2586 FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );
\r
2588 GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );
\r
2590 pt.x = (squareSize - sz.cx) / 2;
\r
2591 pt.y = (squareSize - sz.cy) / 2;
\r
2593 SetBkMode( hdc, TRANSPARENT );
\r
2594 SetTextColor( hdc, chroma );
\r
2595 /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */
\r
2596 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2598 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
\r
2599 /* Step 3: the area outside the piece is filled with white */
\r
2600 // FloodFill( hdc, 0, 0, chroma );
\r
2601 ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );
\r
2602 ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big
\r
2603 ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );
\r
2604 ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );
\r
2605 SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
\r
2607 Step 4: this is the tricky part, the area inside the piece is filled with black,
\r
2608 but if the start point is not inside the piece we're lost!
\r
2609 There should be a better way to do this... if we could create a region or path
\r
2610 from the fill operation we would be fine for example.
\r
2612 // FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );
\r
2613 ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );
\r
2615 { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */
\r
2616 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2617 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2619 SelectObject( dc2, bm2 );
\r
2620 BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy
\r
2621 BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2622 BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2623 BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2624 BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2627 DeleteObject( bm2 );
\r
2630 SetTextColor( hdc, 0 );
\r
2632 Step 5: some fonts have "disconnected" areas that are skipped by the fill:
\r
2633 draw the piece again in black for safety.
\r
2635 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2637 SelectObject( hdc, hbm_old );
\r
2639 if( hPieceMask[index] != NULL ) {
\r
2640 DeleteObject( hPieceMask[index] );
\r
2643 hPieceMask[index] = hbm;
\r
2646 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2648 SelectObject( hdc, hbm );
\r
2651 HDC dc1 = CreateCompatibleDC( hdc_window );
\r
2652 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2653 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2655 SelectObject( dc1, hPieceMask[index] );
\r
2656 SelectObject( dc2, bm2 );
\r
2657 FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );
\r
2658 BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );
\r
2661 Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves
\r
2662 the piece background and deletes (makes transparent) the rest.
\r
2663 Thanks to that mask, we are free to paint the background with the greates
\r
2664 freedom, as we'll be able to mask off the unwanted parts when finished.
\r
2665 We use this, to make gradients and give the pieces a "roundish" look.
\r
2667 SetPieceBackground( hdc, backColor, 2 );
\r
2668 BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );
\r
2672 DeleteObject( bm2 );
\r
2675 SetTextColor( hdc, foreColor );
\r
2676 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2678 SelectObject( hdc, hbm_old );
\r
2680 if( hPieceFace[index] != NULL ) {
\r
2681 DeleteObject( hPieceFace[index] );
\r
2684 hPieceFace[index] = hbm;
\r
2687 static int TranslatePieceToFontPiece( int piece )
\r
2717 case BlackMarshall:
\r
2721 case BlackNightrider:
\r
2727 case BlackUnicorn:
\r
2731 case BlackGrasshopper:
\r
2743 case BlackCardinal:
\r
2750 case WhiteMarshall:
\r
2754 case WhiteNightrider:
\r
2760 case WhiteUnicorn:
\r
2764 case WhiteGrasshopper:
\r
2776 case WhiteCardinal:
\r
2785 void CreatePiecesFromFont()
\r
2788 HDC hdc_window = NULL;
\r
2794 if( fontBitmapSquareSize < 0 ) {
\r
2795 /* Something went seriously wrong in the past: do not try to recreate fonts! */
\r
2799 if( appData.renderPiecesWithFont == NULL || appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {
\r
2800 fontBitmapSquareSize = -1;
\r
2804 if( fontBitmapSquareSize != squareSize ) {
\r
2805 hdc_window = GetDC( hwndMain );
\r
2806 hdc = CreateCompatibleDC( hdc_window );
\r
2808 if( hPieceFont != NULL ) {
\r
2809 DeleteObject( hPieceFont );
\r
2812 for( i=0; i<=(int)BlackKing; i++ ) {
\r
2813 hPieceMask[i] = NULL;
\r
2814 hPieceFace[i] = NULL;
\r
2820 if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {
\r
2821 fontHeight = appData.fontPieceSize;
\r
2824 fontHeight = (fontHeight * squareSize) / 100;
\r
2826 lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
\r
2828 lf.lfEscapement = 0;
\r
2829 lf.lfOrientation = 0;
\r
2830 lf.lfWeight = FW_NORMAL;
\r
2832 lf.lfUnderline = 0;
\r
2833 lf.lfStrikeOut = 0;
\r
2834 lf.lfCharSet = DEFAULT_CHARSET;
\r
2835 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
2836 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
2837 lf.lfQuality = PROOF_QUALITY;
\r
2838 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
\r
2839 strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );
\r
2840 lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';
\r
2842 hPieceFont = CreateFontIndirect( &lf );
\r
2844 if( hPieceFont == NULL ) {
\r
2845 fontBitmapSquareSize = -2;
\r
2848 /* Setup font-to-piece character table */
\r
2849 if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {
\r
2850 /* No (or wrong) global settings, try to detect the font */
\r
2851 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {
\r
2853 SetCharTable(pieceToFontChar, "phbrqkojntwl");
\r
2855 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {
\r
2856 /* DiagramTT* family */
\r
2857 SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");
\r
2859 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {
\r
2860 /* Fairy symbols */
\r
2861 SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
\r
2863 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {
\r
2864 /* Good Companion (Some characters get warped as literal :-( */
\r
2865 char s[] = "1cmWG0ñueOS¯®oYI23wgQU";
\r
2866 s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;
\r
2867 SetCharTable(pieceToFontChar, s);
\r
2870 /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */
\r
2871 SetCharTable(pieceToFontChar, "pnbrqkomvtwl");
\r
2875 /* Create bitmaps */
\r
2876 hfont_old = SelectObject( hdc, hPieceFont );
\r
2878 CreatePieceMaskFromFont( hdc_window, hdc, PM_WP );
\r
2879 CreatePieceMaskFromFont( hdc_window, hdc, PM_WN );
\r
2880 CreatePieceMaskFromFont( hdc_window, hdc, PM_WB );
\r
2881 CreatePieceMaskFromFont( hdc_window, hdc, PM_WR );
\r
2882 CreatePieceMaskFromFont( hdc_window, hdc, PM_WQ );
\r
2883 CreatePieceMaskFromFont( hdc_window, hdc, PM_WK );
\r
2884 CreatePieceMaskFromFont( hdc_window, hdc, PM_BP );
\r
2885 CreatePieceMaskFromFont( hdc_window, hdc, PM_BN );
\r
2886 CreatePieceMaskFromFont( hdc_window, hdc, PM_BB );
\r
2887 CreatePieceMaskFromFont( hdc_window, hdc, PM_BR );
\r
2888 CreatePieceMaskFromFont( hdc_window, hdc, PM_BQ );
\r
2889 CreatePieceMaskFromFont( hdc_window, hdc, PM_BK );
\r
2891 CreatePieceMaskFromFont( hdc_window, hdc, PM_WA );
\r
2892 CreatePieceMaskFromFont( hdc_window, hdc, PM_WC );
\r
2893 CreatePieceMaskFromFont( hdc_window, hdc, PM_WF );
\r
2894 CreatePieceMaskFromFont( hdc_window, hdc, PM_WH );
\r
2895 CreatePieceMaskFromFont( hdc_window, hdc, PM_WE );
\r
2896 CreatePieceMaskFromFont( hdc_window, hdc, PM_WW );
\r
2897 CreatePieceMaskFromFont( hdc_window, hdc, PM_WU );
\r
2898 CreatePieceMaskFromFont( hdc_window, hdc, PM_WO );
\r
2899 CreatePieceMaskFromFont( hdc_window, hdc, PM_WG );
\r
2900 CreatePieceMaskFromFont( hdc_window, hdc, PM_WM );
\r
2901 CreatePieceMaskFromFont( hdc_window, hdc, PM_WSG );
\r
2902 CreatePieceMaskFromFont( hdc_window, hdc, PM_WV );
\r
2903 CreatePieceMaskFromFont( hdc_window, hdc, PM_WAB );
\r
2904 CreatePieceMaskFromFont( hdc_window, hdc, PM_WD );
\r
2905 CreatePieceMaskFromFont( hdc_window, hdc, PM_WL );
\r
2906 CreatePieceMaskFromFont( hdc_window, hdc, PM_WS );
\r
2907 CreatePieceMaskFromFont( hdc_window, hdc, PM_BA );
\r
2908 CreatePieceMaskFromFont( hdc_window, hdc, PM_BC );
\r
2909 CreatePieceMaskFromFont( hdc_window, hdc, PM_BF );
\r
2910 CreatePieceMaskFromFont( hdc_window, hdc, PM_BH );
\r
2911 CreatePieceMaskFromFont( hdc_window, hdc, PM_BE );
\r
2912 CreatePieceMaskFromFont( hdc_window, hdc, PM_BW );
\r
2913 CreatePieceMaskFromFont( hdc_window, hdc, PM_BU );
\r
2914 CreatePieceMaskFromFont( hdc_window, hdc, PM_BO );
\r
2915 CreatePieceMaskFromFont( hdc_window, hdc, PM_BG );
\r
2916 CreatePieceMaskFromFont( hdc_window, hdc, PM_BM );
\r
2917 CreatePieceMaskFromFont( hdc_window, hdc, PM_BSG );
\r
2918 CreatePieceMaskFromFont( hdc_window, hdc, PM_BV );
\r
2919 CreatePieceMaskFromFont( hdc_window, hdc, PM_BAB );
\r
2920 CreatePieceMaskFromFont( hdc_window, hdc, PM_BD );
\r
2921 CreatePieceMaskFromFont( hdc_window, hdc, PM_BL );
\r
2922 CreatePieceMaskFromFont( hdc_window, hdc, PM_BS );
\r
2924 for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */
\r
2925 if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */
\r
2926 CreatePieceMaskFromFont( hdc_window, hdc, i );
\r
2928 SelectObject( hdc, hfont_old );
\r
2930 fontBitmapSquareSize = squareSize;
\r
2934 if( hdc != NULL ) {
\r
2938 if( hdc_window != NULL ) {
\r
2939 ReleaseDC( hwndMain, hdc_window );
\r
2944 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)
\r
2948 sprintf(name, "%s%d%s", piece, squareSize, suffix);
\r
2949 if (gameInfo.event &&
\r
2950 strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&
\r
2951 strcmp(name, "k80s") == 0) {
\r
2952 strcpy(name, "tim");
\r
2954 return LoadBitmap(hinst, name);
\r
2958 /* Insert a color into the program's logical palette
\r
2959 structure. This code assumes the given color is
\r
2960 the result of the RGB or PALETTERGB macro, and it
\r
2961 knows how those macros work (which is documented).
\r
2964 InsertInPalette(COLORREF color)
\r
2966 LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);
\r
2968 if (pLogPal->palNumEntries++ >= PALETTESIZE) {
\r
2969 DisplayFatalError("Too many colors", 0, 1);
\r
2970 pLogPal->palNumEntries--;
\r
2974 pe->peFlags = (char) 0;
\r
2975 pe->peRed = (char) (0xFF & color);
\r
2976 pe->peGreen = (char) (0xFF & (color >> 8));
\r
2977 pe->peBlue = (char) (0xFF & (color >> 16));
\r
2983 InitDrawingColors()
\r
2985 if (pLogPal == NULL) {
\r
2986 /* Allocate enough memory for a logical palette with
\r
2987 * PALETTESIZE entries and set the size and version fields
\r
2988 * of the logical palette structure.
\r
2990 pLogPal = (NPLOGPALETTE)
\r
2991 LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +
\r
2992 (sizeof(PALETTEENTRY) * (PALETTESIZE))));
\r
2993 pLogPal->palVersion = 0x300;
\r
2995 pLogPal->palNumEntries = 0;
\r
2997 InsertInPalette(lightSquareColor);
\r
2998 InsertInPalette(darkSquareColor);
\r
2999 InsertInPalette(whitePieceColor);
\r
3000 InsertInPalette(blackPieceColor);
\r
3001 InsertInPalette(highlightSquareColor);
\r
3002 InsertInPalette(premoveHighlightColor);
\r
3004 /* create a logical color palette according the information
\r
3005 * in the LOGPALETTE structure.
\r
3007 hPal = CreatePalette((LPLOGPALETTE) pLogPal);
\r
3009 lightSquareBrush = CreateSolidBrush(lightSquareColor);
\r
3010 blackSquareBrush = CreateSolidBrush(blackPieceColor);
\r
3011 darkSquareBrush = CreateSolidBrush(darkSquareColor);
\r
3012 whitePieceBrush = CreateSolidBrush(whitePieceColor);
\r
3013 blackPieceBrush = CreateSolidBrush(blackPieceColor);
\r
3014 iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
\r
3016 /* [AS] Force rendering of the font-based pieces */
\r
3017 if( fontBitmapSquareSize > 0 ) {
\r
3018 fontBitmapSquareSize = 0;
\r
3024 BoardWidth(int boardSize, int n)
\r
3025 { /* [HGM] argument n added to allow different width and height */
\r
3026 int lineGap = sizeInfo[boardSize].lineGap;
\r
3028 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3029 lineGap = appData.overrideLineGap;
\r
3032 return (n + 1) * lineGap +
\r
3033 n * sizeInfo[boardSize].squareSize;
\r
3036 /* Respond to board resize by dragging edge */
\r
3038 ResizeBoard(int newSizeX, int newSizeY, int flags)
\r
3040 BoardSize newSize = NUM_SIZES - 1;
\r
3041 static int recurse = 0;
\r
3042 if (IsIconic(hwndMain)) return;
\r
3043 if (recurse > 0) return;
\r
3045 while (newSize > 0) {
\r
3046 InitDrawingSizes(newSize+1000, 0); // [HGM] kludge to update sizeInfo without visible effects
\r
3047 if(newSizeX >= sizeInfo[newSize].cliWidth &&
\r
3048 newSizeY >= sizeInfo[newSize].cliHeight) break;
\r
3051 boardSize = newSize;
\r
3052 InitDrawingSizes(boardSize, flags);
\r
3059 InitDrawingSizes(BoardSize boardSize, int flags)
\r
3061 int i, boardWidth, boardHeight; /* [HGM] height treated separately */
\r
3062 ChessSquare piece;
\r
3063 static int oldBoardSize = -1, oldTinyLayout = 0;
\r
3065 SIZE clockSize, messageSize;
\r
3067 char buf[MSG_SIZ];
\r
3069 HMENU hmenu = GetMenu(hwndMain);
\r
3070 RECT crect, wrect;
\r
3072 LOGBRUSH logbrush;
\r
3074 int suppressVisibleEffects = 0; // [HGM] kludge to request updating sizeInfo only
\r
3075 if((int)boardSize >= 1000 ) { boardSize -= 1000; suppressVisibleEffects = 1; }
\r
3077 /* [HGM] call with -2 uses old size (for if nr of files, ranks changes) */
\r
3078 if(boardSize == (BoardSize)(-2) ) boardSize = oldBoardSize;
\r
3080 tinyLayout = sizeInfo[boardSize].tinyLayout;
\r
3081 smallLayout = sizeInfo[boardSize].smallLayout;
\r
3082 squareSize = sizeInfo[boardSize].squareSize;
\r
3083 lineGap = sizeInfo[boardSize].lineGap;
\r
3084 minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted */
\r
3086 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3087 lineGap = appData.overrideLineGap;
\r
3090 if (tinyLayout != oldTinyLayout) {
\r
3091 long style = GetWindowLong(hwndMain, GWL_STYLE);
\r
3093 style &= ~WS_SYSMENU;
\r
3094 InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize,
\r
3095 "&Minimize\tCtrl+F4");
\r
3097 style |= WS_SYSMENU;
\r
3098 RemoveMenu(hmenu, IDM_Minimize, MF_BYCOMMAND);
\r
3100 SetWindowLong(hwndMain, GWL_STYLE, style);
\r
3102 for (i=0; menuBarText[tinyLayout][i]; i++) {
\r
3103 ModifyMenu(hmenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP,
\r
3104 (UINT)GetSubMenu(hmenu, i), menuBarText[tinyLayout][i]);
\r
3106 DrawMenuBar(hwndMain);
\r
3109 boardWidth = BoardWidth(boardSize, BOARD_WIDTH);
\r
3110 boardHeight = BoardWidth(boardSize, BOARD_HEIGHT);
\r
3112 /* Get text area sizes */
\r
3113 hdc = GetDC(hwndMain);
\r
3114 if (appData.clockMode) {
\r
3115 sprintf(buf, "White: %s", TimeString(23*60*60*1000L));
\r
3117 sprintf(buf, "White");
\r
3119 oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);
\r
3120 GetTextExtentPoint(hdc, buf, strlen(buf), &clockSize);
\r
3121 SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);
\r
3122 str = "We only care about the height here";
\r
3123 GetTextExtentPoint(hdc, str, strlen(str), &messageSize);
\r
3124 SelectObject(hdc, oldFont);
\r
3125 ReleaseDC(hwndMain, hdc);
\r
3127 /* Compute where everything goes */
\r
3128 if(first.programLogo || second.programLogo) {
\r
3129 /* [HGM] logo: if either logo is on, reserve space for it */
\r
3130 logoHeight = 2*clockSize.cy;
\r
3131 leftLogoRect.left = OUTER_MARGIN;
\r
3132 leftLogoRect.right = leftLogoRect.left + 4*clockSize.cy;
\r
3133 leftLogoRect.top = OUTER_MARGIN;
\r
3134 leftLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3136 rightLogoRect.right = OUTER_MARGIN + boardWidth;
\r
3137 rightLogoRect.left = rightLogoRect.right - 4*clockSize.cy;
\r
3138 rightLogoRect.top = OUTER_MARGIN;
\r
3139 rightLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3142 blackRect.left = leftLogoRect.right;
\r
3143 blackRect.right = rightLogoRect.left;
\r
3144 blackRect.top = OUTER_MARGIN;
\r
3145 blackRect.bottom = blackRect.top + clockSize.cy;
\r
3147 whiteRect.left = blackRect.left ;
\r
3148 whiteRect.right = blackRect.right;
\r
3149 whiteRect.top = blackRect.bottom;
\r
3150 whiteRect.bottom = leftLogoRect.bottom;
\r
3152 whiteRect.left = OUTER_MARGIN;
\r
3153 whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2;
\r
3154 whiteRect.top = OUTER_MARGIN + logoHeight;
\r
3155 whiteRect.bottom = whiteRect.top + clockSize.cy;
\r
3157 blackRect.left = whiteRect.right + INNER_MARGIN;
\r
3158 blackRect.right = blackRect.left + boardWidth/2 - 1;
\r
3159 blackRect.top = whiteRect.top;
\r
3160 blackRect.bottom = whiteRect.bottom;
\r
3163 messageRect.left = OUTER_MARGIN + MESSAGE_LINE_LEFTMARGIN;
\r
3164 if (appData.showButtonBar) {
\r
3165 messageRect.right = OUTER_MARGIN + boardWidth // [HGM] logo: expressed independent of clock placement
\r
3166 - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN;
\r
3168 messageRect.right = OUTER_MARGIN + boardWidth;
\r
3170 messageRect.top = whiteRect.bottom + INNER_MARGIN;
\r
3171 messageRect.bottom = messageRect.top + messageSize.cy;
\r
3173 boardRect.left = OUTER_MARGIN;
\r
3174 boardRect.right = boardRect.left + boardWidth;
\r
3175 boardRect.top = messageRect.bottom + INNER_MARGIN;
\r
3176 boardRect.bottom = boardRect.top + boardHeight;
\r
3178 sizeInfo[boardSize].cliWidth = boardRect.right + OUTER_MARGIN;
\r
3179 sizeInfo[boardSize].cliHeight = boardRect.bottom + OUTER_MARGIN;
\r
3180 if(suppressVisibleEffects) return; // [HGM] when called for filling sizeInfo only
\r
3181 winWidth = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN;
\r
3182 winHeight = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) +
\r
3183 GetSystemMetrics(SM_CYCAPTION) + boardRect.bottom + OUTER_MARGIN;
\r
3184 GetWindowRect(hwndMain, &wrect);
\r
3185 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3186 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3187 /* compensate if menu bar wrapped */
\r
3188 GetClientRect(hwndMain, &crect);
\r
3189 offby = boardRect.bottom + OUTER_MARGIN - crect.bottom;
\r
3190 winHeight += offby;
\r
3192 case WMSZ_TOPLEFT:
\r
3193 SetWindowPos(hwndMain, NULL,
\r
3194 wrect.right - winWidth, wrect.bottom - winHeight,
\r
3195 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3198 case WMSZ_TOPRIGHT:
\r
3200 SetWindowPos(hwndMain, NULL,
\r
3201 wrect.left, wrect.bottom - winHeight,
\r
3202 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3205 case WMSZ_BOTTOMLEFT:
\r
3207 SetWindowPos(hwndMain, NULL,
\r
3208 wrect.right - winWidth, wrect.top,
\r
3209 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3212 case WMSZ_BOTTOMRIGHT:
\r
3216 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3217 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3222 for (i = 0; i < N_BUTTONS; i++) {
\r
3223 if (buttonDesc[i].hwnd != NULL) {
\r
3224 DestroyWindow(buttonDesc[i].hwnd);
\r
3225 buttonDesc[i].hwnd = NULL;
\r
3227 if (appData.showButtonBar) {
\r
3228 buttonDesc[i].hwnd =
\r
3229 CreateWindow("BUTTON", buttonDesc[i].label,
\r
3230 WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
\r
3231 boardRect.right - BUTTON_WIDTH*(N_BUTTONS-i),
\r
3232 messageRect.top, BUTTON_WIDTH, messageSize.cy, hwndMain,
\r
3233 (HMENU) buttonDesc[i].id,
\r
3234 (HINSTANCE) GetWindowLong(hwndMain, GWL_HINSTANCE), NULL);
\r
3236 SendMessage(buttonDesc[i].hwnd, WM_SETFONT,
\r
3237 (WPARAM)font[boardSize][MESSAGE_FONT]->hf,
\r
3238 MAKELPARAM(FALSE, 0));
\r
3240 if (buttonDesc[i].id == IDM_Pause)
\r
3241 hwndPause = buttonDesc[i].hwnd;
\r
3242 buttonDesc[i].wndproc = (WNDPROC)
\r
3243 SetWindowLong(buttonDesc[i].hwnd, GWL_WNDPROC, (LONG) ButtonProc);
\r
3246 if (gridPen != NULL) DeleteObject(gridPen);
\r
3247 if (highlightPen != NULL) DeleteObject(highlightPen);
\r
3248 if (premovePen != NULL) DeleteObject(premovePen);
\r
3249 if (lineGap != 0) {
\r
3250 logbrush.lbStyle = BS_SOLID;
\r
3251 logbrush.lbColor = RGB(0, 0, 0); /* grid pen color = black */
\r
3253 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3254 lineGap, &logbrush, 0, NULL);
\r
3255 logbrush.lbColor = highlightSquareColor;
\r
3257 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3258 lineGap, &logbrush, 0, NULL);
\r
3260 logbrush.lbColor = premoveHighlightColor;
\r
3262 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3263 lineGap, &logbrush, 0, NULL);
\r
3265 /* [HGM] Loop had to be split in part for vert. and hor. lines */
\r
3266 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
\r
3267 gridEndpoints[i*2].x = boardRect.left + lineGap / 2;
\r
3268 gridEndpoints[i*2].y = gridEndpoints[i*2 + 1].y =
\r
3269 boardRect.top + lineGap / 2 + (i * (squareSize + lineGap));
\r
3270 gridEndpoints[i*2 + 1].x = boardRect.left + lineGap / 2 +
\r
3271 BOARD_WIDTH * (squareSize + lineGap);
\r
3272 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3274 for (i = 0; i < BOARD_WIDTH + 1; i++) {
\r
3275 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].y = boardRect.top + lineGap / 2;
\r
3276 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].x =
\r
3277 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].x = boardRect.left +
\r
3278 lineGap / 2 + (i * (squareSize + lineGap));
\r
3279 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].y =
\r
3280 boardRect.top + BOARD_HEIGHT * (squareSize + lineGap);
\r
3281 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3285 /* [HGM] Licensing requirement */
\r
3287 if(gameInfo.variant == VariantGothic) GothicPopUp( GOTHIC, VariantGothic); else
\r
3290 if(gameInfo.variant == VariantFalcon) GothicPopUp( FALCON, VariantFalcon); else
\r
3292 GothicPopUp( "", VariantNormal);
\r
3295 /* if (boardSize == oldBoardSize) return; [HGM] variant might have changed */
\r
3296 oldBoardSize = boardSize;
\r
3297 oldTinyLayout = tinyLayout;
\r
3299 /* Load piece bitmaps for this board size */
\r
3300 for (i=0; i<=2; i++) {
\r
3301 for (piece = WhitePawn;
\r
3302 (int) piece < (int) BlackPawn;
\r
3303 piece = (ChessSquare) ((int) piece + 1)) {
\r
3304 if (pieceBitmap[i][piece] != NULL)
\r
3305 DeleteObject(pieceBitmap[i][piece]);
\r
3309 fontBitmapSquareSize = 0; /* [HGM] render: make sure pieces will be recreated, as we might need others now */
\r
3310 // Orthodox Chess pieces
\r
3311 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s");
\r
3312 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s");
\r
3313 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "s");
\r
3314 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "s");
\r
3315 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "s");
\r
3316 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "o");
\r
3317 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "o");
\r
3318 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "o");
\r
3319 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "o");
\r
3320 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "o");
\r
3321 pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "w");
\r
3322 pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "w");
\r
3323 pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "w");
\r
3324 pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w");
\r
3325 pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w");
\r
3326 if( !strcmp(appData.variant, "shogi") && (squareSize==72 || squareSize==49)) {
\r
3327 // in Shogi, Hijack the unused Queen for Lance
\r
3328 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3329 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3330 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3332 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s");
\r
3333 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o");
\r
3334 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w");
\r
3337 if(squareSize <= 72 && squareSize >= 33) {
\r
3338 /* A & C are available in most sizes now */
\r
3339 if(squareSize != 49 && squareSize != 72 && squareSize != 33) { // Vortex-like
\r
3340 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3341 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3342 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3343 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3344 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3345 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3346 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3347 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3348 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3349 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3350 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3351 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3352 } else { // Smirf-like
\r
3353 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "s");
\r
3354 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "o");
\r
3355 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "w");
\r
3357 if(gameInfo.variant == VariantGothic) { // Vortex-like
\r
3358 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3359 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3360 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3361 } else { // WinBoard standard
\r
3362 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s");
\r
3363 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o");
\r
3364 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "w");
\r
3369 if(squareSize==72 || squareSize==49 || squareSize==33) { /* experiment with some home-made bitmaps */
\r
3370 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "s");
\r
3371 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "o");
\r
3372 pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "w");
\r
3373 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "s");
\r
3374 pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "o");
\r
3375 pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3376 pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "s");
\r
3377 pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "o");
\r
3378 pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "w");
\r
3379 pieceBitmap[0][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "s");
\r
3380 pieceBitmap[1][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "o");
\r
3381 pieceBitmap[2][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "w");
\r
3382 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3383 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3384 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3385 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "s");
\r
3386 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "o");
\r
3387 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "w");
\r
3388 pieceBitmap[0][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "s");
\r
3389 pieceBitmap[1][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "o");
\r
3390 pieceBitmap[2][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "w");
\r
3391 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "s");
\r
3392 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "o");
\r
3393 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "w");
\r
3394 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3395 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3396 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3397 pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s");
\r
3398 pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o");
\r
3399 pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w");
\r
3401 if(gameInfo.variant == VariantShogi) { /* promoted Gold represemtations */
\r
3402 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s");
\r
3403 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "o");
\r
3404 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3405 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "s");
\r
3406 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "o");
\r
3407 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3408 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "s");
\r
3409 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "o");
\r
3410 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3411 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "s");
\r
3412 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "o");
\r
3413 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3415 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "s");
\r
3416 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "o");
\r
3417 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "w");
\r
3418 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "s");
\r
3419 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "o");
\r
3420 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "w");
\r
3421 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3422 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3423 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3424 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "s");
\r
3425 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "o");
\r
3426 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "w");
\r
3429 } else { /* other size, no special bitmaps available. Use smaller symbols */
\r
3430 if((int)boardSize < 2) minorSize = sizeInfo[0].squareSize;
\r
3431 else minorSize = sizeInfo[(int)boardSize - 2].squareSize;
\r
3432 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "s");
\r
3433 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "o");
\r
3434 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "w");
\r
3435 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "s");
\r
3436 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "o");
\r
3437 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "w");
\r
3438 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "s");
\r
3439 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "o");
\r
3440 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "w");
\r
3441 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "s");
\r
3442 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "o");
\r
3443 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "w");
\r
3447 if(gameInfo.variant == VariantShogi && squareSize == 58)
\r
3448 /* special Shogi support in this size */
\r
3449 { for (i=0; i<=2; i++) { /* replace all bitmaps */
\r
3450 for (piece = WhitePawn;
\r
3451 (int) piece < (int) BlackPawn;
\r
3452 piece = (ChessSquare) ((int) piece + 1)) {
\r
3453 if (pieceBitmap[i][piece] != NULL)
\r
3454 DeleteObject(pieceBitmap[i][piece]);
\r
3457 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3458 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3459 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3460 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3461 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3462 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3463 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r
3464 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");
\r
3465 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");
\r
3466 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");
\r
3467 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");
\r
3468 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");
\r
3469 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");
\r
3470 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");
\r
3471 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3472 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3473 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3474 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3475 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3476 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3477 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r
3478 pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");
\r
3479 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");
\r
3480 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");
\r
3481 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");
\r
3482 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");
\r
3483 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");
\r
3484 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");
\r
3485 pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "w");
\r
3486 pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "w");
\r
3487 pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3488 pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3489 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "w");
\r
3490 pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "w");
\r
3491 pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3492 pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3493 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "sp", squareSize, "w");
\r
3494 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "sn", squareSize, "w");
\r
3495 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3496 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3497 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "sl", squareSize, "w");
\r
3498 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3504 PieceBitmap(ChessSquare p, int kind)
\r
3506 if ((int) p >= (int) BlackPawn)
\r
3507 p = (ChessSquare) ((int) p - (int) BlackPawn + (int) WhitePawn);
\r
3509 return pieceBitmap[kind][(int) p];
\r
3512 /***************************************************************/
\r
3514 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
\r
3515 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
\r
3517 #define MIN3(a,b,c) (((a) < (b) && (a) < (c)) ? (a) : (((b) < (a) && (b) < (c)) ? (b) : (c)))
\r
3518 #define MAX3(a,b,c) (((a) > (b) && (a) > (c)) ? (a) : (((b) > (a) && (b) > (c)) ? (b) : (c)))
\r
3522 SquareToPos(int row, int column, int * x, int * y)
\r
3525 *x = boardRect.left + lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
\r
3526 *y = boardRect.top + lineGap + row * (squareSize + lineGap);
\r
3528 *x = boardRect.left + lineGap + column * (squareSize + lineGap);
\r
3529 *y = boardRect.top + lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
\r
3534 DrawCoordsOnDC(HDC hdc)
\r
3536 static char files[24] = {'0', '1','2','3','4','5','6','7','8','9','0','1','1','0','9','8','7','6','5','4','3','2','1','0'};
\r
3537 static char ranks[24] = {'l', 'k','j','i','h','g','f','e','d','c','b','a','a','b','c','d','e','f','g','h','i','j','k','l'};
\r
3538 char str[2] = { NULLCHAR, NULLCHAR };
\r
3539 int oldMode, oldAlign, x, y, start, i;
\r
3543 if (!appData.showCoords)
\r
3546 start = flipView ? 1-(ONE!='1') : 23+(ONE!='1')-BOARD_HEIGHT;
\r
3548 oldBrush = SelectObject(hdc, GetStockObject(BLACK_BRUSH));
\r
3549 oldMode = SetBkMode(hdc, (appData.monoMode ? OPAQUE : TRANSPARENT));
\r
3550 oldAlign = GetTextAlign(hdc);
\r
3551 oldFont = SelectObject(hdc, font[boardSize][COORD_FONT]->hf);
\r
3553 y = boardRect.top + lineGap;
\r
3554 x = boardRect.left + lineGap + gameInfo.holdingsWidth*(squareSize + lineGap);
\r
3556 SetTextAlign(hdc, TA_LEFT|TA_TOP);
\r
3557 for (i = 0; i < BOARD_HEIGHT; i++) {
\r
3558 str[0] = files[start + i];
\r
3559 ExtTextOut(hdc, x + 2, y + 1, 0, NULL, str, 1, NULL);
\r
3560 y += squareSize + lineGap;
\r
3563 start = flipView ? 12-(BOARD_RGHT-BOARD_LEFT) : 12;
\r
3565 SetTextAlign(hdc, TA_RIGHT|TA_BOTTOM);
\r
3566 for (i = 0; i < BOARD_RGHT - BOARD_LEFT; i++) {
\r
3567 str[0] = ranks[start + i];
\r
3568 ExtTextOut(hdc, x + squareSize - 2, y - 1, 0, NULL, str, 1, NULL);
\r
3569 x += squareSize + lineGap;
\r
3572 SelectObject(hdc, oldBrush);
\r
3573 SetBkMode(hdc, oldMode);
\r
3574 SetTextAlign(hdc, oldAlign);
\r
3575 SelectObject(hdc, oldFont);
\r
3579 DrawGridOnDC(HDC hdc)
\r
3583 if (lineGap != 0) {
\r
3584 oldPen = SelectObject(hdc, gridPen);
\r
3585 PolyPolyline(hdc, gridEndpoints, gridVertexCounts, BOARD_WIDTH+BOARD_HEIGHT + 2);
\r
3586 SelectObject(hdc, oldPen);
\r
3590 #define HIGHLIGHT_PEN 0
\r
3591 #define PREMOVE_PEN 1
\r
3594 DrawHighlightOnDC(HDC hdc, BOOLEAN on, int x, int y, int pen)
\r
3597 HPEN oldPen, hPen;
\r
3598 if (lineGap == 0) return;
\r
3600 x1 = boardRect.left +
\r
3601 lineGap/2 + ((BOARD_WIDTH-1)-x) * (squareSize + lineGap);
\r
3602 y1 = boardRect.top +
\r
3603 lineGap/2 + y * (squareSize + lineGap);
\r
3605 x1 = boardRect.left +
\r
3606 lineGap/2 + x * (squareSize + lineGap);
\r
3607 y1 = boardRect.top +
\r
3608 lineGap/2 + ((BOARD_HEIGHT-1)-y) * (squareSize + lineGap);
\r
3610 hPen = pen ? premovePen : highlightPen;
\r
3611 oldPen = SelectObject(hdc, on ? hPen : gridPen);
\r
3612 MoveToEx(hdc, x1, y1, NULL);
\r
3613 LineTo(hdc, x1 + squareSize + lineGap, y1);
\r
3614 LineTo(hdc, x1 + squareSize + lineGap, y1 + squareSize + lineGap);
\r
3615 LineTo(hdc, x1, y1 + squareSize + lineGap);
\r
3616 LineTo(hdc, x1, y1);
\r
3617 SelectObject(hdc, oldPen);
\r
3621 DrawHighlightsOnDC(HDC hdc)
\r
3624 for (i=0; i<2; i++) {
\r
3625 if (highlightInfo.sq[i].x >= 0 && highlightInfo.sq[i].y >= 0)
\r
3626 DrawHighlightOnDC(hdc, TRUE,
\r
3627 highlightInfo.sq[i].x, highlightInfo.sq[i].y,
\r
3630 for (i=0; i<2; i++) {
\r
3631 if (premoveHighlightInfo.sq[i].x >= 0 &&
\r
3632 premoveHighlightInfo.sq[i].y >= 0) {
\r
3633 DrawHighlightOnDC(hdc, TRUE,
\r
3634 premoveHighlightInfo.sq[i].x,
\r
3635 premoveHighlightInfo.sq[i].y,
\r
3641 /* Note: sqcolor is used only in monoMode */
\r
3642 /* Note that this code is largely duplicated in woptions.c,
\r
3643 function DrawSampleSquare, so that needs to be updated too */
\r
3645 DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, HDC tmphdc)
\r
3647 HBITMAP oldBitmap;
\r
3651 if (appData.blindfold) return;
\r
3653 /* [AS] Use font-based pieces if needed */
\r
3654 if( fontBitmapSquareSize >= 0 && squareSize > 32 ) {
\r
3655 /* Create piece bitmaps, or do nothing if piece set is up to date */
\r
3656 CreatePiecesFromFont();
\r