2 * WinBoard.c -- Windows NT front end to XBoard
\r
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
\r
5 * Massachusetts. Enhancements Copyright
\r
6 * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software
\r
9 * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,
\r
10 * which was written and is copyrighted by Wayne Christopher.
\r
12 * The following terms apply to Digital Equipment Corporation's copyright
\r
13 * interest in XBoard:
\r
14 * ------------------------------------------------------------------------
\r
15 * All Rights Reserved
\r
17 * Permission to use, copy, modify, and distribute this software and its
\r
18 * documentation for any purpose and without fee is hereby granted,
\r
19 * provided that the above copyright notice appear in all copies and that
\r
20 * both that copyright notice and this permission notice appear in
\r
21 * supporting documentation, and that the name of Digital not be
\r
22 * used in advertising or publicity pertaining to distribution of the
\r
23 * software without specific, written prior permission.
\r
25 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
\r
26 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
\r
27 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
\r
28 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
\r
29 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
\r
30 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
\r
32 * ------------------------------------------------------------------------
\r
34 * The following terms apply to the enhanced version of XBoard
\r
35 * distributed by the Free Software Foundation:
\r
36 * ------------------------------------------------------------------------
\r
38 * GNU XBoard is free software: you can redistribute it and/or modify
\r
39 * it under the terms of the GNU General Public License as published by
\r
40 * the Free Software Foundation, either version 3 of the License, or (at
\r
41 * your option) any later version.
\r
43 * GNU XBoard is distributed in the hope that it will be useful, but
\r
44 * WITHOUT ANY WARRANTY; without even the implied warranty of
\r
45 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
46 * General Public License for more details.
\r
48 * You should have received a copy of the GNU General Public License
\r
49 * along with this program. If not, see http://www.gnu.org/licenses/. *
\r
51 *------------------------------------------------------------------------
\r
52 ** See the file ChangeLog for a revision history. */
\r
56 #include <windows.h>
\r
57 #include <winuser.h>
\r
58 #include <winsock.h>
\r
59 #include <commctrl.h>
\r
65 #include <sys/stat.h>
\r
68 #include <commdlg.h>
\r
70 #include <richedit.h>
\r
71 #include <mmsystem.h>
\r
80 #include "winboard.h"
\r
81 #include "frontend.h"
\r
82 #include "backend.h"
\r
84 #include "wclipbrd.h"
\r
85 #include "wgamelist.h"
\r
86 #include "wedittags.h"
\r
87 #include "woptions.h"
\r
88 #include "wsockerr.h"
\r
89 #include "defaults.h"
\r
93 //void InitEngineUCI( const char * iniDir, ChessProgramState * cps );
\r
96 void mysrandom(unsigned int seed);
\r
98 extern int whiteFlag, blackFlag;
\r
99 Boolean flipClock = FALSE;
\r
101 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);
\r
102 VOID NewVariantPopup(HWND hwnd);
\r
103 int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,
\r
104 /*char*/int promoChar));
\r
105 void AnimateAtomicCapture(int fromX, int fromY, int toX, int toY, int nFrames);
\r
106 void DisplayMove P((int moveNumber));
\r
107 Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen));
\r
109 ChessSquare piece;
\r
110 POINT pos; /* window coordinates of current pos */
\r
111 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
112 POINT from; /* board coordinates of the piece's orig pos */
\r
113 POINT to; /* board coordinates of the piece's new pos */
\r
116 static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };
\r
119 POINT start; /* window coordinates of start pos */
\r
120 POINT pos; /* window coordinates of current pos */
\r
121 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
122 POINT from; /* board coordinates of the piece's orig pos */
\r
125 static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} };
\r
128 POINT sq[2]; /* board coordinates of from, to squares */
\r
131 static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} };
\r
132 static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };
\r
134 typedef struct { // [HGM] atomic
\r
135 int fromX, fromY, toX, toY, radius;
\r
138 static ExplodeInfo explodeInfo;
\r
140 /* Window class names */
\r
141 char szAppName[] = "WinBoard";
\r
142 char szConsoleName[] = "WBConsole";
\r
144 /* Title bar text */
\r
145 char szTitle[] = "WinBoard";
\r
146 char szConsoleTitle[] = "I C S Interaction";
\r
149 char *settingsFileName;
\r
150 BOOLEAN saveSettingsOnExit;
\r
151 char installDir[MSG_SIZ];
\r
153 BoardSize boardSize;
\r
154 BOOLEAN chessProgram;
\r
155 static int boardX, boardY;
\r
156 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
\r
157 static int squareSize, lineGap, minorSize;
\r
158 static int winWidth, winHeight, winW, winH;
\r
159 static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo
\r
160 static int logoHeight = 0;
\r
161 static char messageText[MESSAGE_TEXT_MAX];
\r
162 static int clockTimerEvent = 0;
\r
163 static int loadGameTimerEvent = 0;
\r
164 static int analysisTimerEvent = 0;
\r
165 static DelayedEventCallback delayedTimerCallback;
\r
166 static int delayedTimerEvent = 0;
\r
167 static int buttonCount = 2;
\r
168 char *icsTextMenuString;
\r
170 char *firstChessProgramNames;
\r
171 char *secondChessProgramNames;
\r
173 #define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */
\r
175 #define PALETTESIZE 256
\r
177 HINSTANCE hInst; /* current instance */
\r
178 HWND hwndMain = NULL; /* root window*/
\r
179 HWND hwndConsole = NULL;
\r
180 BOOLEAN alwaysOnTop = FALSE;
\r
182 COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
\r
183 blackPieceColor, highlightSquareColor, premoveHighlightColor;
\r
185 ColorClass currentColorClass;
\r
187 HWND hCommPort = NULL; /* currently open comm port */
\r
188 static HWND hwndPause; /* pause button */
\r
189 static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */
\r
190 static HBRUSH lightSquareBrush, darkSquareBrush,
\r
191 blackSquareBrush, /* [HGM] for band between board and holdings */
\r
192 explodeBrush, /* [HGM] atomic */
\r
193 whitePieceBrush, blackPieceBrush, iconBkgndBrush /*, outlineBrush*/;
\r
194 static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];
\r
195 static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];
\r
196 static HPEN gridPen = NULL;
\r
197 static HPEN highlightPen = NULL;
\r
198 static HPEN premovePen = NULL;
\r
199 static NPLOGPALETTE pLogPal;
\r
200 static BOOL paletteChanged = FALSE;
\r
201 static HICON iconWhite, iconBlack, iconCurrent;
\r
202 static int doingSizing = FALSE;
\r
203 static int lastSizing = 0;
\r
204 static int prevStderrPort;
\r
205 static HBITMAP userLogo;
\r
207 /* [AS] Support for background textures */
\r
208 #define BACK_TEXTURE_MODE_DISABLED 0
\r
209 #define BACK_TEXTURE_MODE_PLAIN 1
\r
210 #define BACK_TEXTURE_MODE_FULL_RANDOM 2
\r
212 static HBITMAP liteBackTexture = NULL;
\r
213 static HBITMAP darkBackTexture = NULL;
\r
214 static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
215 static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
216 static int backTextureSquareSize = 0;
\r
217 static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_SIZE][BOARD_SIZE];
\r
219 #if __GNUC__ && !defined(_winmajor)
\r
220 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */
\r
222 #define oldDialog (_winmajor < 4)
\r
225 char *defaultTextAttribs[] =
\r
227 COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,
\r
228 COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,
\r
238 int cliWidth, cliHeight;
\r
241 SizeInfo sizeInfo[] =
\r
243 { "tiny", 21, 0, 1, 1, 0, 0 },
\r
244 { "teeny", 25, 1, 1, 1, 0, 0 },
\r
245 { "dinky", 29, 1, 1, 1, 0, 0 },
\r
246 { "petite", 33, 1, 1, 1, 0, 0 },
\r
247 { "slim", 37, 2, 1, 0, 0, 0 },
\r
248 { "small", 40, 2, 1, 0, 0, 0 },
\r
249 { "mediocre", 45, 2, 1, 0, 0, 0 },
\r
250 { "middling", 49, 2, 0, 0, 0, 0 },
\r
251 { "average", 54, 2, 0, 0, 0, 0 },
\r
252 { "moderate", 58, 3, 0, 0, 0, 0 },
\r
253 { "medium", 64, 3, 0, 0, 0, 0 },
\r
254 { "bulky", 72, 3, 0, 0, 0, 0 },
\r
255 { "large", 80, 3, 0, 0, 0, 0 },
\r
256 { "big", 87, 3, 0, 0, 0, 0 },
\r
257 { "huge", 95, 3, 0, 0, 0, 0 },
\r
258 { "giant", 108, 3, 0, 0, 0, 0 },
\r
259 { "colossal", 116, 4, 0, 0, 0, 0 },
\r
260 { "titanic", 129, 4, 0, 0, 0, 0 },
\r
261 { NULL, 0, 0, 0, 0, 0, 0 }
\r
264 #define MF(x) {x, {{0,}, 0. }, {0, }, 0}
\r
265 MyFont fontRec[NUM_SIZES][NUM_FONTS] =
\r
267 { 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
268 { 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
269 { 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
270 { 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
271 { 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
272 { 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
273 { 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
274 { 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
275 { 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
276 { 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
277 { 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
278 { 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
279 { 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
280 { 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
281 { 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
282 { 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
283 { 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
284 { 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
287 MyFont *font[NUM_SIZES][NUM_FONTS];
\r
296 #define BUTTON_WIDTH (tinyLayout ? 16 : 32)
\r
297 #define N_BUTTONS 5
\r
299 MyButtonDesc buttonDesc[N_BUTTONS] =
\r
301 {"<<", IDM_ToStart, NULL, NULL},
\r
302 {"<", IDM_Backward, NULL, NULL},
\r
303 {"P", IDM_Pause, NULL, NULL},
\r
304 {">", IDM_Forward, NULL, NULL},
\r
305 {">>", IDM_ToEnd, NULL, NULL},
\r
308 int tinyLayout = 0, smallLayout = 0;
\r
309 #define MENU_BAR_ITEMS 6
\r
310 char *menuBarText[2][MENU_BAR_ITEMS+1] = {
\r
311 { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },
\r
312 { "&F", "&M", "&A", "&S", "&O", "&H", NULL },
\r
316 MySound sounds[(int)NSoundClasses];
\r
317 MyTextAttribs textAttribs[(int)NColorClasses];
\r
319 MyColorizeAttribs colorizeAttribs[] = {
\r
320 { (COLORREF)0, 0, "Shout Text" },
\r
321 { (COLORREF)0, 0, "SShout/CShout" },
\r
322 { (COLORREF)0, 0, "Channel 1 Text" },
\r
323 { (COLORREF)0, 0, "Channel Text" },
\r
324 { (COLORREF)0, 0, "Kibitz Text" },
\r
325 { (COLORREF)0, 0, "Tell Text" },
\r
326 { (COLORREF)0, 0, "Challenge Text" },
\r
327 { (COLORREF)0, 0, "Request Text" },
\r
328 { (COLORREF)0, 0, "Seek Text" },
\r
329 { (COLORREF)0, 0, "Normal Text" },
\r
330 { (COLORREF)0, 0, "None" }
\r
335 static char *commentTitle;
\r
336 static char *commentText;
\r
337 static int commentIndex;
\r
338 static Boolean editComment = FALSE;
\r
339 HWND commentDialog = NULL;
\r
340 BOOLEAN commentDialogUp = FALSE;
\r
341 static int commentX, commentY, commentH, commentW;
\r
343 static char *analysisTitle;
\r
344 static char *analysisText;
\r
345 HWND analysisDialog = NULL;
\r
346 BOOLEAN analysisDialogUp = FALSE;
\r
347 static int analysisX, analysisY, analysisH, analysisW;
\r
349 char errorTitle[MSG_SIZ];
\r
350 char errorMessage[2*MSG_SIZ];
\r
351 HWND errorDialog = NULL;
\r
352 BOOLEAN moveErrorMessageUp = FALSE;
\r
353 BOOLEAN consoleEcho = TRUE;
\r
354 CHARFORMAT consoleCF;
\r
355 COLORREF consoleBackgroundColor;
\r
357 char *programVersion;
\r
363 typedef int CPKind;
\r
372 SOCKET sock2; /* stderr socket for OpenRcmd */
\r
375 #define INPUT_SOURCE_BUF_SIZE 4096
\r
377 typedef struct _InputSource {
\r
384 char buf[INPUT_SOURCE_BUF_SIZE];
\r
388 InputCallback func;
\r
389 struct _InputSource *second; /* for stderr thread on CPRcmd */
\r
393 InputSource *consoleInputSource;
\r
398 VOID ConsoleOutput(char* data, int length, int forceVisible);
\r
399 VOID ConsoleCreate();
\r
401 ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
402 VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
\r
403 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
\r
404 VOID ParseCommSettings(char *arg, DCB *dcb);
\r
406 StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
407 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
\r
408 void ParseIcsTextMenu(char *icsTextMenuString);
\r
409 VOID PopUpMoveDialog(char firstchar);
\r
410 VOID PopUpNameDialog(char firstchar);
\r
411 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
\r
415 int GameListOptions();
\r
417 HWND moveHistoryDialog = NULL;
\r
418 BOOLEAN moveHistoryDialogUp = FALSE;
\r
420 WindowPlacement wpMoveHistory;
\r
422 HWND evalGraphDialog = NULL;
\r
423 BOOLEAN evalGraphDialogUp = FALSE;
\r
425 WindowPlacement wpEvalGraph;
\r
427 HWND engineOutputDialog = NULL;
\r
428 BOOLEAN engineOutputDialogUp = FALSE;
\r
430 WindowPlacement wpEngineOutput;
\r
431 WindowPlacement wpGameList;
\r
432 WindowPlacement wpConsole;
\r
434 VOID MoveHistoryPopUp();
\r
435 VOID MoveHistoryPopDown();
\r
436 VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
437 BOOL MoveHistoryIsUp();
\r
439 VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
440 VOID EvalGraphPopUp();
\r
441 VOID EvalGraphPopDown();
\r
442 BOOL EvalGraphIsUp();
\r
444 VOID EngineOutputPopUp();
\r
445 VOID EngineOutputPopDown();
\r
446 BOOL EngineOutputIsUp();
\r
447 VOID EngineOutputUpdate( FrontEndProgramStats * stats );
\r
449 VOID GothicPopUp(char *title, VariantClass variant);
\r
451 * Setting "frozen" should disable all user input other than deleting
\r
452 * the window. We do this while engines are initializing themselves.
\r
454 static int frozen = 0;
\r
455 static int oldMenuItemState[MENU_BAR_ITEMS];
\r
461 if (frozen) return;
\r
463 hmenu = GetMenu(hwndMain);
\r
464 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
465 oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
\r
467 DrawMenuBar(hwndMain);
\r
470 /* Undo a FreezeUI */
\r
476 if (!frozen) return;
\r
478 hmenu = GetMenu(hwndMain);
\r
479 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
480 EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
\r
482 DrawMenuBar(hwndMain);
\r
485 static int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them
\r
487 /* JAWS preparation patch (WinBoard for the sight impaired). Define required insertions as empty */
\r
492 #define JAWS_ALT_INTERCEPT
\r
493 #define JAWS_KB_NAVIGATION
\r
494 #define JAWS_MENU_ITEMS
\r
495 #define JAWS_SILENCE
\r
496 #define JAWS_REPLAY
\r
497 #define JAWS_DELETE(X) X
\r
498 #define SAYMACHINEMOVE()
\r
502 /*---------------------------------------------------------------------------*\
\r
506 \*---------------------------------------------------------------------------*/
\r
509 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
\r
510 LPSTR lpCmdLine, int nCmdShow)
\r
513 HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
\r
514 // INITCOMMONCONTROLSEX ex;
\r
518 LoadLibrary("RICHED32.DLL");
\r
519 consoleCF.cbSize = sizeof(CHARFORMAT);
\r
521 if (!InitApplication(hInstance)) {
\r
524 if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
\r
530 // InitCommonControlsEx(&ex);
\r
531 InitCommonControls();
\r
533 hAccelMain = LoadAccelerators (hInstance, szAppName);
\r
534 hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
\r
535 hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
\r
537 /* Acquire and dispatch messages until a WM_QUIT message is received. */
\r
539 while (GetMessage(&msg, /* message structure */
\r
540 NULL, /* handle of window receiving the message */
\r
541 0, /* lowest message to examine */
\r
542 0)) /* highest message to examine */
\r
545 if(msg.message == WM_CHAR && msg.wParam == '\t') {
\r
546 // [HGM] navigate: switch between all windows with tab
\r
547 HWND e1 = NULL, e2 = NULL, mh = NULL, hInput = NULL, hText = NULL;
\r
548 int i, currentElement = 0;
\r
550 // first determine what element of the chain we come from (if any)
\r
551 if(appData.icsActive) {
\r
552 hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);
\r
553 hText = GetDlgItem(hwndConsole, OPT_ConsoleText);
\r
555 if(engineOutputDialog && EngineOutputIsUp()) {
\r
556 e1 = GetDlgItem(engineOutputDialog, IDC_EngineMemo1);
\r
557 e2 = GetDlgItem(engineOutputDialog, IDC_EngineMemo2);
\r
559 if(moveHistoryDialog && MoveHistoryIsUp()) {
\r
560 mh = GetDlgItem(moveHistoryDialog, IDC_MoveHistory);
\r
562 if(msg.hwnd == hwndMain) currentElement = 7 ; else
\r
563 if(msg.hwnd == engineOutputDialog) currentElement = 2; else
\r
564 if(msg.hwnd == e1) currentElement = 2; else
\r
565 if(msg.hwnd == e2) currentElement = 3; else
\r
566 if(msg.hwnd == moveHistoryDialog) currentElement = 4; else
\r
567 if(msg.hwnd == mh) currentElement = 4; else
\r
568 if(msg.hwnd == evalGraphDialog) currentElement = 7; else
\r
569 if(msg.hwnd == hText) currentElement = 5; else
\r
570 if(msg.hwnd == hInput) currentElement = 6; else
\r
571 for (i = 0; i < N_BUTTONS; i++) {
\r
572 if (buttonDesc[i].hwnd == msg.hwnd) { currentElement = 1; break; }
\r
575 // determine where to go to
\r
576 if(currentElement) { HWND h = NULL; int direction = GetKeyState(VK_SHIFT) < 0 ? -1 : 1;
\r
578 currentElement = (currentElement + direction) % 7;
\r
579 switch(currentElement) {
\r
581 h = hwndMain; break; // passing this case always makes the loop exit
\r
583 h = buttonDesc[0].hwnd; break; // could be NULL
\r
585 if(!EngineOutputIsUp()) continue; // skip closed auxiliary windows
\r
588 if(!EngineOutputIsUp()) continue;
\r
591 if(!MoveHistoryIsUp()) continue;
\r
593 // case 5: // input to eval graph does not seem to get here!
\r
594 // if(!EvalGraphIsUp()) continue;
\r
595 // h = evalGraphDialog; break;
\r
597 if(!appData.icsActive) continue;
\r
601 if(!appData.icsActive) continue;
\r
607 if(currentElement > 4 && IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);
\r
608 if(currentElement < 5 && IsIconic(hwndMain)) ShowWindow(hwndMain, SW_RESTORE); // all open together
\r
611 continue; // this message now has been processed
\r
615 if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
\r
616 !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
\r
617 !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
\r
618 !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
\r
619 !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
\r
620 !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
\r
621 !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
\r
622 !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) &&
\r
623 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
\r
624 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
\r
625 TranslateMessage(&msg); /* Translates virtual key codes */
\r
626 DispatchMessage(&msg); /* Dispatches message to window */
\r
631 return (msg.wParam); /* Returns the value from PostQuitMessage */
\r
634 /*---------------------------------------------------------------------------*\
\r
636 * Initialization functions
\r
638 \*---------------------------------------------------------------------------*/
\r
642 { // update user logo if necessary
\r
643 static char oldUserName[MSG_SIZ], *curName;
\r
645 if(appData.autoLogo) {
\r
646 curName = UserName();
\r
647 if(strcmp(curName, oldUserName)) {
\r
648 sprintf(oldUserName, "logos\\%s.bmp", curName);
\r
649 userLogo = LoadImage( 0, oldUserName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
650 strcpy(oldUserName, curName);
\r
656 InitApplication(HINSTANCE hInstance)
\r
660 /* Fill in window class structure with parameters that describe the */
\r
663 wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
\r
664 wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
\r
665 wc.cbClsExtra = 0; /* No per-class extra data. */
\r
666 wc.cbWndExtra = 0; /* No per-window extra data. */
\r
667 wc.hInstance = hInstance; /* Owner of this class */
\r
668 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
669 wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
\r
670 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
\r
671 wc.lpszMenuName = szAppName; /* Menu name from .RC */
\r
672 wc.lpszClassName = szAppName; /* Name to register as */
\r
674 /* Register the window class and return success/failure code. */
\r
675 if (!RegisterClass(&wc)) return FALSE;
\r
677 wc.style = CS_HREDRAW | CS_VREDRAW;
\r
678 wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
\r
680 wc.cbWndExtra = DLGWINDOWEXTRA;
\r
681 wc.hInstance = hInstance;
\r
682 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
683 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
\r
684 wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
\r
685 wc.lpszMenuName = NULL;
\r
686 wc.lpszClassName = szConsoleName;
\r
688 if (!RegisterClass(&wc)) return FALSE;
\r
693 /* Set by InitInstance, used by EnsureOnScreen */
\r
694 int screenHeight, screenWidth;
\r
697 EnsureOnScreen(int *x, int *y, int minX, int minY)
\r
699 // int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
\r
700 /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
\r
701 if (*x > screenWidth - 32) *x = 0;
\r
702 if (*y > screenHeight - 32) *y = 0;
\r
703 if (*x < minX) *x = minX;
\r
704 if (*y < minY) *y = minY;
\r
708 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
\r
710 HWND hwnd; /* Main window handle. */
\r
712 WINDOWPLACEMENT wp;
\r
715 hInst = hInstance; /* Store instance handle in our global variable */
\r
717 if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
\r
718 *filepart = NULLCHAR;
\r
720 GetCurrentDirectory(MSG_SIZ, installDir);
\r
722 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise
\r
723 screenWidth = screenHeight = 1000; // [HGM] placement: kludge to allow calling EnsureOnScreen from InitAppData
\r
724 InitAppData(lpCmdLine); /* Get run-time parameters */
\r
725 if (appData.debugMode) {
\r
726 debugFP = fopen(appData.nameOfDebugFile, "w");
\r
727 setbuf(debugFP, NULL);
\r
732 // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()
\r
733 // InitEngineUCI( installDir, &second );
\r
735 /* Create a main window for this application instance. */
\r
736 hwnd = CreateWindow(szAppName, szTitle,
\r
737 (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
\r
738 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
\r
739 NULL, NULL, hInstance, NULL);
\r
742 /* If window could not be created, return "failure" */
\r
747 /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */
\r
748 if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {
\r
749 first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
751 if (first.programLogo == NULL && appData.debugMode) {
\r
752 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );
\r
754 } else if(appData.autoLogo) {
\r
755 if(appData.firstDirectory && appData.firstDirectory[0]) {
\r
757 sprintf(buf, "%s/logo.bmp", appData.firstDirectory);
\r
758 first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
762 if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {
\r
763 second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
765 if (second.programLogo == NULL && appData.debugMode) {
\r
766 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );
\r
768 } else if(appData.autoLogo) {
\r
770 if(appData.icsActive) { // [HGM] logo: in ICS mode second can be used for ICS
\r
771 sprintf(buf, "logos\\%s.bmp", appData.icsHost);
\r
772 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
774 if(appData.secondDirectory && appData.secondDirectory[0]) {
\r
775 sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);
\r
776 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
782 iconWhite = LoadIcon(hInstance, "icon_white");
\r
783 iconBlack = LoadIcon(hInstance, "icon_black");
\r
784 iconCurrent = iconWhite;
\r
785 InitDrawingColors();
\r
786 screenHeight = GetSystemMetrics(SM_CYSCREEN);
\r
787 screenWidth = GetSystemMetrics(SM_CXSCREEN);
\r
788 for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
\r
789 /* Compute window size for each board size, and use the largest
\r
790 size that fits on this screen as the default. */
\r
791 InitDrawingSizes((BoardSize)(ibs+1000), 0);
\r
792 if (boardSize == (BoardSize)-1 &&
\r
793 winH <= screenHeight
\r
794 - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10
\r
795 && winW <= screenWidth) {
\r
796 boardSize = (BoardSize)ibs;
\r
800 InitDrawingSizes(boardSize, 0);
\r
802 buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
\r
804 /* [AS] Load textures if specified */
\r
805 ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );
\r
807 if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {
\r
808 liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
809 liteBackTextureMode = appData.liteBackTextureMode;
\r
811 if (liteBackTexture == NULL && appData.debugMode) {
\r
812 fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );
\r
816 if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {
\r
817 darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
818 darkBackTextureMode = appData.darkBackTextureMode;
\r
820 if (darkBackTexture == NULL && appData.debugMode) {
\r
821 fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );
\r
825 mysrandom( (unsigned) time(NULL) );
\r
827 /* [AS] Restore layout */
\r
828 if( wpMoveHistory.visible ) {
\r
829 MoveHistoryPopUp();
\r
832 if( wpEvalGraph.visible ) {
\r
836 if( wpEngineOutput.visible ) {
\r
837 EngineOutputPopUp();
\r
842 /* Make the window visible; update its client area; and return "success" */
\r
843 EnsureOnScreen(&boardX, &boardY, minX, minY);
\r
844 wp.length = sizeof(WINDOWPLACEMENT);
\r
846 wp.showCmd = nCmdShow;
\r
847 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
\r
848 wp.rcNormalPosition.left = boardX;
\r
849 wp.rcNormalPosition.right = boardX + winWidth;
\r
850 wp.rcNormalPosition.top = boardY;
\r
851 wp.rcNormalPosition.bottom = boardY + winHeight;
\r
852 SetWindowPlacement(hwndMain, &wp);
\r
854 SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
855 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
859 SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
860 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
862 ShowWindow(hwndConsole, nCmdShow);
\r
864 UpdateWindow(hwnd);
\r
872 ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
\r
873 ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
\r
874 ArgSettingsFilename,
\r
875 ArgX, ArgY, ArgZ // [HGM] placement: for window-placement options stored relative to main window
\r
883 String *pString; // ArgString
\r
884 int *pInt; // ArgInt
\r
885 float *pFloat; // ArgFloat
\r
886 Boolean *pBoolean; // ArgBoolean
\r
887 COLORREF *pColor; // ArgColor
\r
888 ColorClass cc; // ArgAttribs
\r
889 String *pFilename; // ArgFilename
\r
890 BoardSize *pBoardSize; // ArgBoardSize
\r
891 int whichFont; // ArgFont
\r
892 DCB *pDCB; // ArgCommSettings
\r
893 String *pFilename; // ArgSettingsFilename
\r
901 ArgDescriptor argDescriptors[] = {
\r
902 /* positional arguments */
\r
903 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
904 { "", ArgNone, NULL },
\r
905 /* keyword arguments */
\r
906 { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },
\r
907 { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },
\r
908 { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },
\r
909 { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },
\r
910 { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },
\r
911 { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },
\r
912 { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },
\r
913 { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },
\r
914 { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },
\r
915 { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },
\r
916 { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },
\r
917 { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },
\r
918 { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },
\r
919 { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },
\r
920 { "initString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
921 { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
922 { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },
\r
923 { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,
\r
925 { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,
\r
927 { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,
\r
929 { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },
\r
930 { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,
\r
932 { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },
\r
933 { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
934 { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
935 { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
936 { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
937 { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },
\r
938 { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },
\r
939 { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
940 { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
941 { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
942 { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
943 { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
944 { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
945 { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
946 { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
947 { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
948 { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
949 /*!!bitmapDirectory?*/
\r
950 { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
951 { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
952 { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
953 { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
954 { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },
\r
955 { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },
\r
956 { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },
\r
957 { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },
\r
958 { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },
\r
959 { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },
\r
960 { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },
\r
961 { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },
\r
962 { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
963 { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
964 { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
965 { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
966 { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
967 { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
968 { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
969 { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
970 { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
971 { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
972 { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
973 { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
974 { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },
\r
975 { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },
\r
976 { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
977 { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
978 { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },
\r
979 { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },
\r
980 { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },
\r
981 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
982 { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
983 { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
984 { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
985 { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },
\r
986 { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },
\r
987 { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },
\r
988 { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },
\r
989 { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
990 { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
991 { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
992 { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
993 { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
994 { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
995 { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
996 { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
997 { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },
\r
998 { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },
\r
999 { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
1000 { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
1001 { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
1002 { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
1003 { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },
\r
1004 { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },
\r
1005 { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
1006 { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
1007 { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },
\r
1008 { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },
\r
1009 { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
1010 { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
1011 { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },
\r
1012 { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },
\r
1013 { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
1014 { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
1015 { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
1016 { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
1017 { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
1018 { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
1019 { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },
\r
1020 { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },
\r
1021 { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
1022 { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
1023 { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },
\r
1024 { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },
\r
1025 { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
1026 { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
1027 { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },
\r
1028 { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1029 { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1030 { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1031 { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },
\r
1032 { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1033 { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1034 { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1035 { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },
\r
1036 { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1037 { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1038 { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1039 { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },
\r
1040 { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1041 { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1042 { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1043 { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors,
\r
1044 FALSE }, /* only so that old WinBoard.ini files from betas can be read */
\r
1045 { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },
\r
1046 { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },
\r
1047 { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },
\r
1048 { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },
\r
1049 { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },
\r
1050 { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },
\r
1051 { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE }, /* [AS] */
\r
1052 { "boardSize", ArgBoardSize, (LPVOID) &boardSize,
\r
1053 TRUE }, /* must come after all fonts */
\r
1054 { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },
\r
1055 { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,
\r
1056 FALSE }, /* historical; kept only so old winboard.ini files will parse */
\r
1057 { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },
\r
1058 { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },
\r
1059 { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
1060 { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
1061 { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },
\r
1062 { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1063 { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1064 { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1065 { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },
\r
1066 { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },
\r
1067 { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
1068 { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
1069 { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },
\r
1070 { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },
\r
1071 { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
1072 { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
1073 { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },
\r
1074 { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },
\r
1075 { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
1076 { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
1077 { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },
\r
1078 { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },
\r
1079 { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
1080 { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
1081 { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },
\r
1082 { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1083 { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1084 { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1086 { "cmailGameName", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
1087 { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
1089 { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },
\r
1090 { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1091 { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1092 { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1093 { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },
\r
1094 { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1095 { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1096 { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1097 { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },
\r
1098 { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },
\r
1099 { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
1100 { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
1101 { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },
\r
1102 { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },
\r
1103 { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
1104 { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
1105 { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },
\r
1106 { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },
\r
1107 { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
1108 { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
1109 { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },
\r
1110 { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },
\r
1111 { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
1112 { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
1113 { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },
\r
1114 { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },
\r
1115 { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
1116 { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
1117 { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },
\r
1118 { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },
\r
1119 { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },
\r
1120 { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1121 { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1122 { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },
\r
1123 { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},
\r
1124 { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},
\r
1125 { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1126 { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1127 { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},
\r
1128 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1129 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1130 { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },
\r
1131 { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1132 { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1133 { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },
\r
1134 { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },
\r
1135 { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1136 { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1137 { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },
\r
1138 { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },
\r
1139 { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },
\r
1140 { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1141 { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1142 { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },
\r
1143 { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },
\r
1144 { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1145 { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1146 { "highlightLastMove", ArgBoolean,
\r
1147 (LPVOID) &appData.highlightLastMove, TRUE },
\r
1148 { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1149 { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1150 { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1151 { "highlightDragging", ArgBoolean,
\r
1152 (LPVOID) &appData.highlightDragging, TRUE },
\r
1153 { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },
\r
1154 { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1155 { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1156 { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },
\r
1157 { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },
\r
1158 { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1159 { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1160 { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },
\r
1161 { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },
\r
1162 { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },
\r
1163 { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },
\r
1164 { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },
\r
1165 { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },
\r
1166 { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },
\r
1167 { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },
\r
1168 { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },
\r
1169 { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },
\r
1170 { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },
\r
1171 { "soundShout", ArgFilename,
\r
1172 (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },
\r
1173 { "soundSShout", ArgFilename,
\r
1174 (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },
\r
1175 { "soundChannel1", ArgFilename,
\r
1176 (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },
\r
1177 { "soundChannel", ArgFilename,
\r
1178 (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },
\r
1179 { "soundKibitz", ArgFilename,
\r
1180 (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },
\r
1181 { "soundTell", ArgFilename,
\r
1182 (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },
\r
1183 { "soundChallenge", ArgFilename,
\r
1184 (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },
\r
1185 { "soundRequest", ArgFilename,
\r
1186 (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },
\r
1187 { "soundSeek", ArgFilename,
\r
1188 (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },
\r
1189 { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },
\r
1190 { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },
\r
1191 { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },
\r
1192 { "soundIcsLoss", ArgFilename,
\r
1193 (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },
\r
1194 { "soundIcsDraw", ArgFilename,
\r
1195 (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },
\r
1196 { "soundIcsUnfinished", ArgFilename,
\r
1197 (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},
\r
1198 { "soundIcsAlarm", ArgFilename,
\r
1199 (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },
\r
1200 { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },
\r
1201 { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },
\r
1202 { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1203 { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1204 { "reuseChessPrograms", ArgBoolean,
\r
1205 (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */
\r
1206 { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },
\r
1207 { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },
\r
1208 { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1209 { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1210 { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },
\r
1211 { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1212 { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1213 { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },
\r
1214 { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },
\r
1215 { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },
\r
1216 { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1217 { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1218 { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },
\r
1219 { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },
\r
1220 { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,
\r
1222 { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,
\r
1224 { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1225 { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1226 { "variant", ArgString, (LPVOID) &appData.variant, FALSE },
\r
1227 { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion, FALSE },
\r
1228 { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,FALSE },
\r
1229 { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },
\r
1230 { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },
\r
1231 { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1232 { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1233 /* [AS] New features */
\r
1234 { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE },
\r
1235 { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE },
\r
1236 { "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE },
\r
1237 { "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE },
\r
1238 { "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE },
\r
1239 { "darkBackTextureFile", ArgString, (LPVOID) &appData.darkBackTextureFile, TRUE },
\r
1240 { "liteBackTextureMode", ArgInt, (LPVOID) &appData.liteBackTextureMode, TRUE },
\r
1241 { "darkBackTextureMode", ArgInt, (LPVOID) &appData.darkBackTextureMode, TRUE },
\r
1242 { "renderPiecesWithFont", ArgString, (LPVOID) &appData.renderPiecesWithFont, TRUE },
\r
1243 { "fontPieceToCharTable", ArgString, (LPVOID) &appData.fontToPieceTable, TRUE },
\r
1244 { "fontPieceBackColorWhite", ArgColor, (LPVOID) &appData.fontBackColorWhite, TRUE },
\r
1245 { "fontPieceForeColorWhite", ArgColor, (LPVOID) &appData.fontForeColorWhite, TRUE },
\r
1246 { "fontPieceBackColorBlack", ArgColor, (LPVOID) &appData.fontBackColorBlack, TRUE },
\r
1247 { "fontPieceForeColorBlack", ArgColor, (LPVOID) &appData.fontForeColorBlack, TRUE },
\r
1248 { "fontPieceSize", ArgInt, (LPVOID) &appData.fontPieceSize, TRUE },
\r
1249 { "overrideLineGap", ArgInt, (LPVOID) &appData.overrideLineGap, TRUE },
\r
1250 { "adjudicateLossThreshold", ArgInt, (LPVOID) &appData.adjudicateLossThreshold, TRUE },
\r
1251 { "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE },
\r
1252 { "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE },
\r
1253 { "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1254 { "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1255 { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },
\r
1256 { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE },
\r
1257 { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE },
\r
1258 { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE },
\r
1259 { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE },
\r
1260 { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE },
\r
1261 { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE },
\r
1262 { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE },
\r
1263 { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE },
\r
1264 { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE },
\r
1265 { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE },
\r
1266 { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE },
\r
1267 { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE },
\r
1268 { "firstIsUCI", ArgBoolean, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1269 { "fUCI", ArgTrue, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1270 { "secondIsUCI", ArgBoolean, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1271 { "sUCI", ArgTrue, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1272 { "firstHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1273 { "fNoOwnBookUCI", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1274 { "firstXBook", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1275 { "secondHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1276 { "sNoOwnBookUCI", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1277 { "secondXBook", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1278 { "polyglotDir", ArgFilename, (LPVOID) &appData.polyglotDir, TRUE },
\r
1279 { "usePolyglotBook", ArgBoolean, (LPVOID) &appData.usePolyglotBook, TRUE },
\r
1280 { "polyglotBook", ArgFilename, (LPVOID) &appData.polyglotBook, TRUE },
\r
1281 { "defaultHashSize", ArgInt, (LPVOID) &appData.defaultHashSize, TRUE },
\r
1282 { "defaultCacheSizeEGTB", ArgInt, (LPVOID) &appData.defaultCacheSizeEGTB, TRUE },
\r
1283 { "defaultPathEGTB", ArgFilename, (LPVOID) &appData.defaultPathEGTB, TRUE },
\r
1285 /* [HGM] board-size, adjudication and misc. options */
\r
1286 { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE },
\r
1287 { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE },
\r
1288 { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE },
\r
1289 { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE },
\r
1290 { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE },
\r
1291 { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE },
\r
1292 { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE },
\r
1293 { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE },
\r
1294 { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE },
\r
1295 { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE },
\r
1296 { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE },
\r
1297 { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE },
\r
1298 { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE },
\r
1299 { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE },
\r
1300 { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE },
\r
1301 { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE },
\r
1302 { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE },
\r
1303 { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE },
\r
1304 { "userName", ArgString, (LPVOID) &appData.userName, FALSE },
\r
1305 { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE },
\r
1306 { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE },
\r
1307 { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE },
\r
1308 { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE },
\r
1309 { "niceEngines", ArgInt, (LPVOID) &appData.niceEngines, TRUE },
\r
1310 { "firstLogo", ArgFilename, (LPVOID) &appData.firstLogo, FALSE },
\r
1311 { "secondLogo", ArgFilename, (LPVOID) &appData.secondLogo, FALSE },
\r
1312 { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE },
\r
1313 { "firstOptions", ArgString, (LPVOID) &appData.firstOptions, FALSE },
\r
1314 { "secondOptions", ArgString, (LPVOID) &appData.secondOptions, FALSE },
\r
1315 { "firstNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride1, FALSE },
\r
1316 { "secondNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride2, FALSE },
\r
1319 { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },
\r
1320 { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },
\r
1321 { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1322 { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1323 { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },
\r
1324 { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },
\r
1325 { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1326 { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1327 { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },
\r
1328 { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },
\r
1329 { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },
\r
1330 { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE },
\r
1331 { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,
\r
1333 { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE },
\r
1334 { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE },
\r
1335 { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE },
\r
1336 { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1337 { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1338 { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE },
\r
1339 { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,
\r
1341 { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1342 { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1343 { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1344 { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE },
\r
1345 { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE },
\r
1346 { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1347 { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1348 { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1349 { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1350 { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE },
\r
1351 { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE },
\r
1352 { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1353 { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1354 { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },
\r
1355 { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },
\r
1356 { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },
\r
1357 { "zippyShortGame", ArgInt, (LPVOID)&appData.zippyShortGame, FALSE },
\r
1358 /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */
\r
1359 { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },
\r
1361 /* [HGM] options for broadcasting and time odds */
\r
1362 { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },
\r
1363 { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },
\r
1364 { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },
\r
1365 { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },
\r
1366 { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },
\r
1367 { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },
\r
1368 { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },
\r
1369 { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },
\r
1370 { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },
\r
1371 { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },
\r
1372 { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE },
\r
1374 // [HGM] placement: put all window layouts last in ini file, but man X,Y before all others
\r
1375 { "minX", ArgZ, (LPVOID) &minX, FALSE }, // [HGM] placement: to make suer auxialary windows can be placed
\r
1376 { "minY", ArgZ, (LPVOID) &minY, FALSE },
\r
1377 { "winWidth", ArgInt, (LPVOID) &winWidth, TRUE }, // [HGM] placement: dummies to remember right & bottom
\r
1378 { "winHeight", ArgInt, (LPVOID) &winHeight, TRUE }, // for attaching auxiliary windows to them
\r
1379 { "x", ArgInt, (LPVOID) &boardX, TRUE },
\r
1380 { "y", ArgInt, (LPVOID) &boardY, TRUE },
\r
1381 { "icsX", ArgX, (LPVOID) &wpConsole.x, TRUE },
\r
1382 { "icsY", ArgY, (LPVOID) &wpConsole.y, TRUE },
\r
1383 { "icsW", ArgInt, (LPVOID) &wpConsole.width, TRUE },
\r
1384 { "icsH", ArgInt, (LPVOID) &wpConsole.height, TRUE },
\r
1385 { "analysisX", ArgX, (LPVOID) &analysisX, FALSE }, // [HGM] placement: analysis window no longer exists
\r
1386 { "analysisY", ArgY, (LPVOID) &analysisY, FALSE }, // provided for compatibility with old ini files
\r
1387 { "analysisW", ArgInt, (LPVOID) &analysisW, FALSE },
\r
1388 { "analysisH", ArgInt, (LPVOID) &analysisH, FALSE },
\r
1389 { "commentX", ArgX, (LPVOID) &commentX, TRUE },
\r
1390 { "commentY", ArgY, (LPVOID) &commentY, TRUE },
\r
1391 { "commentW", ArgInt, (LPVOID) &commentW, TRUE },
\r
1392 { "commentH", ArgInt, (LPVOID) &commentH, TRUE },
\r
1393 { "tagsX", ArgX, (LPVOID) &editTagsX, TRUE },
\r
1394 { "tagsY", ArgY, (LPVOID) &editTagsY, TRUE },
\r
1395 { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },
\r
1396 { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },
\r
1397 { "gameListX", ArgX, (LPVOID) &wpGameList.x, TRUE },
\r
1398 { "gameListY", ArgY, (LPVOID) &wpGameList.y, TRUE },
\r
1399 { "gameListW", ArgInt, (LPVOID) &wpGameList.width, TRUE },
\r
1400 { "gameListH", ArgInt, (LPVOID) &wpGameList.height, TRUE },
\r
1401 /* [AS] Layout stuff */
\r
1402 { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },
\r
1403 { "moveHistoryX", ArgX, (LPVOID) &wpMoveHistory.x, TRUE },
\r
1404 { "moveHistoryY", ArgY, (LPVOID) &wpMoveHistory.y, TRUE },
\r
1405 { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },
\r
1406 { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },
\r
1408 { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },
\r
1409 { "evalGraphX", ArgX, (LPVOID) &wpEvalGraph.x, TRUE },
\r
1410 { "evalGraphY", ArgY, (LPVOID) &wpEvalGraph.y, TRUE },
\r
1411 { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },
\r
1412 { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },
\r
1414 { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },
\r
1415 { "engineOutputX", ArgX, (LPVOID) &wpEngineOutput.x, TRUE },
\r
1416 { "engineOutputY", ArgY, (LPVOID) &wpEngineOutput.y, TRUE },
\r
1417 { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },
\r
1418 { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },
\r
1420 { NULL, ArgNone, NULL, FALSE }
\r
1424 /* Kludge for indirection files on command line */
\r
1425 char* lastIndirectionFilename;
\r
1426 ArgDescriptor argDescriptorIndirection =
\r
1427 { "", ArgSettingsFilename, (LPVOID) NULL, FALSE };
\r
1431 ExitArgError(char *msg, char *badArg)
\r
1433 char buf[MSG_SIZ];
\r
1435 sprintf(buf, "%s %s", msg, badArg);
\r
1436 DisplayFatalError(buf, 0, 2);
\r
1440 /* Command line font name parser. NULL name means do nothing.
\r
1441 Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"
\r
1442 For backward compatibility, syntax without the colon is also
\r
1443 accepted, but font names with digits in them won't work in that case.
\r
1446 ParseFontName(char *name, MyFontParams *mfp)
\r
1449 if (name == NULL) return;
\r
1451 q = strchr(p, ':');
\r
1453 if (q - p >= sizeof(mfp->faceName))
\r
1454 ExitArgError("Font name too long:", name);
\r
1455 memcpy(mfp->faceName, p, q - p);
\r
1456 mfp->faceName[q - p] = NULLCHAR;
\r
1459 q = mfp->faceName;
\r
1460 while (*p && !isdigit(*p)) {
\r
1462 if (q - mfp->faceName >= sizeof(mfp->faceName))
\r
1463 ExitArgError("Font name too long:", name);
\r
1465 while (q > mfp->faceName && q[-1] == ' ') q--;
\r
1468 if (!*p) ExitArgError("Font point size missing:", name);
\r
1469 mfp->pointSize = (float) atof(p);
\r
1470 mfp->bold = (strchr(p, 'b') != NULL);
\r
1471 mfp->italic = (strchr(p, 'i') != NULL);
\r
1472 mfp->underline = (strchr(p, 'u') != NULL);
\r
1473 mfp->strikeout = (strchr(p, 's') != NULL);
\r
1476 /* Color name parser.
\r
1477 X version accepts X color names, but this one
\r
1478 handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */
\r
1480 ParseColorName(char *name)
\r
1482 int red, green, blue, count;
\r
1483 char buf[MSG_SIZ];
\r
1485 count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);
\r
1487 count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d",
\r
1488 &red, &green, &blue);
\r
1491 sprintf(buf, "Can't parse color name %s", name);
\r
1492 DisplayError(buf, 0);
\r
1493 return RGB(0, 0, 0);
\r
1495 return PALETTERGB(red, green, blue);
\r
1499 void ParseAttribs(COLORREF *color, int *effects, char* argValue)
\r
1501 char *e = argValue;
\r
1505 if (*e == 'b') eff |= CFE_BOLD;
\r
1506 else if (*e == 'i') eff |= CFE_ITALIC;
\r
1507 else if (*e == 'u') eff |= CFE_UNDERLINE;
\r
1508 else if (*e == 's') eff |= CFE_STRIKEOUT;
\r
1509 else if (*e == '#' || isdigit(*e)) break;
\r
1513 *color = ParseColorName(e);
\r
1518 ParseBoardSize(char *name)
\r
1520 BoardSize bs = SizeTiny;
\r
1521 while (sizeInfo[bs].name != NULL) {
\r
1522 if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;
\r
1525 ExitArgError("Unrecognized board size value", name);
\r
1526 return bs; /* not reached */
\r
1531 StringGet(void *getClosure)
\r
1533 char **p = (char **) getClosure;
\r
1538 FileGet(void *getClosure)
\r
1541 FILE* f = (FILE*) getClosure;
\r
1544 if (c == '\r') c = getc(f); // work around DOS format files by bypassing the '\r' completely
\r
1551 /* Parse settings file named "name". If file found, return the
\r
1552 full name in fullname and return TRUE; else return FALSE */
\r
1554 ParseSettingsFile(char *name, char fullname[MSG_SIZ])
\r
1558 int ok; char buf[MSG_SIZ];
\r
1560 ok = SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy);
\r
1561 if(!ok && strchr(name, '.') == NULL) { // [HGM] append default file-name extension '.ini' when needed
\r
1562 sprintf(buf, "%s.ini", name);
\r
1563 ok = SearchPath(installDir, buf, NULL, MSG_SIZ, fullname, &dummy);
\r
1566 f = fopen(fullname, "r");
\r
1568 ParseArgs(FileGet, f);
\r
1577 ParseArgs(GetFunc get, void *cl)
\r
1579 char argName[ARG_MAX];
\r
1580 char argValue[ARG_MAX];
\r
1581 ArgDescriptor *ad;
\r
1590 while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);
\r
1591 if (ch == NULLCHAR) break;
\r
1593 /* Comment to end of line */
\r
1595 while (ch != '\n' && ch != NULLCHAR) ch = get(cl);
\r
1597 } else if (ch == '/' || ch == '-') {
\r
1600 while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&
\r
1601 ch != '\n' && ch != '\t') {
\r
1607 for (ad = argDescriptors; ad->argName != NULL; ad++)
\r
1608 if (strcmp(ad->argName, argName + 1) == 0) break;
\r
1610 if (ad->argName == NULL)
\r
1611 ExitArgError("Unrecognized argument", argName);
\r
1613 } else if (ch == '@') {
\r
1614 /* Indirection file */
\r
1615 ad = &argDescriptorIndirection;
\r
1618 /* Positional argument */
\r
1619 ad = &argDescriptors[posarg++];
\r
1620 strcpy(argName, ad->argName);
\r
1623 if (ad->argType == ArgTrue) {
\r
1624 *(Boolean *) ad->argLoc = TRUE;
\r
1627 if (ad->argType == ArgFalse) {
\r
1628 *(Boolean *) ad->argLoc = FALSE;
\r
1632 while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
\r
1633 if (ch == NULLCHAR || ch == '\n') {
\r
1634 ExitArgError("No value provided for argument", argName);
\r
1638 // Quoting with { }. No characters have to (or can) be escaped.
\r
1639 // Thus the string cannot contain a '}' character.
\r
1659 } else if (ch == '\'' || ch == '"') {
\r
1660 // Quoting with ' ' or " ", with \ as escape character.
\r
1661 // Inconvenient for long strings that may contain Windows filenames.
\r
1678 if (ch == start) {
\r
1687 if (ad->argType == ArgFilename
\r
1688 || ad->argType == ArgSettingsFilename) {
\r
1694 ExitArgError("Incomplete \\ escape in value for", argName);
\r
1718 for (i = 0; i < 3; i++) {
\r
1719 if (ch >= '0' && ch <= '7') {
\r
1720 octval = octval*8 + (ch - '0');
\r
1727 *q++ = (char) octval;
\r
1738 while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {
\r
1745 switch (ad->argType) {
\r
1747 *(int *) ad->argLoc = atoi(argValue);
\r
1751 *(int *) ad->argLoc = atoi(argValue) + boardX; // [HGM] placement: translate stored relative to absolute
\r
1755 *(int *) ad->argLoc = atoi(argValue) + boardY; // (this is really kludgey, it should be done where used...)
\r
1759 *(int *) ad->argLoc = atoi(argValue);
\r
1760 EnsureOnScreen(&boardX, &boardY, minX, minY);
\r
1764 *(float *) ad->argLoc = (float) atof(argValue);
\r
1769 *(char **) ad->argLoc = strdup(argValue);
\r
1772 case ArgSettingsFilename:
\r
1774 char fullname[MSG_SIZ];
\r
1775 if (ParseSettingsFile(argValue, fullname)) {
\r
1776 if (ad->argLoc != NULL) {
\r
1777 *(char **) ad->argLoc = strdup(fullname);
\r
1780 if (ad->argLoc != NULL) {
\r
1782 ExitArgError("Failed to open indirection file", argValue);
\r
1789 switch (argValue[0]) {
\r
1792 *(Boolean *) ad->argLoc = TRUE;
\r
1796 *(Boolean *) ad->argLoc = FALSE;
\r
1799 ExitArgError("Unrecognized boolean argument value", argValue);
\r
1805 *(COLORREF *)ad->argLoc = ParseColorName(argValue);
\r
1808 case ArgAttribs: {
\r
1809 ColorClass cc = (ColorClass)ad->argLoc;
\r
1810 ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);
\r
1814 case ArgBoardSize:
\r
1815 *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);
\r
1819 ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);
\r
1822 case ArgCommSettings:
\r
1823 ParseCommSettings(argValue, &dcb);
\r
1827 ExitArgError("Unrecognized argument", argValue);
\r
1836 LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
\r
1838 HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
\r
1839 lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);
\r
1842 lf->lfEscapement = 0;
\r
1843 lf->lfOrientation = 0;
\r
1844 lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;
\r
1845 lf->lfItalic = mfp->italic;
\r
1846 lf->lfUnderline = mfp->underline;
\r
1847 lf->lfStrikeOut = mfp->strikeout;
\r
1848 lf->lfCharSet = DEFAULT_CHARSET;
\r
1849 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
1850 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
1851 lf->lfQuality = DEFAULT_QUALITY;
\r
1852 lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
\r
1853 strcpy(lf->lfFaceName, mfp->faceName);
\r
1857 CreateFontInMF(MyFont *mf)
\r
1859 LFfromMFP(&mf->lf, &mf->mfp);
\r
1860 if (mf->hf) DeleteObject(mf->hf);
\r
1861 mf->hf = CreateFontIndirect(&mf->lf);
\r
1865 SetDefaultTextAttribs()
\r
1868 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1869 ParseAttribs(&textAttribs[cc].color,
\r
1870 &textAttribs[cc].effects,
\r
1871 defaultTextAttribs[cc]);
\r
1876 SetDefaultSounds()
\r
1880 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1881 textAttribs[cc].sound.name = strdup("");
\r
1882 textAttribs[cc].sound.data = NULL;
\r
1884 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1885 sounds[sc].name = strdup("");
\r
1886 sounds[sc].data = NULL;
\r
1888 sounds[(int)SoundBell].name = strdup(SOUND_BELL);
\r
1896 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1897 MyLoadSound(&textAttribs[cc].sound);
\r
1899 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1900 MyLoadSound(&sounds[sc]);
\r
1905 InitAppData(LPSTR lpCmdLine)
\r
1908 char buf[ARG_MAX], currDir[MSG_SIZ];
\r
1911 programName = szAppName;
\r
1913 /* Initialize to defaults */
\r
1914 lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);
\r
1915 darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);
\r
1916 whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);
\r
1917 blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);
\r
1918 highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);
\r
1919 premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);
\r
1920 consoleBackgroundColor = ParseColorName(COLOR_BKGD);
\r
1921 SetDefaultTextAttribs();
\r
1922 SetDefaultSounds();
\r
1923 appData.movesPerSession = MOVES_PER_SESSION;
\r
1924 appData.initString = INIT_STRING;
\r
1925 appData.secondInitString = INIT_STRING;
\r
1926 appData.firstComputerString = COMPUTER_STRING;
\r
1927 appData.secondComputerString = COMPUTER_STRING;
\r
1928 appData.firstChessProgram = FIRST_CHESS_PROGRAM;
\r
1929 appData.secondChessProgram = SECOND_CHESS_PROGRAM;
\r
1930 appData.firstPlaysBlack = FALSE;
\r
1931 appData.noChessProgram = FALSE;
\r
1932 chessProgram = FALSE;
\r
1933 appData.firstHost = FIRST_HOST;
\r
1934 appData.secondHost = SECOND_HOST;
\r
1935 appData.firstDirectory = FIRST_DIRECTORY;
\r
1936 appData.secondDirectory = SECOND_DIRECTORY;
\r
1937 appData.bitmapDirectory = "";
\r
1938 appData.remoteShell = REMOTE_SHELL;
\r
1939 appData.remoteUser = "";
\r
1940 appData.timeDelay = TIME_DELAY;
\r
1941 appData.timeControl = TIME_CONTROL;
\r
1942 appData.timeIncrement = TIME_INCREMENT;
\r
1943 appData.icsActive = FALSE;
\r
1944 appData.icsHost = "";
\r
1945 appData.icsPort = ICS_PORT;
\r
1946 appData.icsCommPort = ICS_COMM_PORT;
\r
1947 appData.icsLogon = ICS_LOGON;
\r
1948 appData.icsHelper = "";
\r
1949 appData.useTelnet = FALSE;
\r
1950 appData.telnetProgram = TELNET_PROGRAM;
\r
1951 appData.gateway = "";
\r
1952 appData.loadGameFile = "";
\r
1953 appData.loadGameIndex = 0;
\r
1954 appData.saveGameFile = "";
\r
1955 appData.autoSaveGames = FALSE;
\r
1956 appData.loadPositionFile = "";
\r
1957 appData.loadPositionIndex = 1;
\r
1958 appData.savePositionFile = "";
\r
1959 appData.matchMode = FALSE;
\r
1960 appData.matchGames = 0;
\r
1961 appData.monoMode = FALSE;
\r
1962 appData.debugMode = FALSE;
\r
1963 appData.clockMode = TRUE;
\r
1964 boardSize = (BoardSize) -1; /* determine by screen size */
\r
1965 appData.Iconic = FALSE; /*unused*/
\r
1966 appData.searchTime = "";
\r
1967 appData.searchDepth = 0;
\r
1968 appData.showCoords = FALSE;
\r
1969 appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/
\r
1970 appData.autoCallFlag = FALSE;
\r
1971 appData.flipView = FALSE;
\r
1972 appData.autoFlipView = TRUE;
\r
1973 appData.cmailGameName = "";
\r
1974 appData.alwaysPromoteToQueen = FALSE;
\r
1975 appData.oldSaveStyle = FALSE;
\r
1976 appData.quietPlay = FALSE;
\r
1977 appData.showThinking = FALSE;
\r
1978 appData.ponderNextMove = TRUE;
\r
1979 appData.periodicUpdates = TRUE;
\r
1980 appData.popupExitMessage = TRUE;
\r
1981 appData.popupMoveErrors = FALSE;
\r
1982 appData.autoObserve = FALSE;
\r
1983 appData.autoComment = FALSE;
\r
1984 appData.animate = TRUE;
\r
1985 appData.animSpeed = 10;
\r
1986 appData.animateDragging = TRUE;
\r
1987 appData.highlightLastMove = TRUE;
\r
1988 appData.getMoveList = TRUE;
\r
1989 appData.testLegality = TRUE;
\r
1990 appData.premove = TRUE;
\r
1991 appData.premoveWhite = FALSE;
\r
1992 appData.premoveWhiteText = "";
\r
1993 appData.premoveBlack = FALSE;
\r
1994 appData.premoveBlackText = "";
\r
1995 appData.icsAlarm = TRUE;
\r
1996 appData.icsAlarmTime = 5000;
\r
1997 appData.autoRaiseBoard = TRUE;
\r
1998 appData.localLineEditing = TRUE;
\r
1999 appData.colorize = TRUE;
\r
2000 appData.reuseFirst = TRUE;
\r
2001 appData.reuseSecond = TRUE;
\r
2002 appData.blindfold = FALSE;
\r
2003 appData.icsEngineAnalyze = FALSE;
\r
2004 memset(&dcb, 0, sizeof(DCB)); // required by VS 2002 +
\r
2005 dcb.DCBlength = sizeof(DCB);
\r
2006 dcb.BaudRate = 9600;
\r
2007 dcb.fBinary = TRUE;
\r
2008 dcb.fParity = FALSE;
\r
2009 dcb.fOutxCtsFlow = FALSE;
\r
2010 dcb.fOutxDsrFlow = FALSE;
\r
2011 dcb.fDtrControl = DTR_CONTROL_ENABLE;
\r
2012 dcb.fDsrSensitivity = FALSE;
\r
2013 dcb.fTXContinueOnXoff = TRUE;
\r
2014 dcb.fOutX = FALSE;
\r
2016 dcb.fNull = FALSE;
\r
2017 dcb.fRtsControl = RTS_CONTROL_ENABLE;
\r
2018 dcb.fAbortOnError = FALSE;
\r
2020 dcb.Parity = SPACEPARITY;
\r
2021 dcb.StopBits = ONESTOPBIT;
\r
2022 settingsFileName = SETTINGS_FILE;
\r
2023 saveSettingsOnExit = TRUE;
\r
2024 boardX = CW_USEDEFAULT;
\r
2025 boardY = CW_USEDEFAULT;
\r
2026 analysisX = CW_USEDEFAULT;
\r
2027 analysisY = CW_USEDEFAULT;
\r
2028 analysisW = CW_USEDEFAULT;
\r
2029 analysisH = CW_USEDEFAULT;
\r
2030 commentX = CW_USEDEFAULT;
\r
2031 commentY = CW_USEDEFAULT;
\r
2032 commentW = CW_USEDEFAULT;
\r
2033 commentH = CW_USEDEFAULT;
\r
2034 editTagsX = CW_USEDEFAULT;
\r
2035 editTagsY = CW_USEDEFAULT;
\r
2036 editTagsW = CW_USEDEFAULT;
\r
2037 editTagsH = CW_USEDEFAULT;
\r
2038 icsTextMenuString = ICS_TEXT_MENU_DEFAULT;
\r
2039 icsNames = ICS_NAMES;
\r
2040 firstChessProgramNames = FCP_NAMES;
\r
2041 secondChessProgramNames = SCP_NAMES;
\r
2042 appData.initialMode = "";
\r
2043 appData.variant = "normal";
\r
2044 appData.firstProtocolVersion = PROTOVER;
\r
2045 appData.secondProtocolVersion = PROTOVER;
\r
2046 appData.showButtonBar = TRUE;
\r
2048 /* [AS] New properties (see comments in header file) */
\r
2049 appData.firstScoreIsAbsolute = FALSE;
\r
2050 appData.secondScoreIsAbsolute = FALSE;
\r
2051 appData.saveExtendedInfoInPGN = FALSE;
\r
2052 appData.hideThinkingFromHuman = FALSE;
\r
2053 appData.liteBackTextureFile = "";
\r
2054 appData.liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
2055 appData.darkBackTextureFile = "";
\r
2056 appData.darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
2057 appData.renderPiecesWithFont = "";
\r
2058 appData.fontToPieceTable = "";
\r
2059 appData.fontBackColorWhite = 0;
\r
2060 appData.fontForeColorWhite = 0;
\r
2061 appData.fontBackColorBlack = 0;
\r
2062 appData.fontForeColorBlack = 0;
\r
2063 appData.fontPieceSize = 80;
\r
2064 appData.overrideLineGap = 1;
\r
2065 appData.adjudicateLossThreshold = 0;
\r
2066 appData.delayBeforeQuit = 0;
\r
2067 appData.delayAfterQuit = 0;
\r
2068 appData.nameOfDebugFile = "winboard.debug";
\r
2069 appData.pgnEventHeader = "Computer Chess Game";
\r
2070 appData.defaultFrcPosition = -1;
\r
2071 appData.gameListTags = GLT_DEFAULT_TAGS;
\r
2072 appData.saveOutOfBookInfo = TRUE;
\r
2073 appData.showEvalInMoveHistory = TRUE;
\r
2074 appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );
\r
2075 appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );
\r
2076 appData.highlightMoveWithArrow = FALSE;
\r
2077 appData.highlightArrowColor = ParseColorName( "#FFFF80" );
\r
2078 appData.useStickyWindows = TRUE;
\r
2079 appData.adjudicateDrawMoves = 0;
\r
2080 appData.autoDisplayComment = TRUE;
\r
2081 appData.autoDisplayTags = TRUE;
\r
2082 appData.firstIsUCI = FALSE;
\r
2083 appData.secondIsUCI = FALSE;
\r
2084 appData.firstHasOwnBookUCI = TRUE;
\r
2085 appData.secondHasOwnBookUCI = TRUE;
\r
2086 appData.polyglotDir = "";
\r
2087 appData.usePolyglotBook = FALSE;
\r
2088 appData.polyglotBook = "";
\r
2089 appData.defaultHashSize = 64;
\r
2090 appData.defaultCacheSizeEGTB = 4;
\r
2091 appData.defaultPathEGTB = "c:\\egtb";
\r
2092 appData.firstOptions = "";
\r
2093 appData.secondOptions = "";
\r
2095 InitWindowPlacement( &wpGameList );
\r
2096 InitWindowPlacement( &wpMoveHistory );
\r
2097 InitWindowPlacement( &wpEvalGraph );
\r
2098 InitWindowPlacement( &wpEngineOutput );
\r
2099 InitWindowPlacement( &wpConsole );
\r
2101 /* [HGM] User-selectable board size, adjudication control, miscellaneous */
\r
2102 appData.NrFiles = -1;
\r
2103 appData.NrRanks = -1;
\r
2104 appData.holdingsSize = -1;
\r
2105 appData.testClaims = FALSE;
\r
2106 appData.checkMates = FALSE;
\r
2107 appData.materialDraws= FALSE;
\r
2108 appData.trivialDraws = FALSE;
\r
2109 appData.ruleMoves = 51;
\r
2110 appData.drawRepeats = 6;
\r
2111 appData.matchPause = 10000;
\r
2112 appData.alphaRank = FALSE;
\r
2113 appData.allWhite = FALSE;
\r
2114 appData.upsideDown = FALSE;
\r
2115 appData.serverPause = 15;
\r
2116 appData.serverMovesName = NULL;
\r
2117 appData.suppressLoadMoves = FALSE;
\r
2118 appData.firstTimeOdds = 1;
\r
2119 appData.secondTimeOdds = 1;
\r
2120 appData.firstAccumulateTC = 1; // combine previous and current sessions
\r
2121 appData.secondAccumulateTC = 1;
\r
2122 appData.firstNPS = -1; // [HGM] nps: use wall-clock time
\r
2123 appData.secondNPS = -1;
\r
2124 appData.engineComments = 1;
\r
2125 appData.smpCores = 1; // [HGM] SMP: max nr of cores
\r
2126 appData.egtFormats = "";
\r
2129 appData.zippyTalk = ZIPPY_TALK;
\r
2130 appData.zippyPlay = ZIPPY_PLAY;
\r
2131 appData.zippyLines = ZIPPY_LINES;
\r
2132 appData.zippyPinhead = ZIPPY_PINHEAD;
\r
2133 appData.zippyPassword = ZIPPY_PASSWORD;
\r
2134 appData.zippyPassword2 = ZIPPY_PASSWORD2;
\r
2135 appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;
\r
2136 appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;
\r
2137 appData.zippyUseI = ZIPPY_USE_I;
\r
2138 appData.zippyBughouse = ZIPPY_BUGHOUSE;
\r
2139 appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;
\r
2140 appData.zippyGameEnd = ZIPPY_GAME_END;
\r
2141 appData.zippyGameStart = ZIPPY_GAME_START;
\r
2142 appData.zippyAdjourn = ZIPPY_ADJOURN;
\r
2143 appData.zippyAbort = ZIPPY_ABORT;
\r
2144 appData.zippyVariants = ZIPPY_VARIANTS;
\r
2145 appData.zippyMaxGames = ZIPPY_MAX_GAMES;
\r
2146 appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;
\r
2149 /* Point font array elements to structures and
\r
2150 parse default font names */
\r
2151 for (i=0; i<NUM_FONTS; i++) {
\r
2152 for (j=0; j<NUM_SIZES; j++) {
\r
2153 font[j][i] = &fontRec[j][i];
\r
2154 ParseFontName(font[j][i]->def, &font[j][i]->mfp);
\r
2158 /* Parse default settings file if any */
\r
2159 if (ParseSettingsFile(settingsFileName, buf)) {
\r
2160 settingsFileName = strdup(buf);
\r
2163 /* Parse command line */
\r
2164 ParseArgs(StringGet, &lpCmdLine);
\r
2166 /* [HGM] make sure board size is acceptable */
\r
2167 if(appData.NrFiles > BOARD_SIZE ||
\r
2168 appData.NrRanks > BOARD_SIZE )
\r
2169 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
2171 /* [HGM] After parsing the options from the .ini file, and overruling them
\r
2172 * with options from the command line, we now make an even higher priority
\r
2173 * overrule by WB options attached to the engine command line. This so that
\r
2174 * tournament managers can use WB options (such as /timeOdds) that follow
\r
2177 if(appData.firstChessProgram != NULL) {
\r
2178 char *p = StrStr(appData.firstChessProgram, "WBopt");
\r
2179 static char *f = "first";
\r
2180 char buf[MSG_SIZ], *q = buf;
\r
2181 if(p != NULL) { // engine command line contains WinBoard options
\r
2182 sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"
\r
2183 ParseArgs(StringGet, &q);
\r
2184 p[-1] = 0; // cut them offengine command line
\r
2187 // now do same for second chess program
\r
2188 if(appData.secondChessProgram != NULL) {
\r
2189 char *p = StrStr(appData.secondChessProgram, "WBopt");
\r
2190 static char *s = "second";
\r
2191 char buf[MSG_SIZ], *q = buf;
\r
2192 if(p != NULL) { // engine command line contains WinBoard options
\r
2193 sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"
\r
2194 ParseArgs(StringGet, &q);
\r
2195 p[-1] = 0; // cut them offengine command line
\r
2200 /* Propagate options that affect others */
\r
2201 if (appData.matchMode || appData.matchGames) chessProgram = TRUE;
\r
2202 if (appData.icsActive || appData.noChessProgram) {
\r
2203 chessProgram = FALSE; /* not local chess program mode */
\r
2206 /* Open startup dialog if needed */
\r
2207 if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||
\r
2208 (appData.icsActive && *appData.icsHost == NULLCHAR) ||
\r
2209 (chessProgram && (*appData.firstChessProgram == NULLCHAR ||
\r
2210 *appData.secondChessProgram == NULLCHAR))) {
\r
2213 lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);
\r
2214 DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);
\r
2215 FreeProcInstance(lpProc);
\r
2218 /* Make sure save files land in the right (?) directory */
\r
2219 if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {
\r
2220 appData.saveGameFile = strdup(buf);
\r
2222 if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {
\r
2223 appData.savePositionFile = strdup(buf);
\r
2226 /* Finish initialization for fonts and sounds */
\r
2227 for (i=0; i<NUM_FONTS; i++) {
\r
2228 for (j=0; j<NUM_SIZES; j++) {
\r
2229 CreateFontInMF(font[j][i]);
\r
2232 /* xboard, and older WinBoards, controlled the move sound with the
\r
2233 appData.ringBellAfterMoves option. In the current WinBoard, we
\r
2234 always turn the option on (so that the backend will call us),
\r
2235 then let the user turn the sound off by setting it to silence if
\r
2236 desired. To accommodate old winboard.ini files saved by old
\r
2237 versions of WinBoard, we also turn off the sound if the option
\r
2238 was initially set to false. */
\r
2239 if (!appData.ringBellAfterMoves) {
\r
2240 sounds[(int)SoundMove].name = strdup("");
\r
2241 appData.ringBellAfterMoves = TRUE;
\r
2243 GetCurrentDirectory(MSG_SIZ, currDir);
\r
2244 SetCurrentDirectory(installDir);
\r
2246 SetCurrentDirectory(currDir);
\r
2248 p = icsTextMenuString;
\r
2249 if (p[0] == '@') {
\r
2250 FILE* f = fopen(p + 1, "r");
\r
2252 DisplayFatalError(p + 1, errno, 2);
\r
2255 i = fread(buf, 1, sizeof(buf)-1, f);
\r
2257 buf[i] = NULLCHAR;
\r
2260 ParseIcsTextMenu(strdup(p));
\r
2267 HMENU hmenu = GetMenu(hwndMain);
\r
2269 (void) EnableMenuItem(hmenu, IDM_CommPort,
\r
2270 MF_BYCOMMAND|((appData.icsActive &&
\r
2271 *appData.icsCommPort != NULLCHAR) ?
\r
2272 MF_ENABLED : MF_GRAYED));
\r
2273 (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,
\r
2274 MF_BYCOMMAND|(saveSettingsOnExit ?
\r
2275 MF_CHECKED : MF_UNCHECKED));
\r
2280 SaveSettings(char* name)
\r
2283 ArgDescriptor *ad;
\r
2284 WINDOWPLACEMENT wp;
\r
2285 char dir[MSG_SIZ];
\r
2287 if (!hwndMain) return;
\r
2289 GetCurrentDirectory(MSG_SIZ, dir);
\r
2290 SetCurrentDirectory(installDir);
\r
2291 f = fopen(name, "w");
\r
2292 SetCurrentDirectory(dir);
\r
2294 DisplayError(name, errno);
\r
2297 fprintf(f, ";\n");
\r
2298 fprintf(f, "; %s %s.%s Save Settings file\n", PRODUCT, VERSION, PATCHLEVEL);
\r
2299 fprintf(f, ";\n");
\r
2300 fprintf(f, "; You can edit the values of options that are already set in this file,\n");
\r
2301 fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");
\r
2302 fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");
\r
2303 fprintf(f, ";\n");
\r
2305 wp.length = sizeof(WINDOWPLACEMENT);
\r
2306 GetWindowPlacement(hwndMain, &wp);
\r
2307 boardX = wp.rcNormalPosition.left;
\r
2308 boardY = wp.rcNormalPosition.top;
\r
2310 if (hwndConsole) {
\r
2311 GetWindowPlacement(hwndConsole, &wp);
\r
2312 wpConsole.x = wp.rcNormalPosition.left;
\r
2313 wpConsole.y = wp.rcNormalPosition.top;
\r
2314 wpConsole.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2315 wpConsole.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2318 if (analysisDialog) {
\r
2319 GetWindowPlacement(analysisDialog, &wp);
\r
2320 analysisX = wp.rcNormalPosition.left;
\r
2321 analysisY = wp.rcNormalPosition.top;
\r
2322 analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2323 analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2326 if (commentDialog) {
\r
2327 GetWindowPlacement(commentDialog, &wp);
\r
2328 commentX = wp.rcNormalPosition.left;
\r
2329 commentY = wp.rcNormalPosition.top;
\r
2330 commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2331 commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2334 if (editTagsDialog) {
\r
2335 GetWindowPlacement(editTagsDialog, &wp);
\r
2336 editTagsX = wp.rcNormalPosition.left;
\r
2337 editTagsY = wp.rcNormalPosition.top;
\r
2338 editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2339 editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2342 if (gameListDialog) {
\r
2343 GetWindowPlacement(gameListDialog, &wp);
\r
2344 wpGameList.x = wp.rcNormalPosition.left;
\r
2345 wpGameList.y = wp.rcNormalPosition.top;
\r
2346 wpGameList.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2347 wpGameList.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2350 /* [AS] Move history */
\r
2351 wpMoveHistory.visible = MoveHistoryIsUp();
\r
2353 if( moveHistoryDialog ) {
\r
2354 GetWindowPlacement(moveHistoryDialog, &wp);
\r
2355 wpMoveHistory.x = wp.rcNormalPosition.left;
\r
2356 wpMoveHistory.y = wp.rcNormalPosition.top;
\r
2357 wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2358 wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2361 /* [AS] Eval graph */
\r
2362 wpEvalGraph.visible = EvalGraphIsUp();
\r
2364 if( evalGraphDialog ) {
\r
2365 GetWindowPlacement(evalGraphDialog, &wp);
\r
2366 wpEvalGraph.x = wp.rcNormalPosition.left;
\r
2367 wpEvalGraph.y = wp.rcNormalPosition.top;
\r
2368 wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2369 wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2372 /* [AS] Engine output */
\r
2373 wpEngineOutput.visible = EngineOutputIsUp();
\r
2375 if( engineOutputDialog ) {
\r
2376 GetWindowPlacement(engineOutputDialog, &wp);
\r
2377 wpEngineOutput.x = wp.rcNormalPosition.left;
\r
2378 wpEngineOutput.y = wp.rcNormalPosition.top;
\r
2379 wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2380 wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2383 for (ad = argDescriptors; ad->argName != NULL; ad++) {
\r
2384 if (!ad->save) continue;
\r
2385 switch (ad->argType) {
\r
2388 char *p = *(char **)ad->argLoc;
\r
2389 if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {
\r
2390 /* Quote multiline values or \-containing values
\r
2391 with { } if possible */
\r
2392 fprintf(f, "/%s={%s}\n", ad->argName, p);
\r
2394 /* Else quote with " " */
\r
2395 fprintf(f, "/%s=\"", ad->argName);
\r
2397 if (*p == '\n') fprintf(f, "\n");
\r
2398 else if (*p == '\r') fprintf(f, "\\r");
\r
2399 else if (*p == '\t') fprintf(f, "\\t");
\r
2400 else if (*p == '\b') fprintf(f, "\\b");
\r
2401 else if (*p == '\f') fprintf(f, "\\f");
\r
2402 else if (*p < ' ') fprintf(f, "\\%03o", *p);
\r
2403 else if (*p == '\"') fprintf(f, "\\\"");
\r
2404 else if (*p == '\\') fprintf(f, "\\\\");
\r
2408 fprintf(f, "\"\n");
\r
2414 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);
\r
2417 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardX); // [HGM] placement: stor relative value
\r
2420 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardY);
\r
2423 fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);
\r
2426 fprintf(f, "/%s=%s\n", ad->argName,
\r
2427 (*(Boolean *)ad->argLoc) ? "true" : "false");
\r
2430 if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2433 if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2437 COLORREF color = *(COLORREF *)ad->argLoc;
\r
2438 fprintf(f, "/%s=#%02lx%02lx%02lx\n", ad->argName,
\r
2439 color&0xff, (color>>8)&0xff, (color>>16)&0xff);
\r
2444 MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];
\r
2445 fprintf(f, "/%s=\"%s%s%s%s%s#%02lx%02lx%02lx\"\n", ad->argName,
\r
2446 (ta->effects & CFE_BOLD) ? "b" : "",
\r
2447 (ta->effects & CFE_ITALIC) ? "i" : "",
\r
2448 (ta->effects & CFE_UNDERLINE) ? "u" : "",
\r
2449 (ta->effects & CFE_STRIKEOUT) ? "s" : "",
\r
2450 (ta->effects) ? " " : "",
\r
2451 ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);
\r
2455 if (strchr(*(char **)ad->argLoc, '\"')) {
\r
2456 fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);
\r
2458 fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);
\r
2461 case ArgBoardSize:
\r
2462 fprintf(f, "/%s=%s\n", ad->argName,
\r
2463 sizeInfo[*(BoardSize *)ad->argLoc].name);
\r
2468 for (bs=0; bs<NUM_SIZES; bs++) {
\r
2469 MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;
\r
2470 fprintf(f, "/size=%s ", sizeInfo[bs].name);
\r
2471 fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n",
\r
2472 ad->argName, mfp->faceName, mfp->pointSize,
\r
2473 mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",
\r
2474 mfp->bold ? "b" : "",
\r
2475 mfp->italic ? "i" : "",
\r
2476 mfp->underline ? "u" : "",
\r
2477 mfp->strikeout ? "s" : "");
\r
2481 case ArgCommSettings:
\r
2482 PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);
\r
2484 case ArgSettingsFilename: ;
\r
2492 /*---------------------------------------------------------------------------*\
\r
2494 * GDI board drawing routines
\r
2496 \*---------------------------------------------------------------------------*/
\r
2498 /* [AS] Draw square using background texture */
\r
2499 static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )
\r
2504 return; /* Should never happen! */
\r
2507 SetGraphicsMode( dst, GM_ADVANCED );
\r
2514 /* X reflection */
\r
2519 x.eDx = (FLOAT) dw + dx - 1;
\r
2522 SetWorldTransform( dst, &x );
\r
2525 /* Y reflection */
\r
2531 x.eDy = (FLOAT) dh + dy - 1;
\r
2533 SetWorldTransform( dst, &x );
\r
2541 x.eDx = (FLOAT) dx;
\r
2542 x.eDy = (FLOAT) dy;
\r
2545 SetWorldTransform( dst, &x );
\r
2549 BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );
\r
2557 SetWorldTransform( dst, &x );
\r
2559 ModifyWorldTransform( dst, 0, MWT_IDENTITY );
\r
2562 /* [AS] [HGM] Make room for more piece types, so all pieces can be different */
\r
2564 PM_WP = (int) WhitePawn,
\r
2565 PM_WN = (int) WhiteKnight,
\r
2566 PM_WB = (int) WhiteBishop,
\r
2567 PM_WR = (int) WhiteRook,
\r
2568 PM_WQ = (int) WhiteQueen,
\r
2569 PM_WF = (int) WhiteFerz,
\r
2570 PM_WW = (int) WhiteWazir,
\r
2571 PM_WE = (int) WhiteAlfil,
\r
2572 PM_WM = (int) WhiteMan,
\r
2573 PM_WO = (int) WhiteCannon,
\r
2574 PM_WU = (int) WhiteUnicorn,
\r
2575 PM_WH = (int) WhiteNightrider,
\r
2576 PM_WA = (int) WhiteAngel,
\r
2577 PM_WC = (int) WhiteMarshall,
\r
2578 PM_WAB = (int) WhiteCardinal,
\r
2579 PM_WD = (int) WhiteDragon,
\r
2580 PM_WL = (int) WhiteLance,
\r
2581 PM_WS = (int) WhiteCobra,
\r
2582 PM_WV = (int) WhiteFalcon,
\r
2583 PM_WSG = (int) WhiteSilver,
\r
2584 PM_WG = (int) WhiteGrasshopper,
\r
2585 PM_WK = (int) WhiteKing,
\r
2586 PM_BP = (int) BlackPawn,
\r
2587 PM_BN = (int) BlackKnight,
\r
2588 PM_BB = (int) BlackBishop,
\r
2589 PM_BR = (int) BlackRook,
\r
2590 PM_BQ = (int) BlackQueen,
\r
2591 PM_BF = (int) BlackFerz,
\r
2592 PM_BW = (int) BlackWazir,
\r
2593 PM_BE = (int) BlackAlfil,
\r
2594 PM_BM = (int) BlackMan,
\r
2595 PM_BO = (int) BlackCannon,
\r
2596 PM_BU = (int) BlackUnicorn,
\r
2597 PM_BH = (int) BlackNightrider,
\r
2598 PM_BA = (int) BlackAngel,
\r
2599 PM_BC = (int) BlackMarshall,
\r
2600 PM_BG = (int) BlackGrasshopper,
\r
2601 PM_BAB = (int) BlackCardinal,
\r
2602 PM_BD = (int) BlackDragon,
\r
2603 PM_BL = (int) BlackLance,
\r
2604 PM_BS = (int) BlackCobra,
\r
2605 PM_BV = (int) BlackFalcon,
\r
2606 PM_BSG = (int) BlackSilver,
\r
2607 PM_BK = (int) BlackKing
\r
2610 static HFONT hPieceFont = NULL;
\r
2611 static HBITMAP hPieceMask[(int) EmptySquare];
\r
2612 static HBITMAP hPieceFace[(int) EmptySquare];
\r
2613 static int fontBitmapSquareSize = 0;
\r
2614 static char pieceToFontChar[(int) EmptySquare] =
\r
2615 { 'p', 'n', 'b', 'r', 'q',
\r
2616 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',
\r
2617 'k', 'o', 'm', 'v', 't', 'w',
\r
2618 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',
\r
2621 extern BOOL SetCharTable( char *table, const char * map );
\r
2622 /* [HGM] moved to backend.c */
\r
2624 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )
\r
2627 BYTE r1 = GetRValue( color );
\r
2628 BYTE g1 = GetGValue( color );
\r
2629 BYTE b1 = GetBValue( color );
\r
2635 /* Create a uniform background first */
\r
2636 hbrush = CreateSolidBrush( color );
\r
2637 SetRect( &rc, 0, 0, squareSize, squareSize );
\r
2638 FillRect( hdc, &rc, hbrush );
\r
2639 DeleteObject( hbrush );
\r
2642 /* Vertical gradient, good for pawn, knight and rook, less for queen and king */
\r
2643 int steps = squareSize / 2;
\r
2646 for( i=0; i<steps; i++ ) {
\r
2647 BYTE r = r1 - (r1-r2) * i / steps;
\r
2648 BYTE g = g1 - (g1-g2) * i / steps;
\r
2649 BYTE b = b1 - (b1-b2) * i / steps;
\r
2651 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2652 SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );
\r
2653 FillRect( hdc, &rc, hbrush );
\r
2654 DeleteObject(hbrush);
\r
2657 else if( mode == 2 ) {
\r
2658 /* Diagonal gradient, good more or less for every piece */
\r
2659 POINT triangle[3];
\r
2660 HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );
\r
2661 HBRUSH hbrush_old;
\r
2662 int steps = squareSize;
\r
2665 triangle[0].x = squareSize - steps;
\r
2666 triangle[0].y = squareSize;
\r
2667 triangle[1].x = squareSize;
\r
2668 triangle[1].y = squareSize;
\r
2669 triangle[2].x = squareSize;
\r
2670 triangle[2].y = squareSize - steps;
\r
2672 for( i=0; i<steps; i++ ) {
\r
2673 BYTE r = r1 - (r1-r2) * i / steps;
\r
2674 BYTE g = g1 - (g1-g2) * i / steps;
\r
2675 BYTE b = b1 - (b1-b2) * i / steps;
\r
2677 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2678 hbrush_old = SelectObject( hdc, hbrush );
\r
2679 Polygon( hdc, triangle, 3 );
\r
2680 SelectObject( hdc, hbrush_old );
\r
2681 DeleteObject(hbrush);
\r
2686 SelectObject( hdc, hpen );
\r
2691 [AS] The method I use to create the bitmaps it a bit tricky, but it
\r
2692 seems to work ok. The main problem here is to find the "inside" of a chess
\r
2693 piece: follow the steps as explained below.
\r
2695 static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
\r
2699 COLORREF chroma = RGB(0xFF,0x00,0xFF);
\r
2703 int backColor = whitePieceColor;
\r
2704 int foreColor = blackPieceColor;
\r
2706 if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {
\r
2707 backColor = appData.fontBackColorWhite;
\r
2708 foreColor = appData.fontForeColorWhite;
\r
2710 else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {
\r
2711 backColor = appData.fontBackColorBlack;
\r
2712 foreColor = appData.fontForeColorBlack;
\r
2716 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2718 hbm_old = SelectObject( hdc, hbm );
\r
2722 rc.right = squareSize;
\r
2723 rc.bottom = squareSize;
\r
2725 /* Step 1: background is now black */
\r
2726 FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );
\r
2728 GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );
\r
2730 pt.x = (squareSize - sz.cx) / 2;
\r
2731 pt.y = (squareSize - sz.cy) / 2;
\r
2733 SetBkMode( hdc, TRANSPARENT );
\r
2734 SetTextColor( hdc, chroma );
\r
2735 /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */
\r
2736 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2738 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
\r
2739 /* Step 3: the area outside the piece is filled with white */
\r
2740 // FloodFill( hdc, 0, 0, chroma );
\r
2741 ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );
\r
2742 ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big
\r
2743 ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );
\r
2744 ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );
\r
2745 SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
\r
2747 Step 4: this is the tricky part, the area inside the piece is filled with black,
\r
2748 but if the start point is not inside the piece we're lost!
\r
2749 There should be a better way to do this... if we could create a region or path
\r
2750 from the fill operation we would be fine for example.
\r
2752 // FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );
\r
2753 ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );
\r
2755 { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */
\r
2756 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2757 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2759 SelectObject( dc2, bm2 );
\r
2760 BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy
\r
2761 BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2762 BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2763 BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2764 BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2767 DeleteObject( bm2 );
\r
2770 SetTextColor( hdc, 0 );
\r
2772 Step 5: some fonts have "disconnected" areas that are skipped by the fill:
\r
2773 draw the piece again in black for safety.
\r
2775 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2777 SelectObject( hdc, hbm_old );
\r
2779 if( hPieceMask[index] != NULL ) {
\r
2780 DeleteObject( hPieceMask[index] );
\r
2783 hPieceMask[index] = hbm;
\r
2786 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2788 SelectObject( hdc, hbm );
\r
2791 HDC dc1 = CreateCompatibleDC( hdc_window );
\r
2792 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2793 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2795 SelectObject( dc1, hPieceMask[index] );
\r
2796 SelectObject( dc2, bm2 );
\r
2797 FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );
\r
2798 BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );
\r
2801 Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves
\r
2802 the piece background and deletes (makes transparent) the rest.
\r
2803 Thanks to that mask, we are free to paint the background with the greates
\r
2804 freedom, as we'll be able to mask off the unwanted parts when finished.
\r
2805 We use this, to make gradients and give the pieces a "roundish" look.
\r
2807 SetPieceBackground( hdc, backColor, 2 );
\r
2808 BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );
\r
2812 DeleteObject( bm2 );
\r
2815 SetTextColor( hdc, foreColor );
\r
2816 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2818 SelectObject( hdc, hbm_old );
\r
2820 if( hPieceFace[index] != NULL ) {
\r
2821 DeleteObject( hPieceFace[index] );
\r
2824 hPieceFace[index] = hbm;
\r
2827 static int TranslatePieceToFontPiece( int piece )
\r
2857 case BlackMarshall:
\r
2861 case BlackNightrider:
\r
2867 case BlackUnicorn:
\r
2871 case BlackGrasshopper:
\r
2883 case BlackCardinal:
\r
2890 case WhiteMarshall:
\r
2894 case WhiteNightrider:
\r
2900 case WhiteUnicorn:
\r
2904 case WhiteGrasshopper:
\r
2916 case WhiteCardinal:
\r
2925 void CreatePiecesFromFont()
\r
2928 HDC hdc_window = NULL;
\r
2934 if( fontBitmapSquareSize < 0 ) {
\r
2935 /* Something went seriously wrong in the past: do not try to recreate fonts! */
\r
2939 if( appData.renderPiecesWithFont == NULL || appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {
\r
2940 fontBitmapSquareSize = -1;
\r
2944 if( fontBitmapSquareSize != squareSize ) {
\r
2945 hdc_window = GetDC( hwndMain );
\r
2946 hdc = CreateCompatibleDC( hdc_window );
\r
2948 if( hPieceFont != NULL ) {
\r
2949 DeleteObject( hPieceFont );
\r
2952 for( i=0; i<=(int)BlackKing; i++ ) {
\r
2953 hPieceMask[i] = NULL;
\r
2954 hPieceFace[i] = NULL;
\r
2960 if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {
\r
2961 fontHeight = appData.fontPieceSize;
\r
2964 fontHeight = (fontHeight * squareSize) / 100;
\r
2966 lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
\r
2968 lf.lfEscapement = 0;
\r
2969 lf.lfOrientation = 0;
\r
2970 lf.lfWeight = FW_NORMAL;
\r
2972 lf.lfUnderline = 0;
\r
2973 lf.lfStrikeOut = 0;
\r
2974 lf.lfCharSet = DEFAULT_CHARSET;
\r
2975 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
2976 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
2977 lf.lfQuality = PROOF_QUALITY;
\r
2978 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
\r
2979 strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );
\r
2980 lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';
\r
2982 hPieceFont = CreateFontIndirect( &lf );
\r
2984 if( hPieceFont == NULL ) {
\r
2985 fontBitmapSquareSize = -2;
\r
2988 /* Setup font-to-piece character table */
\r
2989 if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {
\r
2990 /* No (or wrong) global settings, try to detect the font */
\r
2991 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {
\r
2993 SetCharTable(pieceToFontChar, "phbrqkojntwl");
\r
2995 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {
\r
2996 /* DiagramTT* family */
\r
2997 SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");
\r
2999 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {
\r
3000 /* Fairy symbols */
\r
3001 SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
\r
3003 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {
\r
3004 /* Good Companion (Some characters get warped as literal :-( */
\r
3005 char s[] = "1cmWG0ñueOS¯®oYI23wgQU";
\r
3006 s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;
\r
3007 SetCharTable(pieceToFontChar, s);
\r
3010 /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */
\r
3011 SetCharTable(pieceToFontChar, "pnbrqkomvtwl");
\r
3015 /* Create bitmaps */
\r
3016 hfont_old = SelectObject( hdc, hPieceFont );
\r
3018 CreatePieceMaskFromFont( hdc_window, hdc, PM_WP );
\r
3019 CreatePieceMaskFromFont( hdc_window, hdc, PM_WN );
\r
3020 CreatePieceMaskFromFont( hdc_window, hdc, PM_WB );
\r
3021 CreatePieceMaskFromFont( hdc_window, hdc, PM_WR );
\r
3022 CreatePieceMaskFromFont( hdc_window, hdc, PM_WQ );
\r
3023 CreatePieceMaskFromFont( hdc_window, hdc, PM_WK );
\r
3024 CreatePieceMaskFromFont( hdc_window, hdc, PM_BP );
\r
3025 CreatePieceMaskFromFont( hdc_window, hdc, PM_BN );
\r
3026 CreatePieceMaskFromFont( hdc_window, hdc, PM_BB );
\r
3027 CreatePieceMaskFromFont( hdc_window, hdc, PM_BR );
\r
3028 CreatePieceMaskFromFont( hdc_window, hdc, PM_BQ );
\r
3029 CreatePieceMaskFromFont( hdc_window, hdc, PM_BK );
\r
3031 CreatePieceMaskFromFont( hdc_window, hdc, PM_WA );
\r
3032 CreatePieceMaskFromFont( hdc_window, hdc, PM_WC );
\r
3033 CreatePieceMaskFromFont( hdc_window, hdc, PM_WF );
\r
3034 CreatePieceMaskFromFont( hdc_window, hdc, PM_WH );
\r
3035 CreatePieceMaskFromFont( hdc_window, hdc, PM_WE );
\r
3036 CreatePieceMaskFromFont( hdc_window, hdc, PM_WW );
\r
3037 CreatePieceMaskFromFont( hdc_window, hdc, PM_WU );
\r
3038 CreatePieceMaskFromFont( hdc_window, hdc, PM_WO );
\r
3039 CreatePieceMaskFromFont( hdc_window, hdc, PM_WG );
\r
3040 CreatePieceMaskFromFont( hdc_window, hdc, PM_WM );
\r
3041 CreatePieceMaskFromFont( hdc_window, hdc, PM_WSG );
\r
3042 CreatePieceMaskFromFont( hdc_window, hdc, PM_WV );
\r
3043 CreatePieceMaskFromFont( hdc_window, hdc, PM_WAB );
\r
3044 CreatePieceMaskFromFont( hdc_window, hdc, PM_WD );
\r
3045 CreatePieceMaskFromFont( hdc_window, hdc, PM_WL );
\r
3046 CreatePieceMaskFromFont( hdc_window, hdc, PM_WS );
\r
3047 CreatePieceMaskFromFont( hdc_window, hdc, PM_BA );
\r
3048 CreatePieceMaskFromFont( hdc_window, hdc, PM_BC );
\r
3049 CreatePieceMaskFromFont( hdc_window, hdc, PM_BF );
\r
3050 CreatePieceMaskFromFont( hdc_window, hdc, PM_BH );
\r
3051 CreatePieceMaskFromFont( hdc_window, hdc, PM_BE );
\r
3052 CreatePieceMaskFromFont( hdc_window, hdc, PM_BW );
\r
3053 CreatePieceMaskFromFont( hdc_window, hdc, PM_BU );
\r
3054 CreatePieceMaskFromFont( hdc_window, hdc, PM_BO );
\r
3055 CreatePieceMaskFromFont( hdc_window, hdc, PM_BG );
\r
3056 CreatePieceMaskFromFont( hdc_window, hdc, PM_BM );
\r
3057 CreatePieceMaskFromFont( hdc_window, hdc, PM_BSG );
\r
3058 CreatePieceMaskFromFont( hdc_window, hdc, PM_BV );
\r
3059 CreatePieceMaskFromFont( hdc_window, hdc, PM_BAB );
\r
3060 CreatePieceMaskFromFont( hdc_window, hdc, PM_BD );
\r
3061 CreatePieceMaskFromFont( hdc_window, hdc, PM_BL );
\r
3062 CreatePieceMaskFromFont( hdc_window, hdc, PM_BS );
\r
3064 for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */
\r
3065 if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */
\r
3066 CreatePieceMaskFromFont( hdc_window, hdc, i );
\r
3068 SelectObject( hdc, hfont_old );
\r
3070 fontBitmapSquareSize = squareSize;
\r
3074 if( hdc != NULL ) {
\r
3078 if( hdc_window != NULL ) {
\r
3079 ReleaseDC( hwndMain, hdc_window );
\r
3084 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)
\r
3088 sprintf(name, "%s%d%s", piece, squareSize, suffix);
\r
3089 if (gameInfo.event &&
\r
3090 strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&
\r
3091 strcmp(name, "k80s") == 0) {
\r
3092 strcpy(name, "tim");
\r
3094 return LoadBitmap(hinst, name);
\r
3098 /* Insert a color into the program's logical palette
\r
3099 structure. This code assumes the given color is
\r
3100 the result of the RGB or PALETTERGB macro, and it
\r
3101 knows how those macros work (which is documented).
\r
3104 InsertInPalette(COLORREF color)
\r
3106 LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);
\r
3108 if (pLogPal->palNumEntries++ >= PALETTESIZE) {
\r
3109 DisplayFatalError("Too many colors", 0, 1);
\r
3110 pLogPal->palNumEntries--;
\r
3114 pe->peFlags = (char) 0;
\r
3115 pe->peRed = (char) (0xFF & color);
\r
3116 pe->peGreen = (char) (0xFF & (color >> 8));
\r
3117 pe->peBlue = (char) (0xFF & (color >> 16));
\r
3123 InitDrawingColors()
\r
3125 if (pLogPal == NULL) {
\r
3126 /* Allocate enough memory for a logical palette with
\r
3127 * PALETTESIZE entries and set the size and version fields
\r
3128 * of the logical palette structure.
\r
3130 pLogPal = (NPLOGPALETTE)
\r
3131 LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +
\r
3132 (sizeof(PALETTEENTRY) * (PALETTESIZE))));
\r
3133 pLogPal->palVersion = 0x300;
\r
3135 pLogPal->palNumEntries = 0;
\r
3137 InsertInPalette(lightSquareColor);
\r
3138 InsertInPalette(darkSquareColor);
\r
3139 InsertInPalette(whitePieceColor);
\r
3140 InsertInPalette(blackPieceColor);
\r
3141 InsertInPalette(highlightSquareColor);
\r
3142 InsertInPalette(premoveHighlightColor);
\r
3144 /* create a logical color palette according the information
\r
3145 * in the LOGPALETTE structure.
\r
3147 hPal = CreatePalette((LPLOGPALETTE) pLogPal);
\r
3149 lightSquareBrush = CreateSolidBrush(lightSquareColor);
\r
3150 blackSquareBrush = CreateSolidBrush(blackPieceColor);
\r
3151 darkSquareBrush = CreateSolidBrush(darkSquareColor);
\r
3152 whitePieceBrush = CreateSolidBrush(whitePieceColor);
\r
3153 blackPieceBrush = CreateSolidBrush(blackPieceColor);
\r
3154 iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
\r
3155 explodeBrush = CreateSolidBrush(highlightSquareColor); // [HGM] atomic
\r
3156 /* [AS] Force rendering of the font-based pieces */
\r
3157 if( fontBitmapSquareSize > 0 ) {
\r
3158 fontBitmapSquareSize = 0;
\r
3164 BoardWidth(int boardSize, int n)
\r
3165 { /* [HGM] argument n added to allow different width and height */
\r
3166 int lineGap = sizeInfo[boardSize].lineGap;
\r
3168 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3169 lineGap = appData.overrideLineGap;
\r
3172 return (n + 1) * lineGap +
\r
3173 n * sizeInfo[boardSize].squareSize;
\r
3176 /* Respond to board resize by dragging edge */
\r
3178 ResizeBoard(int newSizeX, int newSizeY, int flags)
\r
3180 BoardSize newSize = NUM_SIZES - 1;
\r
3181 static int recurse = 0;
\r
3182 if (IsIconic(hwndMain)) return;
\r
3183 if (recurse > 0) return;
\r
3185 while (newSize > 0) {
\r
3186 InitDrawingSizes(newSize+1000, 0); // [HGM] kludge to update sizeInfo without visible effects
\r
3187 if(newSizeX >= sizeInfo[newSize].cliWidth &&
\r
3188 newSizeY >= sizeInfo[newSize].cliHeight) break;
\r
3191 boardSize = newSize;
\r
3192 InitDrawingSizes(boardSize, flags);
\r
3199 InitDrawingSizes(BoardSize boardSize, int flags)
\r
3201 int i, boardWidth, boardHeight; /* [HGM] height treated separately */
\r
3202 ChessSquare piece;
\r
3203 static int oldBoardSize = -1, oldTinyLayout = 0;
\r
3205 SIZE clockSize, messageSize;
\r
3207 char buf[MSG_SIZ];
\r
3209 HMENU hmenu = GetMenu(hwndMain);
\r
3210 RECT crect, wrect, oldRect;
\r
3212 LOGBRUSH logbrush;
\r
3214 int suppressVisibleEffects = 0; // [HGM] kludge to request updating sizeInfo only
\r
3215 if((int)boardSize >= 1000 ) { boardSize -= 1000; suppressVisibleEffects = 1; }
\r
3217 /* [HGM] call with -2 uses old size (for if nr of files, ranks changes) */
\r
3218 if(boardSize == (BoardSize)(-2) ) boardSize = oldBoardSize;
\r
3220 oldRect.left = boardX; //[HGM] placement: remember previous window params
\r
3221 oldRect.top = boardY;
\r
3222 oldRect.right = boardX + winWidth;
\r
3223 oldRect.bottom = boardY + winHeight;
\r
3225 tinyLayout = sizeInfo[boardSize].tinyLayout;
\r
3226 smallLayout = sizeInfo[boardSize].smallLayout;
\r
3227 squareSize = sizeInfo[boardSize].squareSize;
\r
3228 lineGap = sizeInfo[boardSize].lineGap;
\r
3229 minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted */
\r
3231 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3232 lineGap = appData.overrideLineGap;
\r
3235 if (tinyLayout != oldTinyLayout) {
\r
3236 long style = GetWindowLong(hwndMain, GWL_STYLE);
\r
3238 style &= ~WS_SYSMENU;
\r
3239 InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize,
\r
3240 "&Minimize\tCtrl+F4");
\r
3242 style |= WS_SYSMENU;
\r
3243 RemoveMenu(hmenu, IDM_Minimize, MF_BYCOMMAND);
\r
3245 SetWindowLong(hwndMain, GWL_STYLE, style);
\r
3247 for (i=0; menuBarText[tinyLayout][i]; i++) {
\r
3248 ModifyMenu(hmenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP,
\r
3249 (UINT)GetSubMenu(hmenu, i), menuBarText[tinyLayout][i]);
\r
3251 DrawMenuBar(hwndMain);
\r
3254 boardWidth = BoardWidth(boardSize, BOARD_WIDTH);
\r
3255 boardHeight = BoardWidth(boardSize, BOARD_HEIGHT);
\r
3257 /* Get text area sizes */
\r
3258 hdc = GetDC(hwndMain);
\r
3259 if (appData.clockMode) {
\r
3260 sprintf(buf, "White: %s", TimeString(23*60*60*1000L));
\r
3262 sprintf(buf, "White");
\r
3264 oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);
\r
3265 GetTextExtentPoint(hdc, buf, strlen(buf), &clockSize);
\r
3266 SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);
\r
3267 str = "We only care about the height here";
\r
3268 GetTextExtentPoint(hdc, str, strlen(str), &messageSize);
\r
3269 SelectObject(hdc, oldFont);
\r
3270 ReleaseDC(hwndMain, hdc);
\r
3272 /* Compute where everything goes */
\r
3273 if((first.programLogo || second.programLogo) && !tinyLayout) {
\r
3274 /* [HGM] logo: if either logo is on, reserve space for it */
\r
3275 logoHeight = 2*clockSize.cy;
\r
3276 leftLogoRect.left = OUTER_MARGIN;
\r
3277 leftLogoRect.right = leftLogoRect.left + 4*clockSize.cy;
\r
3278 leftLogoRect.top = OUTER_MARGIN;
\r
3279 leftLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3281 rightLogoRect.right = OUTER_MARGIN + boardWidth;
\r
3282 rightLogoRect.left = rightLogoRect.right - 4*clockSize.cy;
\r
3283 rightLogoRect.top = OUTER_MARGIN;
\r
3284 rightLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3287 whiteRect.left = leftLogoRect.right;
\r
3288 whiteRect.right = OUTER_MARGIN + boardWidth/2 - INNER_MARGIN/2;
\r
3289 whiteRect.top = OUTER_MARGIN;
\r
3290 whiteRect.bottom = whiteRect.top + logoHeight;
\r
3292 blackRect.right = rightLogoRect.left;
\r
3293 blackRect.left = whiteRect.right + INNER_MARGIN;
\r
3294 blackRect.top = whiteRect.top;
\r
3295 blackRect.bottom = whiteRect.bottom;
\r
3297 whiteRect.left = OUTER_MARGIN;
\r
3298 whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2;
\r
3299 whiteRect.top = OUTER_MARGIN;
\r
3300 whiteRect.bottom = whiteRect.top + clockSize.cy;
\r
3302 blackRect.left = whiteRect.right + INNER_MARGIN;
\r
3303 blackRect.right = blackRect.left + boardWidth/2 - 1;
\r
3304 blackRect.top = whiteRect.top;
\r
3305 blackRect.bottom = whiteRect.bottom;
\r
3308 messageRect.left = OUTER_MARGIN + MESSAGE_LINE_LEFTMARGIN;
\r
3309 if (appData.showButtonBar) {
\r
3310 messageRect.right = OUTER_MARGIN + boardWidth // [HGM] logo: expressed independent of clock placement
\r
3311 - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN;
\r
3313 messageRect.right = OUTER_MARGIN + boardWidth;
\r
3315 messageRect.top = whiteRect.bottom + INNER_MARGIN;
\r
3316 messageRect.bottom = messageRect.top + messageSize.cy;
\r
3318 boardRect.left = OUTER_MARGIN;
\r
3319 boardRect.right = boardRect.left + boardWidth;
\r
3320 boardRect.top = messageRect.bottom + INNER_MARGIN;
\r
3321 boardRect.bottom = boardRect.top + boardHeight;
\r
3323 sizeInfo[boardSize].cliWidth = boardRect.right + OUTER_MARGIN;
\r
3324 sizeInfo[boardSize].cliHeight = boardRect.bottom + OUTER_MARGIN;
\r
3325 oldBoardSize = boardSize;
\r
3326 oldTinyLayout = tinyLayout;
\r
3327 winW = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN;
\r
3328 winH = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) +
\r
3329 GetSystemMetrics(SM_CYCAPTION) + boardRect.bottom + OUTER_MARGIN;
\r
3330 if(suppressVisibleEffects) return; // [HGM] when called for filling sizeInfo only
\r
3331 winWidth = winW; // [HGM] placement: set through temporary which can used by initial sizing choice
\r
3332 winHeight = winH; // without disturbing window attachments
\r
3333 GetWindowRect(hwndMain, &wrect);
\r
3334 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3335 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3337 // [HGM] placement: let attached windows follow size change.
\r
3338 ReattachAfterSize( &oldRect, winWidth, winHeight, moveHistoryDialog, &wpMoveHistory );
\r
3339 ReattachAfterSize( &oldRect, winWidth, winHeight, evalGraphDialog, &wpEvalGraph );
\r
3340 ReattachAfterSize( &oldRect, winWidth, winHeight, engineOutputDialog, &wpEngineOutput );
\r
3341 ReattachAfterSize( &oldRect, winWidth, winHeight, gameListDialog, &wpGameList );
\r
3342 ReattachAfterSize( &oldRect, winWidth, winHeight, hwndConsole, &wpConsole );
\r
3344 /* compensate if menu bar wrapped */
\r
3345 GetClientRect(hwndMain, &crect);
\r
3346 offby = boardRect.bottom + OUTER_MARGIN - crect.bottom;
\r
3347 winHeight += offby;
\r
3349 case WMSZ_TOPLEFT:
\r
3350 SetWindowPos(hwndMain, NULL,
\r
3351 wrect.right - winWidth, wrect.bottom - winHeight,
\r
3352 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3355 case WMSZ_TOPRIGHT:
\r
3357 SetWindowPos(hwndMain, NULL,
\r
3358 wrect.left, wrect.bottom - winHeight,
\r
3359 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3362 case WMSZ_BOTTOMLEFT:
\r
3364 SetWindowPos(hwndMain, NULL,
\r
3365 wrect.right - winWidth, wrect.top,
\r
3366 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3369 case WMSZ_BOTTOMRIGHT:
\r
3373 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3374 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3379 for (i = 0; i < N_BUTTONS; i++) {
\r
3380 if (buttonDesc[i].hwnd != NULL) {
\r
3381 DestroyWindow(buttonDesc[i].hwnd);
\r
3382 buttonDesc[i].hwnd = NULL;
\r
3384 if (appData.showButtonBar) {
\r
3385 buttonDesc[i].hwnd =
\r
3386 CreateWindow("BUTTON", buttonDesc[i].label,
\r
3387 WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
\r
3388 boardRect.right - BUTTON_WIDTH*(N_BUTTONS-i),
\r
3389 messageRect.top, BUTTON_WIDTH, messageSize.cy, hwndMain,
\r
3390 (HMENU) buttonDesc[i].id,
\r
3391 (HINSTANCE) GetWindowLong(hwndMain, GWL_HINSTANCE), NULL);
\r
3393 SendMessage(buttonDesc[i].hwnd, WM_SETFONT,
\r
3394 (WPARAM)font[boardSize][MESSAGE_FONT]->hf,
\r
3395 MAKELPARAM(FALSE, 0));
\r
3397 if (buttonDesc[i].id == IDM_Pause)
\r
3398 hwndPause = buttonDesc[i].hwnd;
\r
3399 buttonDesc[i].wndproc = (WNDPROC)
\r
3400 SetWindowLong(buttonDesc[i].hwnd, GWL_WNDPROC, (LONG) ButtonProc);
\r
3403 if (gridPen != NULL) DeleteObject(gridPen);
\r
3404 if (highlightPen != NULL) DeleteObject(highlightPen);
\r
3405 if (premovePen != NULL) DeleteObject(premovePen);
\r
3406 if (lineGap != 0) {
\r
3407 logbrush.lbStyle = BS_SOLID;
\r
3408 logbrush.lbColor = RGB(0, 0, 0); /* grid pen color = black */
\r
3410 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3411 lineGap, &logbrush, 0, NULL);
\r
3412 logbrush.lbColor = highlightSquareColor;
\r
3414 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3415 lineGap, &logbrush, 0, NULL);
\r
3417 logbrush.lbColor = premoveHighlightColor;
\r
3419 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3420 lineGap, &logbrush, 0, NULL);
\r
3422 /* [HGM] Loop had to be split in part for vert. and hor. lines */
\r
3423 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
\r
3424 gridEndpoints[i*2].x = boardRect.left + lineGap / 2;
\r
3425 gridEndpoints[i*2].y = gridEndpoints[i*2 + 1].y =
\r
3426 boardRect.top + lineGap / 2 + (i * (squareSize + lineGap));
\r
3427 gridEndpoints[i*2 + 1].x = boardRect.left + lineGap / 2 +
\r
3428 BOARD_WIDTH * (squareSize + lineGap);
\r
3429 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3431 for (i = 0; i < BOARD_WIDTH + 1; i++) {
\r
3432 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].y = boardRect.top + lineGap / 2;
\r
3433 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].x =
\r
3434 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].x = boardRect.left +
\r
3435 lineGap / 2 + (i * (squareSize + lineGap));
\r
3436 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].y =
\r
3437 boardRect.top + BOARD_HEIGHT * (squareSize + lineGap);
\r
3438 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3442 /* [HGM] Licensing requirement */
\r
3444 if(gameInfo.variant == VariantGothic) GothicPopUp( GOTHIC, VariantGothic); else
\r
3447 if(gameInfo.variant == VariantFalcon) GothicPopUp( FALCON, VariantFalcon); else
\r
3449 GothicPopUp( "", VariantNormal);
\r
3452 /* if (boardSize == oldBoardSize) return; [HGM] variant might have changed */
\r
3454 /* Load piece bitmaps for this board size */
\r
3455 for (i=0; i<=2; i++) {
\r
3456 for (piece = WhitePawn;
\r
3457 (int) piece < (int) BlackPawn;
\r
3458 piece = (ChessSquare) ((int) piece + 1)) {
\r
3459 if (pieceBitmap[i][piece] != NULL)
\r
3460 DeleteObject(pieceBitmap[i][piece]);
\r
3464 fontBitmapSquareSize = 0; /* [HGM] render: make sure pieces will be recreated, as we might need others now */
\r
3465 // Orthodox Chess pieces
\r
3466 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s");
\r
3467 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s");
\r
3468 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "s");
\r
3469 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "s");
\r
3470 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "s");
\r
3471 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "o");
\r
3472 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "o");
\r
3473 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "o");
\r
3474 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "o");
\r
3475 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "o");
\r
3476 pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "w");
\r
3477 pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "w");
\r
3478 pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "w");
\r
3479 pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w");
\r
3480 pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w");
\r
3481 if( !strcmp(appData.variant, "shogi") && (squareSize==72 || squareSize==49)) {
\r
3482 // in Shogi, Hijack the unused Queen for Lance
\r
3483 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3484 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3485 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3487 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s");
\r
3488 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o");
\r
3489 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w");
\r
3492 if(squareSize <= 72 && squareSize >= 33) {
\r
3493 /* A & C are available in most sizes now */
\r
3494 if(squareSize != 49 && squareSize != 72 && squareSize != 33) { // Vortex-like
\r
3495 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3496 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3497 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3498 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3499 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3500 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3501 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3502 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3503 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3504 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3505 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3506 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3507 } else { // Smirf-like
\r
3508 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "s");
\r
3509 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "o");
\r
3510 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "w");
\r
3512 if(gameInfo.variant == VariantGothic) { // Vortex-like
\r
3513 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3514 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3515 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3516 } else { // WinBoard standard
\r
3517 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s");
\r
3518 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o");
\r
3519 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "w");
\r
3524 if(squareSize==72 || squareSize==49 || squareSize==33) { /* experiment with some home-made bitmaps */
\r
3525 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "s");
\r
3526 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "o");
\r
3527 pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "w");
\r
3528 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "s");
\r
3529 pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "o");
\r
3530 pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3531 pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "s");
\r
3532 pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "o");
\r
3533 pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "w");
\r
3534 pieceBitmap[0][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "s");
\r
3535 pieceBitmap[1][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "o");
\r
3536 pieceBitmap[2][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "w");
\r
3537 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3538 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3539 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3540 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "s");
\r
3541 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "o");
\r
3542 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "w");
\r
3543 pieceBitmap[0][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "s");
\r
3544 pieceBitmap[1][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "o");
\r
3545 pieceBitmap[2][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "w");
\r
3546 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "s");
\r
3547 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "o");
\r
3548 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "w");
\r
3549 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3550 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3551 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3552 pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s");
\r
3553 pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o");
\r
3554 pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w");
\r
3556 if(gameInfo.variant == VariantShogi) { /* promoted Gold represemtations */
\r
3557 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s");
\r
3558 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "o");
\r
3559 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3560 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "s");
\r
3561 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "o");
\r
3562 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3563 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "s");
\r
3564 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "o");
\r
3565 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3566 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "s");
\r
3567 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "o");
\r
3568 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3570 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "s");
\r
3571 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "o");
\r
3572 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "w");
\r
3573 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "s");
\r
3574 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "o");
\r
3575 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "w");
\r
3576 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3577 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3578 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3579 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "s");
\r
3580 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "o");
\r
3581 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "w");
\r
3584 } else { /* other size, no special bitmaps available. Use smaller symbols */
\r
3585 if((int)boardSize < 2) minorSize = sizeInfo[0].squareSize;
\r
3586 else minorSize = sizeInfo[(int)boardSize - 2].squareSize;
\r
3587 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "s");
\r
3588 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "o");
\r
3589 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "w");
\r
3590 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "s");
\r
3591 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "o");
\r
3592 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "w");
\r
3593 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "s");
\r
3594 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "o");
\r
3595 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "w");
\r
3596 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "s");
\r
3597 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "o");
\r
3598 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "w");
\r
3602 if(gameInfo.variant == VariantShogi && squareSize == 58)
\r
3603 /* special Shogi support in this size */
\r
3604 { for (i=0; i<=2; i++) { /* replace all bitmaps */
\r
3605 for (piece = WhitePawn;
\r
3606 (int) piece < (int) BlackPawn;
\r
3607 piece = (ChessSquare) ((int) piece + 1)) {
\r
3608 if (pieceBitmap[i][piece] != NULL)
\r
3609 DeleteObject(pieceBitmap[i][piece]);
\r
3612 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3613 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3614 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3615 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3616 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3617 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3618 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r
3619 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");
\r
3620 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");
\r
3621 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");
\r
3622 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");
\r
3623 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");
\r
3624 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");
\r
3625 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");
\r
3626 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3627 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3628 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3629 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3630 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3631 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3632 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r
3633 pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");
\r
3634 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");
\r
3635 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");
\r
3636 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");
\r
3637 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");
\r
3638 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");
\r
3639 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");
\r
3640 pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "w");
\r
3641 pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "w");
\r
3642 pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3643 pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3644 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "w");
\r
3645 pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "w");
\r
3646 pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3647 pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3648 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "sp", squareSize, "w");
\r
3649 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "sn", squareSize, "w");
\r
3650 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r