2 * WinBoard.c -- Windows NT front end to XBoard
\r
3 * $Id: winboard.c,v 2.3 2003/11/25 05:25:20 mann Exp $
\r
5 * Copyright 1991 by Digital Equipment Corporation, Maynard,
\r
6 * Massachusetts. Enhancements Copyright
\r
7 * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software
\r
10 * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,
\r
11 * which was written and is copyrighted by Wayne Christopher.
\r
13 * The following terms apply to Digital Equipment Corporation's copyright
\r
14 * interest in XBoard:
\r
15 * ------------------------------------------------------------------------
\r
16 * All Rights Reserved
\r
18 * Permission to use, copy, modify, and distribute this software and its
\r
19 * documentation for any purpose and without fee is hereby granted,
\r
20 * provided that the above copyright notice appear in all copies and that
\r
21 * both that copyright notice and this permission notice appear in
\r
22 * supporting documentation, and that the name of Digital not be
\r
23 * used in advertising or publicity pertaining to distribution of the
\r
24 * software without specific, written prior permission.
\r
26 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
\r
27 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
\r
28 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
\r
29 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
\r
30 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
\r
31 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
\r
33 * ------------------------------------------------------------------------
\r
35 * The following terms apply to the enhanced version of XBoard
\r
36 * distributed by the Free Software Foundation:
\r
37 * ------------------------------------------------------------------------
\r
39 * GNU XBoard is free software: you can redistribute it and/or modify
\r
40 * it under the terms of the GNU General Public License as published by
\r
41 * the Free Software Foundation, either version 3 of the License, or (at
\r
42 * your option) any later version.
\r
44 * GNU XBoard is distributed in the hope that it will be useful, but
\r
45 * WITHOUT ANY WARRANTY; without even the implied warranty of
\r
46 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
47 * General Public License for more details.
\r
49 * You should have received a copy of the GNU General Public License
\r
50 * along with this program. If not, see http://www.gnu.org/licenses/. *
\r
52 *------------------------------------------------------------------------
\r
53 ** See the file ChangeLog for a revision history. */
\r
57 #include <windows.h>
\r
58 #include <winuser.h>
\r
59 #include <winsock.h>
\r
60 #include <commctrl.h>
\r
66 #include <sys/stat.h>
\r
69 #include <commdlg.h>
\r
71 #include <richedit.h>
\r
72 #include <mmsystem.h>
\r
81 #include "winboard.h"
\r
82 #include "frontend.h"
\r
83 #include "backend.h"
\r
85 #include "wclipbrd.h"
\r
86 #include "wgamelist.h"
\r
87 #include "wedittags.h"
\r
88 #include "woptions.h"
\r
89 #include "wsockerr.h"
\r
90 #include "defaults.h"
\r
94 //void InitEngineUCI( const char * iniDir, ChessProgramState * cps );
\r
97 void mysrandom(unsigned int seed);
\r
99 extern int whiteFlag, blackFlag;
\r
100 Boolean flipClock = FALSE;
\r
102 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);
\r
103 VOID NewVariantPopup(HWND hwnd);
\r
104 int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,
\r
105 /*char*/int promoChar));
\r
106 void AnimateAtomicCapture(int fromX, int fromY, int toX, int toY, int nFrames);
\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[] = "ICS 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, consoleX, consoleY, consoleW, consoleH;
\r
156 static int squareSize, lineGap, minorSize;
\r
157 static int winWidth, winHeight;
\r
158 static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo
\r
159 static int logoHeight = 0;
\r
160 static char messageText[MESSAGE_TEXT_MAX];
\r
161 static int clockTimerEvent = 0;
\r
162 static int loadGameTimerEvent = 0;
\r
163 static int analysisTimerEvent = 0;
\r
164 static DelayedEventCallback delayedTimerCallback;
\r
165 static int delayedTimerEvent = 0;
\r
166 static int buttonCount = 2;
\r
167 char *icsTextMenuString;
\r
169 char *firstChessProgramNames;
\r
170 char *secondChessProgramNames;
\r
172 #define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */
\r
174 #define PALETTESIZE 256
\r
176 HINSTANCE hInst; /* current instance */
\r
177 HWND hwndMain = NULL; /* root window*/
\r
178 HWND hwndConsole = NULL;
\r
179 BOOLEAN alwaysOnTop = FALSE;
\r
181 COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
\r
182 blackPieceColor, highlightSquareColor, premoveHighlightColor;
\r
184 ColorClass currentColorClass;
\r
186 HWND hCommPort = NULL; /* currently open comm port */
\r
187 static HWND hwndPause; /* pause button */
\r
188 static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */
\r
189 static HBRUSH lightSquareBrush, darkSquareBrush,
\r
190 blackSquareBrush, /* [HGM] for band between board and holdings */
\r
191 explodeBrush, /* [HGM] atomic */
\r
192 whitePieceBrush, blackPieceBrush, iconBkgndBrush /*, outlineBrush*/;
\r
193 static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];
\r
194 static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];
\r
195 static HPEN gridPen = NULL;
\r
196 static HPEN highlightPen = NULL;
\r
197 static HPEN premovePen = NULL;
\r
198 static NPLOGPALETTE pLogPal;
\r
199 static BOOL paletteChanged = FALSE;
\r
200 static HICON iconWhite, iconBlack, iconCurrent;
\r
201 static int doingSizing = FALSE;
\r
202 static int lastSizing = 0;
\r
203 static int prevStderrPort;
\r
205 /* [AS] Support for background textures */
\r
206 #define BACK_TEXTURE_MODE_DISABLED 0
\r
207 #define BACK_TEXTURE_MODE_PLAIN 1
\r
208 #define BACK_TEXTURE_MODE_FULL_RANDOM 2
\r
210 static HBITMAP liteBackTexture = NULL;
\r
211 static HBITMAP darkBackTexture = NULL;
\r
212 static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
213 static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
214 static int backTextureSquareSize = 0;
\r
215 static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_SIZE][BOARD_SIZE];
\r
217 #if __GNUC__ && !defined(_winmajor)
\r
218 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */
\r
220 #define oldDialog (_winmajor < 4)
\r
223 char *defaultTextAttribs[] =
\r
225 COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,
\r
226 COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,
\r
236 int cliWidth, cliHeight;
\r
239 SizeInfo sizeInfo[] =
\r
241 { "tiny", 21, 0, 1, 1, 0, 0 },
\r
242 { "teeny", 25, 1, 1, 1, 0, 0 },
\r
243 { "dinky", 29, 1, 1, 1, 0, 0 },
\r
244 { "petite", 33, 1, 1, 1, 0, 0 },
\r
245 { "slim", 37, 2, 1, 0, 0, 0 },
\r
246 { "small", 40, 2, 1, 0, 0, 0 },
\r
247 { "mediocre", 45, 2, 1, 0, 0, 0 },
\r
248 { "middling", 49, 2, 0, 0, 0, 0 },
\r
249 { "average", 54, 2, 0, 0, 0, 0 },
\r
250 { "moderate", 58, 3, 0, 0, 0, 0 },
\r
251 { "medium", 64, 3, 0, 0, 0, 0 },
\r
252 { "bulky", 72, 3, 0, 0, 0, 0 },
\r
253 { "large", 80, 3, 0, 0, 0, 0 },
\r
254 { "big", 87, 3, 0, 0, 0, 0 },
\r
255 { "huge", 95, 3, 0, 0, 0, 0 },
\r
256 { "giant", 108, 3, 0, 0, 0, 0 },
\r
257 { "colossal", 116, 4, 0, 0, 0, 0 },
\r
258 { "titanic", 129, 4, 0, 0, 0, 0 },
\r
259 { NULL, 0, 0, 0, 0, 0, 0 }
\r
262 #define MF(x) {x, {{0,}, 0. }, {0, }, 0}
\r
263 MyFont fontRec[NUM_SIZES][NUM_FONTS] =
\r
265 { 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
266 { 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
267 { 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
268 { 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
269 { 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
270 { 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
271 { 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
272 { 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
273 { 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
274 { 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
275 { 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
276 { 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
277 { 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
278 { 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
279 { 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
280 { 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
281 { 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
282 { 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
285 MyFont *font[NUM_SIZES][NUM_FONTS];
\r
294 #define BUTTON_WIDTH (tinyLayout ? 16 : 32)
\r
295 #define N_BUTTONS 5
\r
297 MyButtonDesc buttonDesc[N_BUTTONS] =
\r
299 {"<<", IDM_ToStart, NULL, NULL},
\r
300 {"<", IDM_Backward, NULL, NULL},
\r
301 {"P", IDM_Pause, NULL, NULL},
\r
302 {">", IDM_Forward, NULL, NULL},
\r
303 {">>", IDM_ToEnd, NULL, NULL},
\r
306 int tinyLayout = 0, smallLayout = 0;
\r
307 #define MENU_BAR_ITEMS 6
\r
308 char *menuBarText[2][MENU_BAR_ITEMS+1] = {
\r
309 { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },
\r
310 { "&F", "&M", "&A", "&S", "&O", "&H", NULL },
\r
314 MySound sounds[(int)NSoundClasses];
\r
315 MyTextAttribs textAttribs[(int)NColorClasses];
\r
317 MyColorizeAttribs colorizeAttribs[] = {
\r
318 { (COLORREF)0, 0, "Shout Text" },
\r
319 { (COLORREF)0, 0, "SShout/CShout" },
\r
320 { (COLORREF)0, 0, "Channel 1 Text" },
\r
321 { (COLORREF)0, 0, "Channel Text" },
\r
322 { (COLORREF)0, 0, "Kibitz Text" },
\r
323 { (COLORREF)0, 0, "Tell Text" },
\r
324 { (COLORREF)0, 0, "Challenge Text" },
\r
325 { (COLORREF)0, 0, "Request Text" },
\r
326 { (COLORREF)0, 0, "Seek Text" },
\r
327 { (COLORREF)0, 0, "Normal Text" },
\r
328 { (COLORREF)0, 0, "None" }
\r
333 static char *commentTitle;
\r
334 static char *commentText;
\r
335 static int commentIndex;
\r
336 static Boolean editComment = FALSE;
\r
337 HWND commentDialog = NULL;
\r
338 BOOLEAN commentDialogUp = FALSE;
\r
339 static int commentX, commentY, commentH, commentW;
\r
341 static char *analysisTitle;
\r
342 static char *analysisText;
\r
343 HWND analysisDialog = NULL;
\r
344 BOOLEAN analysisDialogUp = FALSE;
\r
345 static int analysisX, analysisY, analysisH, analysisW;
\r
347 char errorTitle[MSG_SIZ];
\r
348 char errorMessage[2*MSG_SIZ];
\r
349 HWND errorDialog = NULL;
\r
350 BOOLEAN moveErrorMessageUp = FALSE;
\r
351 BOOLEAN consoleEcho = TRUE;
\r
352 CHARFORMAT consoleCF;
\r
353 COLORREF consoleBackgroundColor;
\r
355 char *programVersion;
\r
361 typedef int CPKind;
\r
370 SOCKET sock2; /* stderr socket for OpenRcmd */
\r
373 #define INPUT_SOURCE_BUF_SIZE 4096
\r
375 typedef struct _InputSource {
\r
382 char buf[INPUT_SOURCE_BUF_SIZE];
\r
386 InputCallback func;
\r
387 struct _InputSource *second; /* for stderr thread on CPRcmd */
\r
391 InputSource *consoleInputSource;
\r
396 VOID ConsoleOutput(char* data, int length, int forceVisible);
\r
397 VOID ConsoleCreate();
\r
399 ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
400 VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
\r
401 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
\r
402 VOID ParseCommSettings(char *arg, DCB *dcb);
\r
404 StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
405 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
\r
406 void ParseIcsTextMenu(char *icsTextMenuString);
\r
407 VOID PopUpMoveDialog(char firstchar);
\r
408 VOID PopUpNameDialog(char firstchar);
\r
409 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
\r
413 int GameListOptions();
\r
415 HWND moveHistoryDialog = NULL;
\r
416 BOOLEAN moveHistoryDialogUp = FALSE;
\r
418 WindowPlacement wpMoveHistory;
\r
420 HWND evalGraphDialog = NULL;
\r
421 BOOLEAN evalGraphDialogUp = FALSE;
\r
423 WindowPlacement wpEvalGraph;
\r
425 HWND engineOutputDialog = NULL;
\r
426 BOOLEAN engineOutputDialogUp = FALSE;
\r
428 WindowPlacement wpEngineOutput;
\r
430 VOID MoveHistoryPopUp();
\r
431 VOID MoveHistoryPopDown();
\r
432 VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
433 BOOL MoveHistoryIsUp();
\r
435 VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
436 VOID EvalGraphPopUp();
\r
437 VOID EvalGraphPopDown();
\r
438 BOOL EvalGraphIsUp();
\r
440 VOID EngineOutputPopUp();
\r
441 VOID EngineOutputPopDown();
\r
442 BOOL EngineOutputIsUp();
\r
443 VOID EngineOutputUpdate( FrontEndProgramStats * stats );
\r
445 VOID GothicPopUp(char *title, VariantClass variant);
\r
447 * Setting "frozen" should disable all user input other than deleting
\r
448 * the window. We do this while engines are initializing themselves.
\r
450 static int frozen = 0;
\r
451 static int oldMenuItemState[MENU_BAR_ITEMS];
\r
457 if (frozen) return;
\r
459 hmenu = GetMenu(hwndMain);
\r
460 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
461 oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
\r
463 DrawMenuBar(hwndMain);
\r
466 /* Undo a FreezeUI */
\r
472 if (!frozen) return;
\r
474 hmenu = GetMenu(hwndMain);
\r
475 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
476 EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
\r
478 DrawMenuBar(hwndMain);
\r
481 /*---------------------------------------------------------------------------*\
\r
485 \*---------------------------------------------------------------------------*/
\r
488 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
\r
489 LPSTR lpCmdLine, int nCmdShow)
\r
492 HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
\r
493 // INITCOMMONCONTROLSEX ex;
\r
497 LoadLibrary("RICHED32.DLL");
\r
498 consoleCF.cbSize = sizeof(CHARFORMAT);
\r
500 if (!InitApplication(hInstance)) {
\r
503 if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
\r
507 // InitCommonControlsEx(&ex);
\r
508 InitCommonControls();
\r
510 hAccelMain = LoadAccelerators (hInstance, szAppName);
\r
511 hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
\r
512 hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
\r
514 /* Acquire and dispatch messages until a WM_QUIT message is received. */
\r
516 while (GetMessage(&msg, /* message structure */
\r
517 NULL, /* handle of window receiving the message */
\r
518 0, /* lowest message to examine */
\r
519 0)) /* highest message to examine */
\r
521 if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
\r
522 !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
\r
523 !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
\r
524 !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
\r
525 !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
\r
526 !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
\r
527 !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
\r
528 !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) &&
\r
529 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
\r
530 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
\r
531 TranslateMessage(&msg); /* Translates virtual key codes */
\r
532 DispatchMessage(&msg); /* Dispatches message to window */
\r
537 return (msg.wParam); /* Returns the value from PostQuitMessage */
\r
540 /*---------------------------------------------------------------------------*\
\r
542 * Initialization functions
\r
544 \*---------------------------------------------------------------------------*/
\r
547 InitApplication(HINSTANCE hInstance)
\r
551 /* Fill in window class structure with parameters that describe the */
\r
554 wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
\r
555 wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
\r
556 wc.cbClsExtra = 0; /* No per-class extra data. */
\r
557 wc.cbWndExtra = 0; /* No per-window extra data. */
\r
558 wc.hInstance = hInstance; /* Owner of this class */
\r
559 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
560 wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
\r
561 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
\r
562 wc.lpszMenuName = szAppName; /* Menu name from .RC */
\r
563 wc.lpszClassName = szAppName; /* Name to register as */
\r
565 /* Register the window class and return success/failure code. */
\r
566 if (!RegisterClass(&wc)) return FALSE;
\r
568 wc.style = CS_HREDRAW | CS_VREDRAW;
\r
569 wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
\r
571 wc.cbWndExtra = DLGWINDOWEXTRA;
\r
572 wc.hInstance = hInstance;
\r
573 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
574 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
\r
575 wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
\r
576 wc.lpszMenuName = NULL;
\r
577 wc.lpszClassName = szConsoleName;
\r
579 if (!RegisterClass(&wc)) return FALSE;
\r
584 /* Set by InitInstance, used by EnsureOnScreen */
\r
585 int screenHeight, screenWidth;
\r
588 EnsureOnScreen(int *x, int *y)
\r
590 // int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
\r
591 /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
\r
592 if (*x > screenWidth - 32) *x = 0;
\r
593 if (*y > screenHeight - 32) *y = 0;
\r
594 if (*x < 0) *x = 0;
\r
595 if (*y < 0) *y = 0;
\r
596 // if (*x < 10) *x = 10;
\r
597 // if (*y < gap) *y = gap;
\r
601 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
\r
603 HWND hwnd; /* Main window handle. */
\r
605 WINDOWPLACEMENT wp;
\r
608 hInst = hInstance; /* Store instance handle in our global variable */
\r
610 if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
\r
611 *filepart = NULLCHAR;
\r
613 GetCurrentDirectory(MSG_SIZ, installDir);
\r
615 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise
\r
616 InitAppData(lpCmdLine); /* Get run-time parameters */
\r
617 if (appData.debugMode) {
\r
618 debugFP = fopen(appData.nameOfDebugFile, "w");
\r
619 setbuf(debugFP, NULL);
\r
624 // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()
\r
625 // InitEngineUCI( installDir, &second );
\r
627 /* Create a main window for this application instance. */
\r
628 hwnd = CreateWindow(szAppName, szTitle,
\r
629 (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
\r
630 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
\r
631 NULL, NULL, hInstance, NULL);
\r
634 /* If window could not be created, return "failure" */
\r
639 /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */
\r
640 if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {
\r
641 first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
643 if (first.programLogo == NULL && appData.debugMode) {
\r
644 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );
\r
646 } else if(appData.autoLogo) {
\r
647 if(appData.firstDirectory && appData.firstDirectory[0]) {
\r
649 sprintf(buf, "%s/logo.bmp", appData.firstDirectory);
\r
650 first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
654 if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {
\r
655 second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
657 if (second.programLogo == NULL && appData.debugMode) {
\r
658 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );
\r
660 } else if(appData.autoLogo) {
\r
661 if(appData.secondDirectory && appData.secondDirectory[0]) {
\r
663 sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);
\r
664 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
668 iconWhite = LoadIcon(hInstance, "icon_white");
\r
669 iconBlack = LoadIcon(hInstance, "icon_black");
\r
670 iconCurrent = iconWhite;
\r
671 InitDrawingColors();
\r
672 screenHeight = GetSystemMetrics(SM_CYSCREEN);
\r
673 screenWidth = GetSystemMetrics(SM_CXSCREEN);
\r
674 for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
\r
675 /* Compute window size for each board size, and use the largest
\r
676 size that fits on this screen as the default. */
\r
677 InitDrawingSizes((BoardSize)ibs, 0);
\r
678 if (boardSize == (BoardSize)-1 &&
\r
679 winHeight <= screenHeight
\r
680 - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10
\r
681 && winWidth <= screenWidth) {
\r
682 boardSize = (BoardSize)ibs;
\r
686 InitDrawingSizes(boardSize, 0);
\r
688 buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
\r
690 /* [AS] Load textures if specified */
\r
691 ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );
\r
693 if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {
\r
694 liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
695 liteBackTextureMode = appData.liteBackTextureMode;
\r
697 if (liteBackTexture == NULL && appData.debugMode) {
\r
698 fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );
\r
702 if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {
\r
703 darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
704 darkBackTextureMode = appData.darkBackTextureMode;
\r
706 if (darkBackTexture == NULL && appData.debugMode) {
\r
707 fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );
\r
711 mysrandom( (unsigned) time(NULL) );
\r
713 /* [AS] Restore layout */
\r
714 if( wpMoveHistory.visible ) {
\r
715 MoveHistoryPopUp();
\r
718 if( wpEvalGraph.visible ) {
\r
722 if( wpEngineOutput.visible ) {
\r
723 EngineOutputPopUp();
\r
728 /* Make the window visible; update its client area; and return "success" */
\r
729 EnsureOnScreen(&boardX, &boardY);
\r
730 wp.length = sizeof(WINDOWPLACEMENT);
\r
732 wp.showCmd = nCmdShow;
\r
733 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
\r
734 wp.rcNormalPosition.left = boardX;
\r
735 wp.rcNormalPosition.right = boardX + winWidth;
\r
736 wp.rcNormalPosition.top = boardY;
\r
737 wp.rcNormalPosition.bottom = boardY + winHeight;
\r
738 SetWindowPlacement(hwndMain, &wp);
\r
740 SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
741 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
744 /* [AS] Disable the FRC stuff if not playing the proper variant */
\r
745 if( gameInfo.variant != VariantFischeRandom ) {
\r
746 EnableMenuItem( GetMenu(hwndMain), IDM_NewGameFRC, MF_GRAYED );
\r
751 SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
752 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
754 ShowWindow(hwndConsole, nCmdShow);
\r
756 UpdateWindow(hwnd);
\r
764 ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
\r
765 ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
\r
766 ArgSettingsFilename
\r
774 String *pString; // ArgString
\r
775 int *pInt; // ArgInt
\r
776 float *pFloat; // ArgFloat
\r
777 Boolean *pBoolean; // ArgBoolean
\r
778 COLORREF *pColor; // ArgColor
\r
779 ColorClass cc; // ArgAttribs
\r
780 String *pFilename; // ArgFilename
\r
781 BoardSize *pBoardSize; // ArgBoardSize
\r
782 int whichFont; // ArgFont
\r
783 DCB *pDCB; // ArgCommSettings
\r
784 String *pFilename; // ArgSettingsFilename
\r
792 ArgDescriptor argDescriptors[] = {
\r
793 /* positional arguments */
\r
794 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
795 { "", ArgNone, NULL },
\r
796 /* keyword arguments */
\r
797 { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },
\r
798 { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },
\r
799 { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },
\r
800 { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },
\r
801 { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },
\r
802 { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },
\r
803 { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },
\r
804 { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },
\r
805 { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },
\r
806 { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },
\r
807 { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },
\r
808 { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },
\r
809 { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },
\r
810 { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },
\r
811 { "initString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
812 { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
813 { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },
\r
814 { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,
\r
816 { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,
\r
818 { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,
\r
820 { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },
\r
821 { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,
\r
823 { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },
\r
824 { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
825 { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
826 { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
827 { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
828 { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },
\r
829 { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },
\r
830 { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
831 { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
832 { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
833 { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
834 { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
835 { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
836 { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
837 { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
838 { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
839 { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
840 /*!!bitmapDirectory?*/
\r
841 { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
842 { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
843 { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
844 { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
845 { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },
\r
846 { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },
\r
847 { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },
\r
848 { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },
\r
849 { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },
\r
850 { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },
\r
851 { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },
\r
852 { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },
\r
853 { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
854 { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
855 { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
856 { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
857 { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
858 { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
859 { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
860 { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
861 { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
862 { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
863 { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
864 { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
865 { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },
\r
866 { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },
\r
867 { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
868 { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
869 { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },
\r
870 { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },
\r
871 { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },
\r
872 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
873 { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
874 { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
875 { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
876 { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },
\r
877 { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },
\r
878 { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },
\r
879 { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },
\r
880 { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
881 { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
882 { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
883 { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
884 { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
885 { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
886 { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
887 { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
888 { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },
\r
889 { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },
\r
890 { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
891 { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
892 { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
893 { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
894 { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },
\r
895 { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },
\r
896 { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
897 { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
898 { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },
\r
899 { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },
\r
900 { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
901 { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
902 { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },
\r
903 { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },
\r
904 { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
905 { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
906 { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
907 { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
908 { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
909 { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
910 { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },
\r
911 { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },
\r
912 { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
913 { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
914 { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },
\r
915 { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },
\r
916 { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
917 { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
918 { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },
\r
919 { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },
\r
920 { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
921 { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
922 { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },
\r
923 { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },
\r
924 { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
925 { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
926 { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },
\r
927 { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },
\r
928 { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
929 { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
930 { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },
\r
931 { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
932 { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
933 { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
934 { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors,
\r
935 FALSE }, /* only so that old WinBoard.ini files from betas can be read */
\r
936 { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },
\r
937 { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },
\r
938 { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },
\r
939 { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },
\r
940 { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },
\r
941 { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },
\r
942 { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE }, /* [AS] */
\r
943 { "boardSize", ArgBoardSize, (LPVOID) &boardSize,
\r
944 TRUE }, /* must come after all fonts */
\r
945 { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },
\r
946 { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,
\r
947 FALSE }, /* historical; kept only so old winboard.ini files will parse */
\r
948 { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },
\r
949 { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },
\r
950 { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
951 { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
952 { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },
\r
953 { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },
\r
954 { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
955 { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
956 { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },
\r
957 { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },
\r
958 { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
959 { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
960 { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },
\r
961 { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },
\r
962 { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
963 { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
964 { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },
\r
965 { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },
\r
966 { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
967 { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
968 { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },
\r
969 { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },
\r
970 { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
971 { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
972 { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },
\r
973 { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
974 { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
975 { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
977 { "cmailGameName", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
978 { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
980 { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },
\r
981 { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
982 { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
983 { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
984 { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },
\r
985 { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
986 { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
987 { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
988 { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },
\r
989 { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },
\r
990 { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
991 { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
992 { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },
\r
993 { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },
\r
994 { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
995 { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
996 { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },
\r
997 { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },
\r
998 { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
999 { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
1000 { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },
\r
1001 { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },
\r
1002 { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
1003 { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
1004 { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },
\r
1005 { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },
\r
1006 { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
1007 { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
1008 { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },
\r
1009 { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },
\r
1010 { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },
\r
1011 { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1012 { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1013 { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },
\r
1014 { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},
\r
1015 { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},
\r
1016 { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1017 { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1018 { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},
\r
1019 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1020 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1021 { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },
\r
1022 { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1023 { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1024 { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },
\r
1025 { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },
\r
1026 { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1027 { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1028 { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },
\r
1029 { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },
\r
1030 { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },
\r
1031 { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1032 { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1033 { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },
\r
1034 { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },
\r
1035 { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1036 { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1037 { "highlightLastMove", ArgBoolean,
\r
1038 (LPVOID) &appData.highlightLastMove, TRUE },
\r
1039 { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1040 { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1041 { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1042 { "highlightDragging", ArgBoolean,
\r
1043 (LPVOID) &appData.highlightDragging, TRUE },
\r
1044 { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },
\r
1045 { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1046 { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1047 { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },
\r
1048 { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },
\r
1049 { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1050 { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1051 { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },
\r
1052 { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },
\r
1053 { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },
\r
1054 { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },
\r
1055 { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },
\r
1056 { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },
\r
1057 { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },
\r
1058 { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },
\r
1059 { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },
\r
1060 { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },
\r
1061 { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },
\r
1062 { "soundShout", ArgFilename,
\r
1063 (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },
\r
1064 { "soundSShout", ArgFilename,
\r
1065 (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },
\r
1066 { "soundChannel1", ArgFilename,
\r
1067 (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },
\r
1068 { "soundChannel", ArgFilename,
\r
1069 (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },
\r
1070 { "soundKibitz", ArgFilename,
\r
1071 (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },
\r
1072 { "soundTell", ArgFilename,
\r
1073 (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },
\r
1074 { "soundChallenge", ArgFilename,
\r
1075 (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },
\r
1076 { "soundRequest", ArgFilename,
\r
1077 (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },
\r
1078 { "soundSeek", ArgFilename,
\r
1079 (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },
\r
1080 { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },
\r
1081 { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },
\r
1082 { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },
\r
1083 { "soundIcsLoss", ArgFilename,
\r
1084 (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },
\r
1085 { "soundIcsDraw", ArgFilename,
\r
1086 (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },
\r
1087 { "soundIcsUnfinished", ArgFilename,
\r
1088 (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},
\r
1089 { "soundIcsAlarm", ArgFilename,
\r
1090 (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },
\r
1091 { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },
\r
1092 { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },
\r
1093 { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1094 { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1095 { "reuseChessPrograms", ArgBoolean,
\r
1096 (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */
\r
1097 { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },
\r
1098 { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },
\r
1099 { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1100 { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1101 { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },
\r
1102 { "x", ArgInt, (LPVOID) &boardX, TRUE },
\r
1103 { "y", ArgInt, (LPVOID) &boardY, TRUE },
\r
1104 { "icsX", ArgInt, (LPVOID) &consoleX, TRUE },
\r
1105 { "icsY", ArgInt, (LPVOID) &consoleY, TRUE },
\r
1106 { "icsW", ArgInt, (LPVOID) &consoleW, TRUE },
\r
1107 { "icsH", ArgInt, (LPVOID) &consoleH, TRUE },
\r
1108 { "analysisX", ArgInt, (LPVOID) &analysisX, TRUE },
\r
1109 { "analysisY", ArgInt, (LPVOID) &analysisY, TRUE },
\r
1110 { "analysisW", ArgInt, (LPVOID) &analysisW, TRUE },
\r
1111 { "analysisH", ArgInt, (LPVOID) &analysisH, TRUE },
\r
1112 { "commentX", ArgInt, (LPVOID) &commentX, TRUE },
\r
1113 { "commentY", ArgInt, (LPVOID) &commentY, TRUE },
\r
1114 { "commentW", ArgInt, (LPVOID) &commentW, TRUE },
\r
1115 { "commentH", ArgInt, (LPVOID) &commentH, TRUE },
\r
1116 { "tagsX", ArgInt, (LPVOID) &editTagsX, TRUE },
\r
1117 { "tagsY", ArgInt, (LPVOID) &editTagsY, TRUE },
\r
1118 { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },
\r
1119 { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },
\r
1120 { "gameListX", ArgInt, (LPVOID) &gameListX, TRUE },
\r
1121 { "gameListY", ArgInt, (LPVOID) &gameListY, TRUE },
\r
1122 { "gameListW", ArgInt, (LPVOID) &gameListW, TRUE },
\r
1123 { "gameListH", ArgInt, (LPVOID) &gameListH, TRUE },
\r
1124 { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1125 { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1126 { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },
\r
1127 { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },
\r
1128 { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },
\r
1129 { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1130 { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1131 { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },
\r
1132 { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },
\r
1133 { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,
\r
1135 { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,
\r
1137 { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1138 { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1139 { "variant", ArgString, (LPVOID) &appData.variant, FALSE },
\r
1140 { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion, FALSE },
\r
1141 { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,FALSE },
\r
1142 { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },
\r
1143 { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },
\r
1144 { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1145 { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1146 /* [AS] New features */
\r
1147 { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE },
\r
1148 { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE },
\r
1149 { "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE },
\r
1150 { "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE },
\r
1151 { "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE },
\r
1152 { "darkBackTextureFile", ArgString, (LPVOID) &appData.darkBackTextureFile, TRUE },
\r
1153 { "liteBackTextureMode", ArgInt, (LPVOID) &appData.liteBackTextureMode, TRUE },
\r
1154 { "darkBackTextureMode", ArgInt, (LPVOID) &appData.darkBackTextureMode, TRUE },
\r
1155 { "renderPiecesWithFont", ArgString, (LPVOID) &appData.renderPiecesWithFont, TRUE },
\r
1156 { "fontPieceToCharTable", ArgString, (LPVOID) &appData.fontToPieceTable, TRUE },
\r
1157 { "fontPieceBackColorWhite", ArgColor, (LPVOID) &appData.fontBackColorWhite, TRUE },
\r
1158 { "fontPieceForeColorWhite", ArgColor, (LPVOID) &appData.fontForeColorWhite, TRUE },
\r
1159 { "fontPieceBackColorBlack", ArgColor, (LPVOID) &appData.fontBackColorBlack, TRUE },
\r
1160 { "fontPieceForeColorBlack", ArgColor, (LPVOID) &appData.fontForeColorBlack, TRUE },
\r
1161 { "fontPieceSize", ArgInt, (LPVOID) &appData.fontPieceSize, TRUE },
\r
1162 { "overrideLineGap", ArgInt, (LPVOID) &appData.overrideLineGap, TRUE },
\r
1163 { "adjudicateLossThreshold", ArgInt, (LPVOID) &appData.adjudicateLossThreshold, TRUE },
\r
1164 { "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE },
\r
1165 { "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE },
\r
1166 { "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1167 { "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1168 { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },
\r
1169 { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE },
\r
1170 { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE },
\r
1171 { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE },
\r
1172 { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE },
\r
1173 { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE },
\r
1174 { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE },
\r
1175 { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE },
\r
1176 { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE },
\r
1177 { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE },
\r
1178 { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE },
\r
1179 { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE },
\r
1180 { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE },
\r
1181 { "firstIsUCI", ArgBoolean, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1182 { "fUCI", ArgTrue, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1183 { "secondIsUCI", ArgBoolean, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1184 { "sUCI", ArgTrue, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1185 { "firstHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1186 { "fNoOwnBookUCI", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1187 { "firstXBook", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1188 { "secondHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1189 { "sNoOwnBookUCI", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1190 { "secondXBook", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1191 { "polyglotDir", ArgFilename, (LPVOID) &appData.polyglotDir, TRUE },
\r
1192 { "usePolyglotBook", ArgBoolean, (LPVOID) &appData.usePolyglotBook, TRUE },
\r
1193 { "polyglotBook", ArgFilename, (LPVOID) &appData.polyglotBook, TRUE },
\r
1194 { "defaultHashSize", ArgInt, (LPVOID) &appData.defaultHashSize, TRUE },
\r
1195 { "defaultCacheSizeEGTB", ArgInt, (LPVOID) &appData.defaultCacheSizeEGTB, TRUE },
\r
1196 { "defaultPathEGTB", ArgFilename, (LPVOID) &appData.defaultPathEGTB, TRUE },
\r
1198 /* [AS] Layout stuff */
\r
1199 { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },
\r
1200 { "moveHistoryX", ArgInt, (LPVOID) &wpMoveHistory.x, TRUE },
\r
1201 { "moveHistoryY", ArgInt, (LPVOID) &wpMoveHistory.y, TRUE },
\r
1202 { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },
\r
1203 { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },
\r
1205 { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },
\r
1206 { "evalGraphX", ArgInt, (LPVOID) &wpEvalGraph.x, TRUE },
\r
1207 { "evalGraphY", ArgInt, (LPVOID) &wpEvalGraph.y, TRUE },
\r
1208 { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },
\r
1209 { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },
\r
1211 { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },
\r
1212 { "engineOutputX", ArgInt, (LPVOID) &wpEngineOutput.x, TRUE },
\r
1213 { "engineOutputY", ArgInt, (LPVOID) &wpEngineOutput.y, TRUE },
\r
1214 { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },
\r
1215 { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },
\r
1217 /* [HGM] board-size, adjudication and misc. options */
\r
1218 { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE },
\r
1219 { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE },
\r
1220 { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE },
\r
1221 { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE },
\r
1222 { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE },
\r
1223 { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE },
\r
1224 { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE },
\r
1225 { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE },
\r
1226 { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE },
\r
1227 { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE },
\r
1228 { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE },
\r
1229 { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE },
\r
1230 { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE },
\r
1231 { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE },
\r
1232 { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE },
\r
1233 { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE },
\r
1234 { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE },
\r
1235 { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE },
\r
1236 { "userName", ArgString, (LPVOID) &appData.userName, FALSE },
\r
1237 { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE },
\r
1238 { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE },
\r
1239 { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE },
\r
1240 { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE },
\r
1241 { "niceEngines", ArgInt, (LPVOID) &appData.niceEngines, TRUE },
\r
1242 { "firstLogo", ArgFilename, (LPVOID) &appData.firstLogo, FALSE },
\r
1243 { "secondLogo", ArgFilename, (LPVOID) &appData.secondLogo, FALSE },
\r
1244 { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE },
\r
1245 { "firstOptions", ArgString, (LPVOID) &appData.firstOptions, FALSE },
\r
1246 { "secondOptions", ArgString, (LPVOID) &appData.secondOptions, FALSE },
\r
1247 { "firstNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride1, FALSE },
\r
1248 { "secondNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride2, FALSE },
\r
1251 { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },
\r
1252 { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },
\r
1253 { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1254 { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1255 { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },
\r
1256 { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },
\r
1257 { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1258 { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1259 { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },
\r
1260 { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },
\r
1261 { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },
\r
1262 { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE },
\r
1263 { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,
\r
1265 { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE },
\r
1266 { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE },
\r
1267 { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE },
\r
1268 { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1269 { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1270 { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE },
\r
1271 { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,
\r
1273 { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1274 { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1275 { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1276 { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE },
\r
1277 { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE },
\r
1278 { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1279 { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1280 { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1281 { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1282 { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE },
\r
1283 { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE },
\r
1284 { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1285 { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1286 { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },
\r
1287 { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },
\r
1288 { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },
\r
1289 /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */
\r
1290 { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },
\r
1292 /* [HGM] options for broadcasting and time odds */
\r
1293 { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },
\r
1294 { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },
\r
1295 { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },
\r
1296 { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },
\r
1297 { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },
\r
1298 { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },
\r
1299 { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },
\r
1300 { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },
\r
1301 { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },
\r
1302 { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },
\r
1303 { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE },
\r
1304 { NULL, ArgNone, NULL, FALSE }
\r
1308 /* Kludge for indirection files on command line */
\r
1309 char* lastIndirectionFilename;
\r
1310 ArgDescriptor argDescriptorIndirection =
\r
1311 { "", ArgSettingsFilename, (LPVOID) NULL, FALSE };
\r
1315 ExitArgError(char *msg, char *badArg)
\r
1317 char buf[MSG_SIZ];
\r
1319 sprintf(buf, "%s %s", msg, badArg);
\r
1320 DisplayFatalError(buf, 0, 2);
\r
1324 /* Command line font name parser. NULL name means do nothing.
\r
1325 Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"
\r
1326 For backward compatibility, syntax without the colon is also
\r
1327 accepted, but font names with digits in them won't work in that case.
\r
1330 ParseFontName(char *name, MyFontParams *mfp)
\r
1333 if (name == NULL) return;
\r
1335 q = strchr(p, ':');
\r
1337 if (q - p >= sizeof(mfp->faceName))
\r
1338 ExitArgError("Font name too long:", name);
\r
1339 memcpy(mfp->faceName, p, q - p);
\r
1340 mfp->faceName[q - p] = NULLCHAR;
\r
1343 q = mfp->faceName;
\r
1344 while (*p && !isdigit(*p)) {
\r
1346 if (q - mfp->faceName >= sizeof(mfp->faceName))
\r
1347 ExitArgError("Font name too long:", name);
\r
1349 while (q > mfp->faceName && q[-1] == ' ') q--;
\r
1352 if (!*p) ExitArgError("Font point size missing:", name);
\r
1353 mfp->pointSize = (float) atof(p);
\r
1354 mfp->bold = (strchr(p, 'b') != NULL);
\r
1355 mfp->italic = (strchr(p, 'i') != NULL);
\r
1356 mfp->underline = (strchr(p, 'u') != NULL);
\r
1357 mfp->strikeout = (strchr(p, 's') != NULL);
\r
1360 /* Color name parser.
\r
1361 X version accepts X color names, but this one
\r
1362 handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */
\r
1364 ParseColorName(char *name)
\r
1366 int red, green, blue, count;
\r
1367 char buf[MSG_SIZ];
\r
1369 count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);
\r
1371 count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d",
\r
1372 &red, &green, &blue);
\r
1375 sprintf(buf, "Can't parse color name %s", name);
\r
1376 DisplayError(buf, 0);
\r
1377 return RGB(0, 0, 0);
\r
1379 return PALETTERGB(red, green, blue);
\r
1383 void ParseAttribs(COLORREF *color, int *effects, char* argValue)
\r
1385 char *e = argValue;
\r
1389 if (*e == 'b') eff |= CFE_BOLD;
\r
1390 else if (*e == 'i') eff |= CFE_ITALIC;
\r
1391 else if (*e == 'u') eff |= CFE_UNDERLINE;
\r
1392 else if (*e == 's') eff |= CFE_STRIKEOUT;
\r
1393 else if (*e == '#' || isdigit(*e)) break;
\r
1397 *color = ParseColorName(e);
\r
1402 ParseBoardSize(char *name)
\r
1404 BoardSize bs = SizeTiny;
\r
1405 while (sizeInfo[bs].name != NULL) {
\r
1406 if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;
\r
1409 ExitArgError("Unrecognized board size value", name);
\r
1410 return bs; /* not reached */
\r
1415 StringGet(void *getClosure)
\r
1417 char **p = (char **) getClosure;
\r
1422 FileGet(void *getClosure)
\r
1425 FILE* f = (FILE*) getClosure;
\r
1428 if (c == '\r') c = getc(f); // work around DOS format files by bypassing the '\r' completely
\r
1435 /* Parse settings file named "name". If file found, return the
\r
1436 full name in fullname and return TRUE; else return FALSE */
\r
1438 ParseSettingsFile(char *name, char fullname[MSG_SIZ])
\r
1442 int ok; char buf[MSG_SIZ];
\r
1444 ok = SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy);
\r
1445 if(!ok && strchr(name, '.') == NULL) { // [HGM] append default file-name extension '.ini' when needed
\r
1446 sprintf(buf, "%s.ini", name);
\r
1447 ok = SearchPath(installDir, buf, NULL, MSG_SIZ, fullname, &dummy);
\r
1450 f = fopen(fullname, "r");
\r
1452 ParseArgs(FileGet, f);
\r
1461 ParseArgs(GetFunc get, void *cl)
\r
1463 char argName[ARG_MAX];
\r
1464 char argValue[ARG_MAX];
\r
1465 ArgDescriptor *ad;
\r
1474 while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);
\r
1475 if (ch == NULLCHAR) break;
\r
1477 /* Comment to end of line */
\r
1479 while (ch != '\n' && ch != NULLCHAR) ch = get(cl);
\r
1481 } else if (ch == '/' || ch == '-') {
\r
1484 while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&
\r
1485 ch != '\n' && ch != '\t') {
\r
1491 for (ad = argDescriptors; ad->argName != NULL; ad++)
\r
1492 if (strcmp(ad->argName, argName + 1) == 0) break;
\r
1494 if (ad->argName == NULL)
\r
1495 ExitArgError("Unrecognized argument", argName);
\r
1497 } else if (ch == '@') {
\r
1498 /* Indirection file */
\r
1499 ad = &argDescriptorIndirection;
\r
1502 /* Positional argument */
\r
1503 ad = &argDescriptors[posarg++];
\r
1504 strcpy(argName, ad->argName);
\r
1507 if (ad->argType == ArgTrue) {
\r
1508 *(Boolean *) ad->argLoc = TRUE;
\r
1511 if (ad->argType == ArgFalse) {
\r
1512 *(Boolean *) ad->argLoc = FALSE;
\r
1516 while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
\r
1517 if (ch == NULLCHAR || ch == '\n') {
\r
1518 ExitArgError("No value provided for argument", argName);
\r
1522 // Quoting with { }. No characters have to (or can) be escaped.
\r
1523 // Thus the string cannot contain a '}' character.
\r
1543 } else if (ch == '\'' || ch == '"') {
\r
1544 // Quoting with ' ' or " ", with \ as escape character.
\r
1545 // Inconvenient for long strings that may contain Windows filenames.
\r
1562 if (ch == start) {
\r
1571 if (ad->argType == ArgFilename
\r
1572 || ad->argType == ArgSettingsFilename) {
\r
1578 ExitArgError("Incomplete \\ escape in value for", argName);
\r
1602 for (i = 0; i < 3; i++) {
\r
1603 if (ch >= '0' && ch <= '7') {
\r
1604 octval = octval*8 + (ch - '0');
\r
1611 *q++ = (char) octval;
\r
1622 while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {
\r
1629 switch (ad->argType) {
\r
1631 *(int *) ad->argLoc = atoi(argValue);
\r
1635 *(float *) ad->argLoc = (float) atof(argValue);
\r
1640 *(char **) ad->argLoc = strdup(argValue);
\r
1643 case ArgSettingsFilename:
\r
1645 char fullname[MSG_SIZ];
\r
1646 if (ParseSettingsFile(argValue, fullname)) {
\r
1647 if (ad->argLoc != NULL) {
\r
1648 *(char **) ad->argLoc = strdup(fullname);
\r
1651 if (ad->argLoc != NULL) {
\r
1653 ExitArgError("Failed to open indirection file", argValue);
\r
1660 switch (argValue[0]) {
\r
1663 *(Boolean *) ad->argLoc = TRUE;
\r
1667 *(Boolean *) ad->argLoc = FALSE;
\r
1670 ExitArgError("Unrecognized boolean argument value", argValue);
\r
1676 *(COLORREF *)ad->argLoc = ParseColorName(argValue);
\r
1679 case ArgAttribs: {
\r
1680 ColorClass cc = (ColorClass)ad->argLoc;
\r
1681 ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);
\r
1685 case ArgBoardSize:
\r
1686 *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);
\r
1690 ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);
\r
1693 case ArgCommSettings:
\r
1694 ParseCommSettings(argValue, &dcb);
\r
1698 ExitArgError("Unrecognized argument", argValue);
\r
1707 LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
\r
1709 HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
\r
1710 lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);
\r
1713 lf->lfEscapement = 0;
\r
1714 lf->lfOrientation = 0;
\r
1715 lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;
\r
1716 lf->lfItalic = mfp->italic;
\r
1717 lf->lfUnderline = mfp->underline;
\r
1718 lf->lfStrikeOut = mfp->strikeout;
\r
1719 lf->lfCharSet = DEFAULT_CHARSET;
\r
1720 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
1721 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
1722 lf->lfQuality = DEFAULT_QUALITY;
\r
1723 lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
\r
1724 strcpy(lf->lfFaceName, mfp->faceName);
\r
1728 CreateFontInMF(MyFont *mf)
\r
1730 LFfromMFP(&mf->lf, &mf->mfp);
\r
1731 if (mf->hf) DeleteObject(mf->hf);
\r
1732 mf->hf = CreateFontIndirect(&mf->lf);
\r
1736 SetDefaultTextAttribs()
\r
1739 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1740 ParseAttribs(&textAttribs[cc].color,
\r
1741 &textAttribs[cc].effects,
\r
1742 defaultTextAttribs[cc]);
\r
1747 SetDefaultSounds()
\r
1751 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1752 textAttribs[cc].sound.name = strdup("");
\r
1753 textAttribs[cc].sound.data = NULL;
\r
1755 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1756 sounds[sc].name = strdup("");
\r
1757 sounds[sc].data = NULL;
\r
1759 sounds[(int)SoundBell].name = strdup(SOUND_BELL);
\r
1767 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1768 MyLoadSound(&textAttribs[cc].sound);
\r
1770 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1771 MyLoadSound(&sounds[sc]);
\r
1776 InitAppData(LPSTR lpCmdLine)
\r
1779 char buf[ARG_MAX], currDir[MSG_SIZ];
\r
1782 programName = szAppName;
\r
1784 /* Initialize to defaults */
\r
1785 lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);
\r
1786 darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);
\r
1787 whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);
\r
1788 blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);
\r
1789 highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);
\r
1790 premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);
\r
1791 consoleBackgroundColor = ParseColorName(COLOR_BKGD);
\r
1792 SetDefaultTextAttribs();
\r
1793 SetDefaultSounds();
\r
1794 appData.movesPerSession = MOVES_PER_SESSION;
\r
1795 appData.initString = INIT_STRING;
\r
1796 appData.secondInitString = INIT_STRING;
\r
1797 appData.firstComputerString = COMPUTER_STRING;
\r
1798 appData.secondComputerString = COMPUTER_STRING;
\r
1799 appData.firstChessProgram = FIRST_CHESS_PROGRAM;
\r
1800 appData.secondChessProgram = SECOND_CHESS_PROGRAM;
\r
1801 appData.firstPlaysBlack = FALSE;
\r
1802 appData.noChessProgram = FALSE;
\r
1803 chessProgram = FALSE;
\r
1804 appData.firstHost = FIRST_HOST;
\r
1805 appData.secondHost = SECOND_HOST;
\r
1806 appData.firstDirectory = FIRST_DIRECTORY;
\r
1807 appData.secondDirectory = SECOND_DIRECTORY;
\r
1808 appData.bitmapDirectory = "";
\r
1809 appData.remoteShell = REMOTE_SHELL;
\r
1810 appData.remoteUser = "";
\r
1811 appData.timeDelay = TIME_DELAY;
\r
1812 appData.timeControl = TIME_CONTROL;
\r
1813 appData.timeIncrement = TIME_INCREMENT;
\r
1814 appData.icsActive = FALSE;
\r
1815 appData.icsHost = "";
\r
1816 appData.icsPort = ICS_PORT;
\r
1817 appData.icsCommPort = ICS_COMM_PORT;
\r
1818 appData.icsLogon = ICS_LOGON;
\r
1819 appData.icsHelper = "";
\r
1820 appData.useTelnet = FALSE;
\r
1821 appData.telnetProgram = TELNET_PROGRAM;
\r
1822 appData.gateway = "";
\r
1823 appData.loadGameFile = "";
\r
1824 appData.loadGameIndex = 0;
\r
1825 appData.saveGameFile = "";
\r
1826 appData.autoSaveGames = FALSE;
\r
1827 appData.loadPositionFile = "";
\r
1828 appData.loadPositionIndex = 1;
\r
1829 appData.savePositionFile = "";
\r
1830 appData.matchMode = FALSE;
\r
1831 appData.matchGames = 0;
\r
1832 appData.monoMode = FALSE;
\r
1833 appData.debugMode = FALSE;
\r
1834 appData.clockMode = TRUE;
\r
1835 boardSize = (BoardSize) -1; /* determine by screen size */
\r
1836 appData.Iconic = FALSE; /*unused*/
\r
1837 appData.searchTime = "";
\r
1838 appData.searchDepth = 0;
\r
1839 appData.showCoords = FALSE;
\r
1840 appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/
\r
1841 appData.autoCallFlag = FALSE;
\r
1842 appData.flipView = FALSE;
\r
1843 appData.autoFlipView = TRUE;
\r
1844 appData.cmailGameName = "";
\r
1845 appData.alwaysPromoteToQueen = FALSE;
\r
1846 appData.oldSaveStyle = FALSE;
\r
1847 appData.quietPlay = FALSE;
\r
1848 appData.showThinking = FALSE;
\r
1849 appData.ponderNextMove = TRUE;
\r
1850 appData.periodicUpdates = TRUE;
\r
1851 appData.popupExitMessage = TRUE;
\r
1852 appData.popupMoveErrors = FALSE;
\r
1853 appData.autoObserve = FALSE;
\r
1854 appData.autoComment = FALSE;
\r
1855 appData.animate = TRUE;
\r
1856 appData.animSpeed = 10;
\r
1857 appData.animateDragging = TRUE;
\r
1858 appData.highlightLastMove = TRUE;
\r
1859 appData.getMoveList = TRUE;
\r
1860 appData.testLegality = TRUE;
\r
1861 appData.premove = TRUE;
\r
1862 appData.premoveWhite = FALSE;
\r
1863 appData.premoveWhiteText = "";
\r
1864 appData.premoveBlack = FALSE;
\r
1865 appData.premoveBlackText = "";
\r
1866 appData.icsAlarm = TRUE;
\r
1867 appData.icsAlarmTime = 5000;
\r
1868 appData.autoRaiseBoard = TRUE;
\r
1869 appData.localLineEditing = TRUE;
\r
1870 appData.colorize = TRUE;
\r
1871 appData.reuseFirst = TRUE;
\r
1872 appData.reuseSecond = TRUE;
\r
1873 appData.blindfold = FALSE;
\r
1874 appData.icsEngineAnalyze = FALSE;
\r
1875 memset(&dcb, 0, sizeof(DCB)); // required by VS 2002 +
\r
1876 dcb.DCBlength = sizeof(DCB);
\r
1877 dcb.BaudRate = 9600;
\r
1878 dcb.fBinary = TRUE;
\r
1879 dcb.fParity = FALSE;
\r
1880 dcb.fOutxCtsFlow = FALSE;
\r
1881 dcb.fOutxDsrFlow = FALSE;
\r
1882 dcb.fDtrControl = DTR_CONTROL_ENABLE;
\r
1883 dcb.fDsrSensitivity = FALSE;
\r
1884 dcb.fTXContinueOnXoff = TRUE;
\r
1885 dcb.fOutX = FALSE;
\r
1887 dcb.fNull = FALSE;
\r
1888 dcb.fRtsControl = RTS_CONTROL_ENABLE;
\r
1889 dcb.fAbortOnError = FALSE;
\r
1891 dcb.Parity = SPACEPARITY;
\r
1892 dcb.StopBits = ONESTOPBIT;
\r
1893 settingsFileName = SETTINGS_FILE;
\r
1894 saveSettingsOnExit = TRUE;
\r
1895 boardX = CW_USEDEFAULT;
\r
1896 boardY = CW_USEDEFAULT;
\r
1897 consoleX = CW_USEDEFAULT;
\r
1898 consoleY = CW_USEDEFAULT;
\r
1899 consoleW = CW_USEDEFAULT;
\r
1900 consoleH = CW_USEDEFAULT;
\r
1901 analysisX = CW_USEDEFAULT;
\r
1902 analysisY = CW_USEDEFAULT;
\r
1903 analysisW = CW_USEDEFAULT;
\r
1904 analysisH = CW_USEDEFAULT;
\r
1905 commentX = CW_USEDEFAULT;
\r
1906 commentY = CW_USEDEFAULT;
\r
1907 commentW = CW_USEDEFAULT;
\r
1908 commentH = CW_USEDEFAULT;
\r
1909 editTagsX = CW_USEDEFAULT;
\r
1910 editTagsY = CW_USEDEFAULT;
\r
1911 editTagsW = CW_USEDEFAULT;
\r
1912 editTagsH = CW_USEDEFAULT;
\r
1913 gameListX = CW_USEDEFAULT;
\r
1914 gameListY = CW_USEDEFAULT;
\r
1915 gameListW = CW_USEDEFAULT;
\r
1916 gameListH = CW_USEDEFAULT;
\r
1917 icsTextMenuString = ICS_TEXT_MENU_DEFAULT;
\r
1918 icsNames = ICS_NAMES;
\r
1919 firstChessProgramNames = FCP_NAMES;
\r
1920 secondChessProgramNames = SCP_NAMES;
\r
1921 appData.initialMode = "";
\r
1922 appData.variant = "normal";
\r
1923 appData.firstProtocolVersion = PROTOVER;
\r
1924 appData.secondProtocolVersion = PROTOVER;
\r
1925 appData.showButtonBar = TRUE;
\r
1927 /* [AS] New properties (see comments in header file) */
\r
1928 appData.firstScoreIsAbsolute = FALSE;
\r
1929 appData.secondScoreIsAbsolute = FALSE;
\r
1930 appData.saveExtendedInfoInPGN = FALSE;
\r
1931 appData.hideThinkingFromHuman = FALSE;
\r
1932 appData.liteBackTextureFile = "";
\r
1933 appData.liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
1934 appData.darkBackTextureFile = "";
\r
1935 appData.darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
1936 appData.renderPiecesWithFont = "";
\r
1937 appData.fontToPieceTable = "";
\r
1938 appData.fontBackColorWhite = 0;
\r
1939 appData.fontForeColorWhite = 0;
\r
1940 appData.fontBackColorBlack = 0;
\r
1941 appData.fontForeColorBlack = 0;
\r
1942 appData.fontPieceSize = 80;
\r
1943 appData.overrideLineGap = 1;
\r
1944 appData.adjudicateLossThreshold = 0;
\r
1945 appData.delayBeforeQuit = 0;
\r
1946 appData.delayAfterQuit = 0;
\r
1947 appData.nameOfDebugFile = "winboard.debug";
\r
1948 appData.pgnEventHeader = "Computer Chess Game";
\r
1949 appData.defaultFrcPosition = -1;
\r
1950 appData.gameListTags = GLT_DEFAULT_TAGS;
\r
1951 appData.saveOutOfBookInfo = TRUE;
\r
1952 appData.showEvalInMoveHistory = TRUE;
\r
1953 appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );
\r
1954 appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );
\r
1955 appData.highlightMoveWithArrow = FALSE;
\r
1956 appData.highlightArrowColor = ParseColorName( "#FFFF80" );
\r
1957 appData.useStickyWindows = TRUE;
\r
1958 appData.adjudicateDrawMoves = 0;
\r
1959 appData.autoDisplayComment = TRUE;
\r
1960 appData.autoDisplayTags = TRUE;
\r
1961 appData.firstIsUCI = FALSE;
\r
1962 appData.secondIsUCI = FALSE;
\r
1963 appData.firstHasOwnBookUCI = TRUE;
\r
1964 appData.secondHasOwnBookUCI = TRUE;
\r
1965 appData.polyglotDir = "";
\r
1966 appData.usePolyglotBook = FALSE;
\r
1967 appData.polyglotBook = "";
\r
1968 appData.defaultHashSize = 64;
\r
1969 appData.defaultCacheSizeEGTB = 4;
\r
1970 appData.defaultPathEGTB = "c:\\egtb";
\r
1971 appData.firstOptions = "";
\r
1972 appData.secondOptions = "";
\r
1974 InitWindowPlacement( &wpMoveHistory );
\r
1975 InitWindowPlacement( &wpEvalGraph );
\r
1976 InitWindowPlacement( &wpEngineOutput );
\r
1978 /* [HGM] User-selectable board size, adjudication control, miscellaneous */
\r
1979 appData.NrFiles = -1;
\r
1980 appData.NrRanks = -1;
\r
1981 appData.holdingsSize = -1;
\r
1982 appData.testClaims = FALSE;
\r
1983 appData.checkMates = FALSE;
\r
1984 appData.materialDraws= FALSE;
\r
1985 appData.trivialDraws = FALSE;
\r
1986 appData.ruleMoves = 51;
\r
1987 appData.drawRepeats = 6;
\r
1988 appData.matchPause = 10000;
\r
1989 appData.alphaRank = FALSE;
\r
1990 appData.allWhite = FALSE;
\r
1991 appData.upsideDown = FALSE;
\r
1992 appData.serverPause = 15;
\r
1993 appData.serverMovesName = NULL;
\r
1994 appData.suppressLoadMoves = FALSE;
\r
1995 appData.firstTimeOdds = 1;
\r
1996 appData.secondTimeOdds = 1;
\r
1997 appData.firstAccumulateTC = 1; // combine previous and current sessions
\r
1998 appData.secondAccumulateTC = 1;
\r
1999 appData.firstNPS = -1; // [HGM] nps: use wall-clock time
\r
2000 appData.secondNPS = -1;
\r
2001 appData.engineComments = 1;
\r
2002 appData.smpCores = 1; // [HGM] SMP: max nr of cores
\r
2003 appData.egtFormats = "";
\r
2006 appData.zippyTalk = ZIPPY_TALK;
\r
2007 appData.zippyPlay = ZIPPY_PLAY;
\r
2008 appData.zippyLines = ZIPPY_LINES;
\r
2009 appData.zippyPinhead = ZIPPY_PINHEAD;
\r
2010 appData.zippyPassword = ZIPPY_PASSWORD;
\r
2011 appData.zippyPassword2 = ZIPPY_PASSWORD2;
\r
2012 appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;
\r
2013 appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;
\r
2014 appData.zippyUseI = ZIPPY_USE_I;
\r
2015 appData.zippyBughouse = ZIPPY_BUGHOUSE;
\r
2016 appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;
\r
2017 appData.zippyGameEnd = ZIPPY_GAME_END;
\r
2018 appData.zippyGameStart = ZIPPY_GAME_START;
\r
2019 appData.zippyAdjourn = ZIPPY_ADJOURN;
\r
2020 appData.zippyAbort = ZIPPY_ABORT;
\r
2021 appData.zippyVariants = ZIPPY_VARIANTS;
\r
2022 appData.zippyMaxGames = ZIPPY_MAX_GAMES;
\r
2023 appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;
\r
2026 /* Point font array elements to structures and
\r
2027 parse default font names */
\r
2028 for (i=0; i<NUM_FONTS; i++) {
\r
2029 for (j=0; j<NUM_SIZES; j++) {
\r
2030 font[j][i] = &fontRec[j][i];
\r
2031 ParseFontName(font[j][i]->def, &font[j][i]->mfp);
\r
2035 /* Parse default settings file if any */
\r
2036 if (ParseSettingsFile(settingsFileName, buf)) {
\r
2037 settingsFileName = strdup(buf);
\r
2040 /* Parse command line */
\r
2041 ParseArgs(StringGet, &lpCmdLine);
\r
2043 /* [HGM] make sure board size is acceptable */
\r
2044 if(appData.NrFiles > BOARD_SIZE ||
\r
2045 appData.NrRanks > BOARD_SIZE )
\r
2046 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
2048 /* [HGM] After parsing the options from the .ini file, and overruling them
\r
2049 * with options from the command line, we now make an even higher priority
\r
2050 * overrule by WB options attached to the engine command line. This so that
\r
2051 * tournament managers can use WB options (such as /timeOdds) that follow
\r
2054 if(appData.firstChessProgram != NULL) {
\r
2055 char *p = StrStr(appData.firstChessProgram, "WBopt");
\r
2056 static char *f = "first";
\r
2057 char buf[MSG_SIZ], *q = buf;
\r
2058 if(p != NULL) { // engine command line contains WinBoard options
\r
2059 sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"
\r
2060 ParseArgs(StringGet, &q);
\r
2061 p[-1] = 0; // cut them offengine command line
\r
2064 // now do same for second chess program
\r
2065 if(appData.secondChessProgram != NULL) {
\r
2066 char *p = StrStr(appData.secondChessProgram, "WBopt");
\r
2067 static char *s = "second";
\r
2068 char buf[MSG_SIZ], *q = buf;
\r
2069 if(p != NULL) { // engine command line contains WinBoard options
\r
2070 sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"
\r
2071 ParseArgs(StringGet, &q);
\r
2072 p[-1] = 0; // cut them offengine command line
\r
2077 /* Propagate options that affect others */
\r
2078 if (appData.matchMode || appData.matchGames) chessProgram = TRUE;
\r
2079 if (appData.icsActive || appData.noChessProgram) {
\r
2080 chessProgram = FALSE; /* not local chess program mode */
\r
2083 /* Open startup dialog if needed */
\r
2084 if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||
\r
2085 (appData.icsActive && *appData.icsHost == NULLCHAR) ||
\r
2086 (chessProgram && (*appData.firstChessProgram == NULLCHAR ||
\r
2087 *appData.secondChessProgram == NULLCHAR))) {
\r
2090 lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);
\r
2091 DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);
\r
2092 FreeProcInstance(lpProc);
\r
2095 /* Make sure save files land in the right (?) directory */
\r
2096 if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {
\r
2097 appData.saveGameFile = strdup(buf);
\r
2099 if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {
\r
2100 appData.savePositionFile = strdup(buf);
\r
2103 /* Finish initialization for fonts and sounds */
\r
2104 for (i=0; i<NUM_FONTS; i++) {
\r
2105 for (j=0; j<NUM_SIZES; j++) {
\r
2106 CreateFontInMF(font[j][i]);
\r
2109 /* xboard, and older WinBoards, controlled the move sound with the
\r
2110 appData.ringBellAfterMoves option. In the current WinBoard, we
\r
2111 always turn the option on (so that the backend will call us),
\r
2112 then let the user turn the sound off by setting it to silence if
\r
2113 desired. To accommodate old winboard.ini files saved by old
\r
2114 versions of WinBoard, we also turn off the sound if the option
\r
2115 was initially set to false. */
\r
2116 if (!appData.ringBellAfterMoves) {
\r
2117 sounds[(int)SoundMove].name = strdup("");
\r
2118 appData.ringBellAfterMoves = TRUE;
\r
2120 GetCurrentDirectory(MSG_SIZ, currDir);
\r
2121 SetCurrentDirectory(installDir);
\r
2123 SetCurrentDirectory(currDir);
\r
2125 p = icsTextMenuString;
\r
2126 if (p[0] == '@') {
\r
2127 FILE* f = fopen(p + 1, "r");
\r
2129 DisplayFatalError(p + 1, errno, 2);
\r
2132 i = fread(buf, 1, sizeof(buf)-1, f);
\r
2134 buf[i] = NULLCHAR;
\r
2137 ParseIcsTextMenu(strdup(p));
\r
2144 HMENU hmenu = GetMenu(hwndMain);
\r
2146 (void) EnableMenuItem(hmenu, IDM_CommPort,
\r
2147 MF_BYCOMMAND|((appData.icsActive &&
\r
2148 *appData.icsCommPort != NULLCHAR) ?
\r
2149 MF_ENABLED : MF_GRAYED));
\r
2150 (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,
\r
2151 MF_BYCOMMAND|(saveSettingsOnExit ?
\r
2152 MF_CHECKED : MF_UNCHECKED));
\r
2157 SaveSettings(char* name)
\r
2160 ArgDescriptor *ad;
\r
2161 WINDOWPLACEMENT wp;
\r
2162 char dir[MSG_SIZ];
\r
2164 if (!hwndMain) return;
\r
2166 GetCurrentDirectory(MSG_SIZ, dir);
\r
2167 SetCurrentDirectory(installDir);
\r
2168 f = fopen(name, "w");
\r
2169 SetCurrentDirectory(dir);
\r
2171 DisplayError(name, errno);
\r
2174 fprintf(f, ";\n");
\r
2175 fprintf(f, "; %s %s.%s Save Settings file\n", PRODUCT, VERSION, PATCHLEVEL);
\r
2176 fprintf(f, ";\n");
\r
2177 fprintf(f, "; You can edit the values of options that are already set in this file,\n");
\r
2178 fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");
\r
2179 fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");
\r
2180 fprintf(f, ";\n");
\r
2182 wp.length = sizeof(WINDOWPLACEMENT);
\r
2183 GetWindowPlacement(hwndMain, &wp);
\r
2184 boardX = wp.rcNormalPosition.left;
\r
2185 boardY = wp.rcNormalPosition.top;
\r
2187 if (hwndConsole) {
\r
2188 GetWindowPlacement(hwndConsole, &wp);
\r
2189 consoleX = wp.rcNormalPosition.left;
\r
2190 consoleY = wp.rcNormalPosition.top;
\r
2191 consoleW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2192 consoleH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2195 if (analysisDialog) {
\r
2196 GetWindowPlacement(analysisDialog, &wp);
\r
2197 analysisX = wp.rcNormalPosition.left;
\r
2198 analysisY = wp.rcNormalPosition.top;
\r
2199 analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2200 analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2203 if (commentDialog) {
\r
2204 GetWindowPlacement(commentDialog, &wp);
\r
2205 commentX = wp.rcNormalPosition.left;
\r
2206 commentY = wp.rcNormalPosition.top;
\r
2207 commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2208 commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2211 if (editTagsDialog) {
\r
2212 GetWindowPlacement(editTagsDialog, &wp);
\r
2213 editTagsX = wp.rcNormalPosition.left;
\r
2214 editTagsY = wp.rcNormalPosition.top;
\r
2215 editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2216 editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2219 if (gameListDialog) {
\r
2220 GetWindowPlacement(gameListDialog, &wp);
\r
2221 gameListX = wp.rcNormalPosition.left;
\r
2222 gameListY = wp.rcNormalPosition.top;
\r
2223 gameListW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2224 gameListH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2227 /* [AS] Move history */
\r
2228 wpMoveHistory.visible = MoveHistoryIsUp();
\r
2230 if( moveHistoryDialog ) {
\r
2231 GetWindowPlacement(moveHistoryDialog, &wp);
\r
2232 wpMoveHistory.x = wp.rcNormalPosition.left;
\r
2233 wpMoveHistory.y = wp.rcNormalPosition.top;
\r
2234 wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2235 wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2238 /* [AS] Eval graph */
\r
2239 wpEvalGraph.visible = EvalGraphIsUp();
\r
2241 if( evalGraphDialog ) {
\r
2242 GetWindowPlacement(evalGraphDialog, &wp);
\r
2243 wpEvalGraph.x = wp.rcNormalPosition.left;
\r
2244 wpEvalGraph.y = wp.rcNormalPosition.top;
\r
2245 wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2246 wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2249 /* [AS] Engine output */
\r
2250 wpEngineOutput.visible = EngineOutputIsUp();
\r
2252 if( engineOutputDialog ) {
\r
2253 GetWindowPlacement(engineOutputDialog, &wp);
\r
2254 wpEngineOutput.x = wp.rcNormalPosition.left;
\r
2255 wpEngineOutput.y = wp.rcNormalPosition.top;
\r
2256 wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2257 wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2260 for (ad = argDescriptors; ad->argName != NULL; ad++) {
\r
2261 if (!ad->save) continue;
\r
2262 switch (ad->argType) {
\r
2265 char *p = *(char **)ad->argLoc;
\r
2266 if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {
\r
2267 /* Quote multiline values or \-containing values
\r
2268 with { } if possible */
\r
2269 fprintf(f, "/%s={%s}\n", ad->argName, p);
\r
2271 /* Else quote with " " */
\r
2272 fprintf(f, "/%s=\"", ad->argName);
\r
2274 if (*p == '\n') fprintf(f, "\n");
\r
2275 else if (*p == '\r') fprintf(f, "\\r");
\r
2276 else if (*p == '\t') fprintf(f, "\\t");
\r
2277 else if (*p == '\b') fprintf(f, "\\b");
\r
2278 else if (*p == '\f') fprintf(f, "\\f");
\r
2279 else if (*p < ' ') fprintf(f, "\\%03o", *p);
\r
2280 else if (*p == '\"') fprintf(f, "\\\"");
\r
2281 else if (*p == '\\') fprintf(f, "\\\\");
\r
2285 fprintf(f, "\"\n");
\r
2290 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);
\r
2293 fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);
\r
2296 fprintf(f, "/%s=%s\n", ad->argName,
\r
2297 (*(Boolean *)ad->argLoc) ? "true" : "false");
\r
2300 if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2303 if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2307 COLORREF color = *(COLORREF *)ad->argLoc;
\r
2308 fprintf(f, "/%s=#%02lx%02lx%02lx\n", ad->argName,
\r
2309 color&0xff, (color>>8)&0xff, (color>>16)&0xff);
\r
2314 MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];
\r
2315 fprintf(f, "/%s=\"%s%s%s%s%s#%02lx%02lx%02lx\"\n", ad->argName,
\r
2316 (ta->effects & CFE_BOLD) ? "b" : "",
\r
2317 (ta->effects & CFE_ITALIC) ? "i" : "",
\r
2318 (ta->effects & CFE_UNDERLINE) ? "u" : "",
\r
2319 (ta->effects & CFE_STRIKEOUT) ? "s" : "",
\r
2320 (ta->effects) ? " " : "",
\r
2321 ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);
\r
2325 if (strchr(*(char **)ad->argLoc, '\"')) {
\r
2326 fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);
\r
2328 fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);
\r
2331 case ArgBoardSize:
\r
2332 fprintf(f, "/%s=%s\n", ad->argName,
\r
2333 sizeInfo[*(BoardSize *)ad->argLoc].name);
\r
2338 for (bs=0; bs<NUM_SIZES; bs++) {
\r
2339 MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;
\r
2340 fprintf(f, "/size=%s ", sizeInfo[bs].name);
\r
2341 fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n",
\r
2342 ad->argName, mfp->faceName, mfp->pointSize,
\r
2343 mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",
\r
2344 mfp->bold ? "b" : "",
\r
2345 mfp->italic ? "i" : "",
\r
2346 mfp->underline ? "u" : "",
\r
2347 mfp->strikeout ? "s" : "");
\r
2351 case ArgCommSettings:
\r
2352 PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);
\r
2354 case ArgSettingsFilename: ;
\r
2362 /*---------------------------------------------------------------------------*\
\r
2364 * GDI board drawing routines
\r
2366 \*---------------------------------------------------------------------------*/
\r
2368 /* [AS] Draw square using background texture */
\r
2369 static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )
\r
2374 return; /* Should never happen! */
\r
2377 SetGraphicsMode( dst, GM_ADVANCED );
\r
2384 /* X reflection */
\r
2389 x.eDx = (FLOAT) dw + dx - 1;
\r
2392 SetWorldTransform( dst, &x );
\r
2395 /* Y reflection */
\r
2401 x.eDy = (FLOAT) dh + dy - 1;
\r
2403 SetWorldTransform( dst, &x );
\r
2411 x.eDx = (FLOAT) dx;
\r
2412 x.eDy = (FLOAT) dy;
\r
2415 SetWorldTransform( dst, &x );
\r
2419 BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );
\r
2427 SetWorldTransform( dst, &x );
\r
2429 ModifyWorldTransform( dst, 0, MWT_IDENTITY );
\r
2432 /* [AS] [HGM] Make room for more piece types, so all pieces can be different */
\r
2434 PM_WP = (int) WhitePawn,
\r
2435 PM_WN = (int) WhiteKnight,
\r
2436 PM_WB = (int) WhiteBishop,
\r
2437 PM_WR = (int) WhiteRook,
\r
2438 PM_WQ = (int) WhiteQueen,
\r
2439 PM_WF = (int) WhiteFerz,
\r
2440 PM_WW = (int) WhiteWazir,
\r
2441 PM_WE = (int) WhiteAlfil,
\r
2442 PM_WM = (int) WhiteMan,
\r
2443 PM_WO = (int) WhiteCannon,
\r
2444 PM_WU = (int) WhiteUnicorn,
\r
2445 PM_WH = (int) WhiteNightrider,
\r
2446 PM_WA = (int) WhiteAngel,
\r
2447 PM_WC = (int) WhiteMarshall,
\r
2448 PM_WAB = (int) WhiteCardinal,
\r
2449 PM_WD = (int) WhiteDragon,
\r
2450 PM_WL = (int) WhiteLance,
\r
2451 PM_WS = (int) WhiteCobra,
\r
2452 PM_WV = (int) WhiteFalcon,
\r
2453 PM_WSG = (int) WhiteSilver,
\r
2454 PM_WG = (int) WhiteGrasshopper,
\r
2455 PM_WK = (int) WhiteKing,
\r
2456 PM_BP = (int) BlackPawn,
\r
2457 PM_BN = (int) BlackKnight,
\r
2458 PM_BB = (int) BlackBishop,
\r
2459 PM_BR = (int) BlackRook,
\r
2460 PM_BQ = (int) BlackQueen,
\r
2461 PM_BF = (int) BlackFerz,
\r
2462 PM_BW = (int) BlackWazir,
\r
2463 PM_BE = (int) BlackAlfil,
\r
2464 PM_BM = (int) BlackMan,
\r
2465 PM_BO = (int) BlackCannon,
\r
2466 PM_BU = (int) BlackUnicorn,
\r
2467 PM_BH = (int) BlackNightrider,
\r
2468 PM_BA = (int) BlackAngel,
\r
2469 PM_BC = (int) BlackMarshall,
\r
2470 PM_BG = (int) BlackGrasshopper,
\r
2471 PM_BAB = (int) BlackCardinal,
\r
2472 PM_BD = (int) BlackDragon,
\r
2473 PM_BL = (int) BlackLance,
\r
2474 PM_BS = (int) BlackCobra,
\r
2475 PM_BV = (int) BlackFalcon,
\r
2476 PM_BSG = (int) BlackSilver,
\r
2477 PM_BK = (int) BlackKing
\r
2480 static HFONT hPieceFont = NULL;
\r
2481 static HBITMAP hPieceMask[(int) EmptySquare];
\r
2482 static HBITMAP hPieceFace[(int) EmptySquare];
\r
2483 static int fontBitmapSquareSize = 0;
\r
2484 static char pieceToFontChar[(int) EmptySquare] =
\r
2485 { 'p', 'n', 'b', 'r', 'q',
\r
2486 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',
\r
2487 'k', 'o', 'm', 'v', 't', 'w',
\r
2488 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',
\r
2491 extern BOOL SetCharTable( char *table, const char * map );
\r
2492 /* [HGM] moved to backend.c */
\r
2494 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )
\r
2497 BYTE r1 = GetRValue( color );
\r
2498 BYTE g1 = GetGValue( color );
\r
2499 BYTE b1 = GetBValue( color );
\r
2505 /* Create a uniform background first */
\r
2506 hbrush = CreateSolidBrush( color );
\r
2507 SetRect( &rc, 0, 0, squareSize, squareSize );
\r
2508 FillRect( hdc, &rc, hbrush );
\r
2509 DeleteObject( hbrush );
\r
2512 /* Vertical gradient, good for pawn, knight and rook, less for queen and king */
\r
2513 int steps = squareSize / 2;
\r
2516 for( i=0; i<steps; i++ ) {
\r
2517 BYTE r = r1 - (r1-r2) * i / steps;
\r
2518 BYTE g = g1 - (g1-g2) * i / steps;
\r
2519 BYTE b = b1 - (b1-b2) * i / steps;
\r
2521 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2522 SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );
\r
2523 FillRect( hdc, &rc, hbrush );
\r
2524 DeleteObject(hbrush);
\r
2527 else if( mode == 2 ) {
\r
2528 /* Diagonal gradient, good more or less for every piece */
\r
2529 POINT triangle[3];
\r
2530 HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );
\r
2531 HBRUSH hbrush_old;
\r
2532 int steps = squareSize;
\r
2535 triangle[0].x = squareSize - steps;
\r
2536 triangle[0].y = squareSize;
\r
2537 triangle[1].x = squareSize;
\r
2538 triangle[1].y = squareSize;
\r
2539 triangle[2].x = squareSize;
\r
2540 triangle[2].y = squareSize - steps;
\r
2542 for( i=0; i<steps; i++ ) {
\r
2543 BYTE r = r1 - (r1-r2) * i / steps;
\r
2544 BYTE g = g1 - (g1-g2) * i / steps;
\r
2545 BYTE b = b1 - (b1-b2) * i / steps;
\r
2547 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2548 hbrush_old = SelectObject( hdc, hbrush );
\r
2549 Polygon( hdc, triangle, 3 );
\r
2550 SelectObject( hdc, hbrush_old );
\r
2551 DeleteObject(hbrush);
\r
2556 SelectObject( hdc, hpen );
\r
2561 [AS] The method I use to create the bitmaps it a bit tricky, but it
\r
2562 seems to work ok. The main problem here is to find the "inside" of a chess
\r
2563 piece: follow the steps as explained below.
\r
2565 static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
\r
2569 COLORREF chroma = RGB(0xFF,0x00,0xFF);
\r
2573 int backColor = whitePieceColor;
\r
2574 int foreColor = blackPieceColor;
\r
2576 if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {
\r
2577 backColor = appData.fontBackColorWhite;
\r
2578 foreColor = appData.fontForeColorWhite;
\r
2580 else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {
\r
2581 backColor = appData.fontBackColorBlack;
\r
2582 foreColor = appData.fontForeColorBlack;
\r
2586 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2588 hbm_old = SelectObject( hdc, hbm );
\r
2592 rc.right = squareSize;
\r
2593 rc.bottom = squareSize;
\r
2595 /* Step 1: background is now black */
\r
2596 FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );
\r
2598 GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );
\r
2600 pt.x = (squareSize - sz.cx) / 2;
\r
2601 pt.y = (squareSize - sz.cy) / 2;
\r
2603 SetBkMode( hdc, TRANSPARENT );
\r
2604 SetTextColor( hdc, chroma );
\r
2605 /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */
\r
2606 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2608 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
\r
2609 /* Step 3: the area outside the piece is filled with white */
\r
2610 // FloodFill( hdc, 0, 0, chroma );
\r
2611 ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );
\r
2612 ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big
\r
2613 ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );
\r
2614 ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );
\r
2615 SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
\r
2617 Step 4: this is the tricky part, the area inside the piece is filled with black,
\r
2618 but if the start point is not inside the piece we're lost!
\r
2619 There should be a better way to do this... if we could create a region or path
\r
2620 from the fill operation we would be fine for example.
\r
2622 // FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );
\r
2623 ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );
\r
2625 { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */
\r
2626 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2627 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2629 SelectObject( dc2, bm2 );
\r
2630 BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy
\r
2631 BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2632 BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2633 BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2634 BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2637 DeleteObject( bm2 );
\r
2640 SetTextColor( hdc, 0 );
\r
2642 Step 5: some fonts have "disconnected" areas that are skipped by the fill:
\r
2643 draw the piece again in black for safety.
\r
2645 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2647 SelectObject( hdc, hbm_old );
\r
2649 if( hPieceMask[index] != NULL ) {
\r
2650 DeleteObject( hPieceMask[index] );
\r
2653 hPieceMask[index] = hbm;
\r
2656 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2658 SelectObject( hdc, hbm );
\r
2661 HDC dc1 = CreateCompatibleDC( hdc_window );
\r
2662 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2663 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2665 SelectObject( dc1, hPieceMask[index] );
\r
2666 SelectObject( dc2, bm2 );
\r
2667 FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );
\r
2668 BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );
\r
2671 Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves
\r
2672 the piece background and deletes (makes transparent) the rest.
\r
2673 Thanks to that mask, we are free to paint the background with the greates
\r
2674 freedom, as we'll be able to mask off the unwanted parts when finished.
\r
2675 We use this, to make gradients and give the pieces a "roundish" look.
\r
2677 SetPieceBackground( hdc, backColor, 2 );
\r
2678 BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );
\r
2682 DeleteObject( bm2 );
\r
2685 SetTextColor( hdc, foreColor );
\r
2686 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2688 SelectObject( hdc, hbm_old );
\r
2690 if( hPieceFace[index] != NULL ) {
\r
2691 DeleteObject( hPieceFace[index] );
\r
2694 hPieceFace[index] = hbm;
\r
2697 static int TranslatePieceToFontPiece( int piece )
\r
2727 case BlackMarshall:
\r
2731 case BlackNightrider:
\r
2737 case BlackUnicorn:
\r
2741 case BlackGrasshopper:
\r
2753 case BlackCardinal:
\r
2760 case WhiteMarshall:
\r
2764 case WhiteNightrider:
\r
2770 case WhiteUnicorn:
\r
2774 case WhiteGrasshopper:
\r
2786 case WhiteCardinal:
\r
2795 void CreatePiecesFromFont()
\r
2798 HDC hdc_window = NULL;
\r
2804 if( fontBitmapSquareSize < 0 ) {
\r
2805 /* Something went seriously wrong in the past: do not try to recreate fonts! */
\r
2809 if( appData.renderPiecesWithFont == NULL || appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {
\r
2810 fontBitmapSquareSize = -1;
\r
2814 if( fontBitmapSquareSize != squareSize ) {
\r
2815 hdc_window = GetDC( hwndMain );
\r
2816 hdc = CreateCompatibleDC( hdc_window );
\r
2818 if( hPieceFont != NULL ) {
\r
2819 DeleteObject( hPieceFont );
\r
2822 for( i=0; i<=(int)BlackKing; i++ ) {
\r
2823 hPieceMask[i] = NULL;
\r
2824 hPieceFace[i] = NULL;
\r
2830 if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {
\r
2831 fontHeight = appData.fontPieceSize;
\r
2834 fontHeight = (fontHeight * squareSize) / 100;
\r
2836 lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
\r
2838 lf.lfEscapement = 0;
\r
2839 lf.lfOrientation = 0;
\r
2840 lf.lfWeight = FW_NORMAL;
\r
2842 lf.lfUnderline = 0;
\r
2843 lf.lfStrikeOut = 0;
\r
2844 lf.lfCharSet = DEFAULT_CHARSET;
\r
2845 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
2846 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
2847 lf.lfQuality = PROOF_QUALITY;
\r
2848 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
\r
2849 strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );
\r
2850 lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';
\r
2852 hPieceFont = CreateFontIndirect( &lf );
\r
2854 if( hPieceFont == NULL ) {
\r
2855 fontBitmapSquareSize = -2;
\r
2858 /* Setup font-to-piece character table */
\r
2859 if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {
\r
2860 /* No (or wrong) global settings, try to detect the font */
\r
2861 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {
\r
2863 SetCharTable(pieceToFontChar, "phbrqkojntwl");
\r
2865 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {
\r
2866 /* DiagramTT* family */
\r
2867 SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");
\r
2869 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {
\r
2870 /* Fairy symbols */
\r
2871 SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
\r
2873 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {
\r
2874 /* Good Companion (Some characters get warped as literal :-( */
\r
2875 char s[] = "1cmWG0ñueOS¯®oYI23wgQU";
\r
2876 s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;
\r
2877 SetCharTable(pieceToFontChar, s);
\r
2880 /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */
\r
2881 SetCharTable(pieceToFontChar, "pnbrqkomvtwl");
\r
2885 /* Create bitmaps */
\r
2886 hfont_old = SelectObject( hdc, hPieceFont );
\r
2888 CreatePieceMaskFromFont( hdc_window, hdc, PM_WP );
\r
2889 CreatePieceMaskFromFont( hdc_window, hdc, PM_WN );
\r
2890 CreatePieceMaskFromFont( hdc_window, hdc, PM_WB );
\r
2891 CreatePieceMaskFromFont( hdc_window, hdc, PM_WR );
\r
2892 CreatePieceMaskFromFont( hdc_window, hdc, PM_WQ );
\r
2893 CreatePieceMaskFromFont( hdc_window, hdc, PM_WK );
\r
2894 CreatePieceMaskFromFont( hdc_window, hdc, PM_BP );
\r
2895 CreatePieceMaskFromFont( hdc_window, hdc, PM_BN );
\r
2896 CreatePieceMaskFromFont( hdc_window, hdc, PM_BB );
\r
2897 CreatePieceMaskFromFont( hdc_window, hdc, PM_BR );
\r
2898 CreatePieceMaskFromFont( hdc_window, hdc, PM_BQ );
\r
2899 CreatePieceMaskFromFont( hdc_window, hdc, PM_BK );
\r
2901 CreatePieceMaskFromFont( hdc_window, hdc, PM_WA );
\r
2902 CreatePieceMaskFromFont( hdc_window, hdc, PM_WC );
\r
2903 CreatePieceMaskFromFont( hdc_window, hdc, PM_WF );
\r
2904 CreatePieceMaskFromFont( hdc_window, hdc, PM_WH );
\r
2905 CreatePieceMaskFromFont( hdc_window, hdc, PM_WE );
\r
2906 CreatePieceMaskFromFont( hdc_window, hdc, PM_WW );
\r
2907 CreatePieceMaskFromFont( hdc_window, hdc, PM_WU );
\r
2908 CreatePieceMaskFromFont( hdc_window, hdc, PM_WO );
\r
2909 CreatePieceMaskFromFont( hdc_window, hdc, PM_WG );
\r
2910 CreatePieceMaskFromFont( hdc_window, hdc, PM_WM );
\r
2911 CreatePieceMaskFromFont( hdc_window, hdc, PM_WSG );
\r
2912 CreatePieceMaskFromFont( hdc_window, hdc, PM_WV );
\r
2913 CreatePieceMaskFromFont( hdc_window, hdc, PM_WAB );
\r
2914 CreatePieceMaskFromFont( hdc_window, hdc, PM_WD );
\r
2915 CreatePieceMaskFromFont( hdc_window, hdc, PM_WL );
\r
2916 CreatePieceMaskFromFont( hdc_window, hdc, PM_WS );
\r
2917 CreatePieceMaskFromFont( hdc_window, hdc, PM_BA );
\r
2918 CreatePieceMaskFromFont( hdc_window, hdc, PM_BC );
\r
2919 CreatePieceMaskFromFont( hdc_window, hdc, PM_BF );
\r
2920 CreatePieceMaskFromFont( hdc_window, hdc, PM_BH );
\r
2921 CreatePieceMaskFromFont( hdc_window, hdc, PM_BE );
\r
2922 CreatePieceMaskFromFont( hdc_window, hdc, PM_BW );
\r
2923 CreatePieceMaskFromFont( hdc_window, hdc, PM_BU );
\r
2924 CreatePieceMaskFromFont( hdc_window, hdc, PM_BO );
\r
2925 CreatePieceMaskFromFont( hdc_window, hdc, PM_BG );
\r
2926 CreatePieceMaskFromFont( hdc_window, hdc, PM_BM );
\r
2927 CreatePieceMaskFromFont( hdc_window, hdc, PM_BSG );
\r
2928 CreatePieceMaskFromFont( hdc_window, hdc, PM_BV );
\r
2929 CreatePieceMaskFromFont( hdc_window, hdc, PM_BAB );
\r
2930 CreatePieceMaskFromFont( hdc_window, hdc, PM_BD );
\r
2931 CreatePieceMaskFromFont( hdc_window, hdc, PM_BL );
\r
2932 CreatePieceMaskFromFont( hdc_window, hdc, PM_BS );
\r
2934 for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */
\r
2935 if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */
\r
2936 CreatePieceMaskFromFont( hdc_window, hdc, i );
\r
2938 SelectObject( hdc, hfont_old );
\r
2940 fontBitmapSquareSize = squareSize;
\r
2944 if( hdc != NULL ) {
\r
2948 if( hdc_window != NULL ) {
\r
2949 ReleaseDC( hwndMain, hdc_window );
\r
2954 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)
\r
2958 sprintf(name, "%s%d%s", piece, squareSize, suffix);
\r
2959 if (gameInfo.event &&
\r
2960 strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&
\r
2961 strcmp(name, "k80s") == 0) {
\r
2962 strcpy(name, "tim");
\r
2964 return LoadBitmap(hinst, name);
\r
2968 /* Insert a color into the program's logical palette
\r
2969 structure. This code assumes the given color is
\r
2970 the result of the RGB or PALETTERGB macro, and it
\r
2971 knows how those macros work (which is documented).
\r
2974 InsertInPalette(COLORREF color)
\r
2976 LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);
\r
2978 if (pLogPal->palNumEntries++ >= PALETTESIZE) {
\r
2979 DisplayFatalError("Too many colors", 0, 1);
\r
2980 pLogPal->palNumEntries--;
\r
2984 pe->peFlags = (char) 0;
\r
2985 pe->peRed = (char) (0xFF & color);
\r
2986 pe->peGreen = (char) (0xFF & (color >> 8));
\r
2987 pe->peBlue = (char) (0xFF & (color >> 16));
\r
2993 InitDrawingColors()
\r
2995 if (pLogPal == NULL) {
\r
2996 /* Allocate enough memory for a logical palette with
\r
2997 * PALETTESIZE entries and set the size and version fields
\r
2998 * of the logical palette structure.
\r
3000 pLogPal = (NPLOGPALETTE)
\r
3001 LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +
\r
3002 (sizeof(PALETTEENTRY) * (PALETTESIZE))));
\r
3003 pLogPal->palVersion = 0x300;
\r
3005 pLogPal->palNumEntries = 0;
\r
3007 InsertInPalette(lightSquareColor);
\r
3008 InsertInPalette(darkSquareColor);
\r
3009 InsertInPalette(whitePieceColor);
\r
3010 InsertInPalette(blackPieceColor);
\r
3011 InsertInPalette(highlightSquareColor);
\r
3012 InsertInPalette(premoveHighlightColor);
\r
3014 /* create a logical color palette according the information
\r
3015 * in the LOGPALETTE structure.
\r
3017 hPal = CreatePalette((LPLOGPALETTE) pLogPal);
\r
3019 lightSquareBrush = CreateSolidBrush(lightSquareColor);
\r
3020 blackSquareBrush = CreateSolidBrush(blackPieceColor);
\r
3021 darkSquareBrush = CreateSolidBrush(darkSquareColor);
\r
3022 whitePieceBrush = CreateSolidBrush(whitePieceColor);
\r
3023 blackPieceBrush = CreateSolidBrush(blackPieceColor);
\r
3024 iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
\r
3025 explodeBrush = CreateSolidBrush(highlightSquareColor); // [HGM] atomic
\r
3026 /* [AS] Force rendering of the font-based pieces */
\r
3027 if( fontBitmapSquareSize > 0 ) {
\r
3028 fontBitmapSquareSize = 0;
\r
3034 BoardWidth(int boardSize, int n)
\r
3035 { /* [HGM] argument n added to allow different width and height */
\r
3036 int lineGap = sizeInfo[boardSize].lineGap;
\r
3038 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3039 lineGap = appData.overrideLineGap;
\r
3042 return (n + 1) * lineGap +
\r
3043 n * sizeInfo[boardSize].squareSize;
\r
3046 /* Respond to board resize by dragging edge */
\r
3048 ResizeBoard(int newSizeX, int newSizeY, int flags)
\r
3050 BoardSize newSize = NUM_SIZES - 1;
\r
3051 static int recurse = 0;
\r
3052 if (IsIconic(hwndMain)) return;
\r
3053 if (recurse > 0) return;
\r
3055 while (newSize > 0) {
\r
3056 InitDrawingSizes(newSize+1000, 0); // [HGM] kludge to update sizeInfo without visible effects
\r
3057 if(newSizeX >= sizeInfo[newSize].cliWidth &&
\r
3058 newSizeY >= sizeInfo[newSize].cliHeight) break;
\r
3061 boardSize = newSize;
\r
3062 InitDrawingSizes(boardSize, flags);
\r
3069 InitDrawingSizes(BoardSize boardSize, int flags)
\r
3071 int i, boardWidth, boardHeight; /* [HGM] height treated separately */
\r
3072 ChessSquare piece;
\r
3073 static int oldBoardSize = -1, oldTinyLayout = 0;
\r
3075 SIZE clockSize, messageSize;
\r
3077 char buf[MSG_SIZ];
\r
3079 HMENU hmenu = GetMenu(hwndMain);
\r
3080 RECT crect, wrect;
\r
3082 LOGBRUSH logbrush;
\r
3084 int suppressVisibleEffects = 0; // [HGM] kludge to request updating sizeInfo only
\r
3085 if((int)boardSize >= 1000 ) { boardSize -= 1000; suppressVisibleEffects = 1; }
\r
3087 /* [HGM] call with -2 uses old size (for if nr of files, ranks changes) */
\r
3088 if(boardSize == (BoardSize)(-2) ) boardSize = oldBoardSize;
\r
3090 tinyLayout = sizeInfo[boardSize].tinyLayout;
\r
3091 smallLayout = sizeInfo[boardSize].smallLayout;
\r
3092 squareSize = sizeInfo[boardSize].squareSize;
\r
3093 lineGap = sizeInfo[boardSize].lineGap;
\r
3094 minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted */
\r
3096 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3097 lineGap = appData.overrideLineGap;
\r
3100 if (tinyLayout != oldTinyLayout) {
\r
3101 long style = GetWindowLong(hwndMain, GWL_STYLE);
\r
3103 style &= ~WS_SYSMENU;
\r
3104 InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize,
\r
3105 "&Minimize\tCtrl+F4");
\r
3107 style |= WS_SYSMENU;
\r
3108 RemoveMenu(hmenu, IDM_Minimize, MF_BYCOMMAND);
\r
3110 SetWindowLong(hwndMain, GWL_STYLE, style);
\r
3112 for (i=0; menuBarText[tinyLayout][i]; i++) {
\r
3113 ModifyMenu(hmenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP,
\r
3114 (UINT)GetSubMenu(hmenu, i), menuBarText[tinyLayout][i]);
\r
3116 DrawMenuBar(hwndMain);
\r
3119 boardWidth = BoardWidth(boardSize, BOARD_WIDTH);
\r
3120 boardHeight = BoardWidth(boardSize, BOARD_HEIGHT);
\r
3122 /* Get text area sizes */
\r
3123 hdc = GetDC(hwndMain);
\r
3124 if (appData.clockMode) {
\r
3125 sprintf(buf, "White: %s", TimeString(23*60*60*1000L));
\r
3127 sprintf(buf, "White");
\r
3129 oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);
\r
3130 GetTextExtentPoint(hdc, buf, strlen(buf), &clockSize);
\r
3131 SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);
\r
3132 str = "We only care about the height here";
\r
3133 GetTextExtentPoint(hdc, str, strlen(str), &messageSize);
\r
3134 SelectObject(hdc, oldFont);
\r
3135 ReleaseDC(hwndMain, hdc);
\r
3137 /* Compute where everything goes */
\r
3138 if(first.programLogo || second.programLogo) {
\r
3139 /* [HGM] logo: if either logo is on, reserve space for it */
\r
3140 logoHeight = 2*clockSize.cy;
\r
3141 leftLogoRect.left = OUTER_MARGIN;
\r
3142 leftLogoRect.right = leftLogoRect.left + 4*clockSize.cy;
\r
3143 leftLogoRect.top = OUTER_MARGIN;
\r
3144 leftLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3146 rightLogoRect.right = OUTER_MARGIN + boardWidth;
\r
3147 rightLogoRect.left = rightLogoRect.right - 4*clockSize.cy;
\r
3148 rightLogoRect.top = OUTER_MARGIN;
\r
3149 rightLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3152 blackRect.left = leftLogoRect.right;
\r
3153 blackRect.right = rightLogoRect.left;
\r
3154 blackRect.top = OUTER_MARGIN;
\r
3155 blackRect.bottom = blackRect.top + clockSize.cy;
\r
3157 whiteRect.left = blackRect.left ;
\r
3158 whiteRect.right = blackRect.right;
\r
3159 whiteRect.top = blackRect.bottom;
\r
3160 whiteRect.bottom = leftLogoRect.bottom;
\r
3162 whiteRect.left = OUTER_MARGIN;
\r
3163 whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2;
\r
3164 whiteRect.top = OUTER_MARGIN + logoHeight;
\r
3165 whiteRect.bottom = whiteRect.top + clockSize.cy;
\r
3167 blackRect.left = whiteRect.right + INNER_MARGIN;
\r
3168 blackRect.right = blackRect.left + boardWidth/2 - 1;
\r
3169 blackRect.top = whiteRect.top;
\r
3170 blackRect.bottom = whiteRect.bottom;
\r
3173 messageRect.left = OUTER_MARGIN + MESSAGE_LINE_LEFTMARGIN;
\r
3174 if (appData.showButtonBar) {
\r
3175 messageRect.right = OUTER_MARGIN + boardWidth // [HGM] logo: expressed independent of clock placement
\r
3176 - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN;
\r
3178 messageRect.right = OUTER_MARGIN + boardWidth;
\r
3180 messageRect.top = whiteRect.bottom + INNER_MARGIN;
\r
3181 messageRect.bottom = messageRect.top + messageSize.cy;
\r
3183 boardRect.left = OUTER_MARGIN;
\r
3184 boardRect.right = boardRect.left + boardWidth;
\r
3185 boardRect.top = messageRect.bottom + INNER_MARGIN;
\r
3186 boardRect.bottom = boardRect.top + boardHeight;
\r
3188 sizeInfo[boardSize].cliWidth = boardRect.right + OUTER_MARGIN;
\r
3189 sizeInfo[boardSize].cliHeight = boardRect.bottom + OUTER_MARGIN;
\r
3190 if(suppressVisibleEffects) return; // [HGM] when called for filling sizeInfo only
\r
3191 winWidth = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN;
\r
3192 winHeight = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) +
\r
3193 GetSystemMetrics(SM_CYCAPTION) + boardRect.bottom + OUTER_MARGIN;
\r
3194 GetWindowRect(hwndMain, &wrect);
\r
3195 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3196 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3197 /* compensate if menu bar wrapped */
\r
3198 GetClientRect(hwndMain, &crect);
\r
3199 offby = boardRect.bottom + OUTER_MARGIN - crect.bottom;
\r
3200 winHeight += offby;
\r
3202 case WMSZ_TOPLEFT:
\r
3203 SetWindowPos(hwndMain, NULL,
\r
3204 wrect.right - winWidth, wrect.bottom - winHeight,
\r
3205 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3208 case WMSZ_TOPRIGHT:
\r
3210 SetWindowPos(hwndMain, NULL,
\r
3211 wrect.left, wrect.bottom - winHeight,
\r
3212 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3215 case WMSZ_BOTTOMLEFT:
\r
3217 SetWindowPos(hwndMain, NULL,
\r
3218 wrect.right - winWidth, wrect.top,
\r
3219 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3222 case WMSZ_BOTTOMRIGHT:
\r
3226 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3227 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3232 for (i = 0; i < N_BUTTONS; i++) {
\r
3233 if (buttonDesc[i].hwnd != NULL) {
\r
3234 DestroyWindow(buttonDesc[i].hwnd);
\r
3235 buttonDesc[i].hwnd = NULL;
\r
3237 if (appData.showButtonBar) {
\r
3238 buttonDesc[i].hwnd =
\r
3239 CreateWindow("BUTTON", buttonDesc[i].label,
\r
3240 WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
\r
3241 boardRect.right - BUTTON_WIDTH*(N_BUTTONS-i),
\r
3242 messageRect.top, BUTTON_WIDTH, messageSize.cy, hwndMain,
\r
3243 (HMENU) buttonDesc[i].id,
\r
3244 (HINSTANCE) GetWindowLong(hwndMain, GWL_HINSTANCE), NULL);
\r
3246 SendMessage(buttonDesc[i].hwnd, WM_SETFONT,
\r
3247 (WPARAM)font[boardSize][MESSAGE_FONT]->hf,
\r
3248 MAKELPARAM(FALSE, 0));
\r
3250 if (buttonDesc[i].id == IDM_Pause)
\r
3251 hwndPause = buttonDesc[i].hwnd;
\r
3252 buttonDesc[i].wndproc = (WNDPROC)
\r
3253 SetWindowLong(buttonDesc[i].hwnd, GWL_WNDPROC, (LONG) ButtonProc);
\r
3256 if (gridPen != NULL) DeleteObject(gridPen);
\r
3257 if (highlightPen != NULL) DeleteObject(highlightPen);
\r
3258 if (premovePen != NULL) DeleteObject(premovePen);
\r
3259 if (lineGap != 0) {
\r
3260 logbrush.lbStyle = BS_SOLID;
\r
3261 logbrush.lbColor = RGB(0, 0, 0); /* grid pen color = black */
\r
3263 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3264 lineGap, &logbrush, 0, NULL);
\r
3265 logbrush.lbColor = highlightSquareColor;
\r
3267 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3268 lineGap, &logbrush, 0, NULL);
\r
3270 logbrush.lbColor = premoveHighlightColor;
\r
3272 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3273 lineGap, &logbrush, 0, NULL);
\r
3275 /* [HGM] Loop had to be split in part for vert. and hor. lines */
\r
3276 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
\r
3277 gridEndpoints[i*2].x = boardRect.left + lineGap / 2;
\r
3278 gridEndpoints[i*2].y = gridEndpoints[i*2 + 1].y =
\r
3279 boardRect.top + lineGap / 2 + (i * (squareSize + lineGap));
\r
3280 gridEndpoints[i*2 + 1].x = boardRect.left + lineGap / 2 +
\r
3281 BOARD_WIDTH * (squareSize + lineGap);
\r
3282 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3284 for (i = 0; i < BOARD_WIDTH + 1; i++) {
\r
3285 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].y = boardRect.top + lineGap / 2;
\r
3286 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].x =
\r
3287 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].x = boardRect.left +
\r
3288 lineGap / 2 + (i * (squareSize + lineGap));
\r
3289 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].y =
\r
3290 boardRect.top + BOARD_HEIGHT * (squareSize + lineGap);
\r
3291 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3295 /* [HGM] Licensing requirement */
\r
3297 if(gameInfo.variant == VariantGothic) GothicPopUp( GOTHIC, VariantGothic); else
\r
3300 if(gameInfo.variant == VariantFalcon) GothicPopUp( FALCON, VariantFalcon); else
\r
3302 GothicPopUp( "", VariantNormal);
\r
3305 /* if (boardSize == oldBoardSize) return; [HGM] variant might have changed */
\r
3306 oldBoardSize = boardSize;
\r
3307 oldTinyLayout = tinyLayout;
\r
3309 /* Load piece bitmaps for this board size */
\r
3310 for (i=0; i<=2; i++) {
\r
3311 for (piece = WhitePawn;
\r
3312 (int) piece < (int) BlackPawn;
\r
3313 piece = (ChessSquare) ((int) piece + 1)) {
\r
3314 if (pieceBitmap[i][piece] != NULL)
\r
3315 DeleteObject(pieceBitmap[i][piece]);
\r
3319 fontBitmapSquareSize = 0; /* [HGM] render: make sure pieces will be recreated, as we might need others now */
\r
3320 // Orthodox Chess pieces
\r
3321 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s");
\r
3322 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s");
\r
3323 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "s");
\r
3324 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "s");
\r
3325 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "s");
\r
3326 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "o");
\r
3327 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "o");
\r
3328 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "o");
\r
3329 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "o");
\r
3330 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "o");
\r
3331 pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "w");
\r
3332 pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "w");
\r
3333 pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "w");
\r
3334 pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w");
\r
3335 pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w");
\r
3336 if( !strcmp(appData.variant, "shogi") && (squareSize==72 || squareSize==49)) {
\r
3337 // in Shogi, Hijack the unused Queen for Lance
\r
3338 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3339 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3340 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3342 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s");
\r
3343 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o");
\r
3344 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w");
\r
3347 if(squareSize <= 72 && squareSize >= 33) {
\r
3348 /* A & C are available in most sizes now */
\r
3349 if(squareSize != 49 && squareSize != 72 && squareSize != 33) { // Vortex-like
\r
3350 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3351 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3352 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3353 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3354 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3355 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3356 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3357 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3358 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3359 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3360 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3361 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3362 } else { // Smirf-like
\r
3363 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "s");
\r
3364 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "o");
\r
3365 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "w");
\r
3367 if(gameInfo.variant == VariantGothic) { // Vortex-like
\r
3368 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3369 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3370 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3371 } else { // WinBoard standard
\r
3372 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s");
\r
3373 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o");
\r
3374 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "w");
\r
3379 if(squareSize==72 || squareSize==49 || squareSize==33) { /* experiment with some home-made bitmaps */
\r
3380 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "s");
\r
3381 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "o");
\r
3382 pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "w");
\r
3383 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "s");
\r
3384 pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "o");
\r
3385 pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3386 pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "s");
\r
3387 pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "o");
\r
3388 pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "w");
\r
3389 pieceBitmap[0][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "s");
\r
3390 pieceBitmap[1][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "o");
\r
3391 pieceBitmap[2][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "w");
\r
3392 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3393 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3394 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3395 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "s");
\r
3396 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "o");
\r
3397 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "w");
\r
3398 pieceBitmap[0][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "s");
\r
3399 pieceBitmap[1][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "o");
\r
3400 pieceBitmap[2][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "w");
\r
3401 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "s");
\r
3402 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "o");
\r
3403 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "w");
\r
3404 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3405 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3406 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3407 pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s");
\r
3408 pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o");
\r
3409 pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w");
\r
3411 if(gameInfo.variant == VariantShogi) { /* promoted Gold represemtations */
\r
3412 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s");
\r
3413 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "o");
\r
3414 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3415 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "s");
\r
3416 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "o");
\r
3417 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3418 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "s");
\r
3419 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "o");
\r
3420 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3421 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "s");
\r
3422 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "o");
\r
3423 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3425 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "s");
\r
3426 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "o");
\r
3427 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "w");
\r
3428 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "s");
\r
3429 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "o");
\r
3430 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "w");
\r
3431 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3432 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3433 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3434 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "s");
\r
3435 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "o");
\r
3436 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "w");
\r
3439 } else { /* other size, no special bitmaps available. Use smaller symbols */
\r
3440 if((int)boardSize < 2) minorSize = sizeInfo[0].squareSize;
\r
3441 else minorSize = sizeInfo[(int)boardSize - 2].squareSize;
\r
3442 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "s");
\r
3443 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "o");
\r
3444 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "w");
\r
3445 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "s");
\r
3446 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "o");
\r
3447 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "w");
\r
3448 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "s");
\r
3449 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "o");
\r
3450 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "w");
\r
3451 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "s");
\r
3452 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "o");
\r
3453 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "w");
\r
3457 if(gameInfo.variant == VariantShogi && squareSize == 58)
\r
3458 /* special Shogi support in this size */
\r
3459 { for (i=0; i<=2; i++) { /* replace all bitmaps */
\r
3460 for (piece = WhitePawn;
\r
3461 (int) piece < (int) BlackPawn;
\r
3462 piece = (ChessSquare) ((int) piece + 1)) {
\r
3463 if (pieceBitmap[i][piece] != NULL)
\r
3464 DeleteObject(pieceBitmap[i][piece]);
\r
3467 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3468 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3469 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3470 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3471 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3472 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3473 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r
3474 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");
\r
3475 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");
\r
3476 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");
\r
3477 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");
\r
3478 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");
\r
3479 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");
\r
3480 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");
\r
3481 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3482 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3483 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3484 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3485 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3486 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3487 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r
3488 pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");
\r
3489 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");
\r
3490 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");
\r
3491 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");
\r
3492 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");
\r
3493 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");
\r
3494 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");
\r
3495 pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "w");
\r
3496 pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "w");
\r
3497 pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3498 pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3499 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "w");
\r
3500 pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "w");
\r
3501 pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3502 pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3503 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "sp", squareSize, "w");
\r
3504 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "sn", squareSize, "w");
\r
3505 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3506 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3507 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "sl", squareSize, "w");
\r
3508 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3514 PieceBitmap(ChessSquare p, int kind)
\r
3516 if ((int) p >= (int) BlackPawn)
\r
3517 p = (ChessSquare) ((int) p - (int) BlackPawn + (int) WhitePawn);
\r
3519 return pieceBitmap[kind][(int) p];
\r
3522 /***************************************************************/
\r
3524 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
\r
3525 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
\r
3527 #define MIN3(a,b,c) (((a) < (b) && (a) < (c)) ? (a) : (((b) < (a) && (b) < (c)) ? (b) : (c)))
\r
3528 #define MAX3(a,b,c) (((a) > (b) && (a) > (c)) ? (a) : (((b) > (a) && (b) > (c)) ? (b) : (c)))
\r
3532 SquareToPos(int row, int column, int * x, int * y)
\r
3535 *x = boardRect.left + lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
\r
3536 *y = boardRect.top + lineGap + row * (squareSize + lineGap);
\r
3538 *x = boardRect.left + lineGap + column * (squareSize + lineGap);
\r
3539 *y = boardRect.top + lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
\r
3544 DrawCoordsOnDC(HDC hdc)
\r
3546 static char files[24] = {'0', '1','2','3','4','5','6','7','8','9','0','1','1','0','9','8','7','6','5','4','3','2','1','0'};
\r
3547 static char ranks[24] = {'l', 'k','j','i','h','g','f','e','d','c','b','a','a','b','c','d','e','f','g','h','i','j','k','l'};
\r
3548 char str[2] = { NULLCHAR, NULLCHAR };
\r
3549 int oldMode, oldAlign, x, y, start, i;
\r
3553 if (!appData.showCoords)
\r
3556 start = flipView ? 1-(ONE!='1') : 23+(ONE!='1')-BOARD_HEIGHT;
\r
3558 oldBrush = SelectObject(hdc, GetStockObject(BLACK_BRUSH));
\r
3559 oldMode = SetBkMode(hdc, (appData.monoMode ? OPAQUE : TRANSPARENT));
\r
3560 oldAlign = GetTextAlign(hdc);
\r
3561 oldFont = SelectObject(hdc, font[boardSize][COORD_FONT]->hf);
\r
3563 y = boardRect.top + lineGap;
\r
3564 x = boardRect.left + lineGap + gameInfo.holdingsWidth*(squareSize + lineGap);
\r
3566 SetTextAlign(hdc, TA_LEFT|TA_TOP);
\r
3567 for (i = 0; i < BOARD_HEIGHT; i++) {
\r
3568 str[0] = files[start + i];
\r
3569 ExtTextOut(hdc, x + 2, y + 1, 0, NULL, str, 1, NULL);
\r
3570 y += squareSize + lineGap;
\r
3573 start = flipView ? 12-(BOARD_RGHT-BOARD_LEFT) : 12;
\r
3575 SetTextAlign(hdc, TA_RIGHT|TA_BOTTOM);
\r
3576 for (i = 0; i < BOARD_RGHT - BOARD_LEFT; i++) {
\r
3577 str[0] = ranks[start + i];
\r
3578 ExtTextOut(hdc, x + squareSize - 2, y - 1, 0, NULL, str, 1, NULL);
\r
3579 x += squareSize + lineGap;
\r
3582 SelectObject(hdc, oldBrush);
\r
3583 SetBkMode(hdc, oldMode);
\r
3584 SetTextAlign(hdc, oldAlign);
\r
3585 SelectObject(hdc, oldFont);
\r
3589 DrawGridOnDC(HDC hdc)
\r
3593 if (lineGap != 0) {
\r
3594 oldPen = SelectObject(hdc, gridPen);
\r
3595 PolyPolyline(hdc, gridEndpoints, gridVertexCounts, BOARD_WIDTH+BOARD_HEIGHT + 2);
\r
3596 SelectObject(hdc, oldPen);
\r
3600 #define HIGHLIGHT_PEN 0
\r
3601 #define PREMOVE_PEN 1
\r
3604 DrawHighlightOnDC(HDC hdc, BOOLEAN on, int x, int y, int pen)
\r
3607 HPEN oldPen, hPen;
\r
3608 if (lineGap == 0) return;
\r
3610 x1 = boardRect.left +
\r
3611 lineGap/2 + ((BOARD_WIDTH-1)-x) * (squareSize + lineGap);
\r
3612 y1 = boardRect.top +
\r
3613 lineGap/2 + y * (squareSize + lineGap);
\r
3615 x1 = boardRect.left +
\r
3616 lineGap/2 + x * (squareSize + lineGap);
\r
3617 y1 = boardRect.top +
\r
3618 lineGap/2 + ((BOARD_HEIGHT-1)-y) * (squareSize + lineGap);
\r
3620 hPen = pen ? premovePen : highlightPen;
\r
3621 oldPen = SelectObject(hdc, on ? hPen : gridPen);
\r
3622 MoveToEx(hdc, x1, y1, NULL);
\r
3623 LineTo(hdc, x1 + squareSize + lineGap, y1);
\r
3624 LineTo(hdc, x1 + squareSize + lineGap, y1 + squareSize + lineGap);
\r
3625 LineTo(hdc, x1, y1 + squareSize + lineGap);
\r
3626 LineTo(hdc, x1, y1);
\r
3627 SelectObject(hdc, oldPen);
\r
3631 DrawHighlightsOnDC(HDC hdc)
\r
3634 for (i=0; i<2; i++) {
\r
3635 if (highlightInfo.sq[i].x >= 0 && highlightInfo.sq[i].y >= 0)
\r
3636 DrawHighlightOnDC(hdc, TRUE,
\r
3637 highlightInfo.sq[i].x, highlightInfo.sq[i].y,
\r
3640 for (i=0; i<2; i++) {
\r
3641 if (premoveHighlightInfo.sq[i].x >= 0 &&
\r
3642 premoveHighlightInfo.sq[i].y >= 0) {
\r
3643 DrawHighlightOnDC(hdc, TRUE,
\r
3644 premoveHighlightInfo.sq[i].x,
\r
3645 premoveHighlightInfo.sq[i].y,
\r
3651 /* Note: sqcolor is used only in monoMode */
\r
3652 /* Note that this code is largely duplicated in woptions.c,
\r
3653 function DrawSampleSquare, so that needs to be updated too */
\r
3655 DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, HDC tmphdc)
\r