2 * WinBoard.c -- Windows NT front end to XBoard
\r
3 * $Id: winboard.c,v 2.3 2003/11/25 05:25:20 mann Exp $
\r
5 * Copyright 1991 by Digital Equipment Corporation, Maynard,
\r
6 * Massachusetts. Enhancements Copyright
\r
7 * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software
\r
10 * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,
\r
11 * which was written and is copyrighted by Wayne Christopher.
\r
13 * The following terms apply to Digital Equipment Corporation's copyright
\r
14 * interest in XBoard:
\r
15 * ------------------------------------------------------------------------
\r
16 * All Rights Reserved
\r
18 * Permission to use, copy, modify, and distribute this software and its
\r
19 * documentation for any purpose and without fee is hereby granted,
\r
20 * provided that the above copyright notice appear in all copies and that
\r
21 * both that copyright notice and this permission notice appear in
\r
22 * supporting documentation, and that the name of Digital not be
\r
23 * used in advertising or publicity pertaining to distribution of the
\r
24 * software without specific, written prior permission.
\r
26 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
\r
27 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
\r
28 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
\r
29 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
\r
30 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
\r
31 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
\r
33 * ------------------------------------------------------------------------
\r
35 * The following terms apply to the enhanced version of XBoard
\r
36 * distributed by the Free Software Foundation:
\r
37 * ------------------------------------------------------------------------
\r
39 * GNU XBoard is free software: you can redistribute it and/or modify
\r
40 * it under the terms of the GNU General Public License as published by
\r
41 * the Free Software Foundation, either version 3 of the License, or (at
\r
42 * your option) any later version.
\r
44 * GNU XBoard is distributed in the hope that it will be useful, but
\r
45 * WITHOUT ANY WARRANTY; without even the implied warranty of
\r
46 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
47 * General Public License for more details.
\r
49 * You should have received a copy of the GNU General Public License
\r
50 * along with this program. If not, see http://www.gnu.org/licenses/. *
\r
52 *------------------------------------------------------------------------
\r
53 ** See the file ChangeLog for a revision history. */
\r
57 #include <windows.h>
\r
58 #include <winuser.h>
\r
59 #include <winsock.h>
\r
60 #include <commctrl.h>
\r
66 #include <sys/stat.h>
\r
69 #include <commdlg.h>
\r
71 #include <richedit.h>
\r
72 #include <mmsystem.h>
\r
81 #include "winboard.h"
\r
82 #include "frontend.h"
\r
83 #include "backend.h"
\r
85 #include "wclipbrd.h"
\r
86 #include "wgamelist.h"
\r
87 #include "wedittags.h"
\r
88 #include "woptions.h"
\r
89 #include "wsockerr.h"
\r
90 #include "defaults.h"
\r
94 //void InitEngineUCI( const char * iniDir, ChessProgramState * cps );
\r
97 void mysrandom(unsigned int seed);
\r
99 extern int whiteFlag, blackFlag;
\r
100 Boolean flipClock = FALSE;
\r
102 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);
\r
103 VOID NewVariantPopup(HWND hwnd);
\r
104 int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,
\r
105 /*char*/int promoChar));
\r
108 ChessSquare piece;
\r
109 POINT pos; /* window coordinates of current pos */
\r
110 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
111 POINT from; /* board coordinates of the piece's orig pos */
\r
112 POINT to; /* board coordinates of the piece's new pos */
\r
115 static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };
\r
118 POINT start; /* window coordinates of start pos */
\r
119 POINT pos; /* window coordinates of current pos */
\r
120 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
121 POINT from; /* board coordinates of the piece's orig pos */
\r
124 static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} };
\r
127 POINT sq[2]; /* board coordinates of from, to squares */
\r
130 static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} };
\r
131 static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };
\r
133 /* Window class names */
\r
134 char szAppName[] = "WinBoard";
\r
135 char szConsoleName[] = "WBConsole";
\r
137 /* Title bar text */
\r
138 char szTitle[] = "WinBoard";
\r
139 char szConsoleTitle[] = "ICS Interaction";
\r
142 char *settingsFileName;
\r
143 BOOLEAN saveSettingsOnExit;
\r
144 char installDir[MSG_SIZ];
\r
146 BoardSize boardSize;
\r
147 BOOLEAN chessProgram;
\r
148 static int boardX, boardY, consoleX, consoleY, consoleW, consoleH;
\r
149 static int squareSize, lineGap, minorSize;
\r
150 static int winWidth, winHeight;
\r
151 static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo
\r
152 static int logoHeight = 0;
\r
153 static char messageText[MESSAGE_TEXT_MAX];
\r
154 static int clockTimerEvent = 0;
\r
155 static int loadGameTimerEvent = 0;
\r
156 static int analysisTimerEvent = 0;
\r
157 static DelayedEventCallback delayedTimerCallback;
\r
158 static int delayedTimerEvent = 0;
\r
159 static int buttonCount = 2;
\r
160 char *icsTextMenuString;
\r
162 char *firstChessProgramNames;
\r
163 char *secondChessProgramNames;
\r
165 #define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */
\r
167 #define PALETTESIZE 256
\r
169 HINSTANCE hInst; /* current instance */
\r
170 HWND hwndMain = NULL; /* root window*/
\r
171 HWND hwndConsole = NULL;
\r
172 BOOLEAN alwaysOnTop = FALSE;
\r
174 COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
\r
175 blackPieceColor, highlightSquareColor, premoveHighlightColor;
\r
177 ColorClass currentColorClass;
\r
179 HWND hCommPort = NULL; /* currently open comm port */
\r
180 static HWND hwndPause; /* pause button */
\r
181 static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */
\r
182 static HBRUSH lightSquareBrush, darkSquareBrush,
\r
183 blackSquareBrush, /* [HGM] for band between board and holdings */
\r
184 whitePieceBrush, blackPieceBrush, iconBkgndBrush /*, outlineBrush*/;
\r
185 static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];
\r
186 static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];
\r
187 static HPEN gridPen = NULL;
\r
188 static HPEN highlightPen = NULL;
\r
189 static HPEN premovePen = NULL;
\r
190 static NPLOGPALETTE pLogPal;
\r
191 static BOOL paletteChanged = FALSE;
\r
192 static HICON iconWhite, iconBlack, iconCurrent;
\r
193 static int doingSizing = FALSE;
\r
194 static int lastSizing = 0;
\r
195 static int prevStderrPort;
\r
197 /* [AS] Support for background textures */
\r
198 #define BACK_TEXTURE_MODE_DISABLED 0
\r
199 #define BACK_TEXTURE_MODE_PLAIN 1
\r
200 #define BACK_TEXTURE_MODE_FULL_RANDOM 2
\r
202 static HBITMAP liteBackTexture = NULL;
\r
203 static HBITMAP darkBackTexture = NULL;
\r
204 static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
205 static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
206 static int backTextureSquareSize = 0;
\r
207 static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_SIZE][BOARD_SIZE];
\r
209 #if __GNUC__ && !defined(_winmajor)
\r
210 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */
\r
212 #define oldDialog (_winmajor < 4)
\r
215 char *defaultTextAttribs[] =
\r
217 COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,
\r
218 COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,
\r
228 int cliWidth, cliHeight;
\r
231 SizeInfo sizeInfo[] =
\r
233 { "tiny", 21, 0, 1, 1, 0, 0 },
\r
234 { "teeny", 25, 1, 1, 1, 0, 0 },
\r
235 { "dinky", 29, 1, 1, 1, 0, 0 },
\r
236 { "petite", 33, 1, 1, 1, 0, 0 },
\r
237 { "slim", 37, 2, 1, 0, 0, 0 },
\r
238 { "small", 40, 2, 1, 0, 0, 0 },
\r
239 { "mediocre", 45, 2, 1, 0, 0, 0 },
\r
240 { "middling", 49, 2, 0, 0, 0, 0 },
\r
241 { "average", 54, 2, 0, 0, 0, 0 },
\r
242 { "moderate", 58, 3, 0, 0, 0, 0 },
\r
243 { "medium", 64, 3, 0, 0, 0, 0 },
\r
244 { "bulky", 72, 3, 0, 0, 0, 0 },
\r
245 { "large", 80, 3, 0, 0, 0, 0 },
\r
246 { "big", 87, 3, 0, 0, 0, 0 },
\r
247 { "huge", 95, 3, 0, 0, 0, 0 },
\r
248 { "giant", 108, 3, 0, 0, 0, 0 },
\r
249 { "colossal", 116, 4, 0, 0, 0, 0 },
\r
250 { "titanic", 129, 4, 0, 0, 0, 0 },
\r
251 { NULL, 0, 0, 0, 0, 0, 0 }
\r
254 #define MF(x) {x, {{0,}, 0. }, {0, }, 0}
\r
255 MyFont fontRec[NUM_SIZES][NUM_FONTS] =
\r
257 { MF(CLOCK_FONT_TINY), MF(MESSAGE_FONT_TINY), MF(COORD_FONT_TINY), MF(CONSOLE_FONT_TINY), MF(COMMENT_FONT_TINY), MF(EDITTAGS_FONT_TINY), MF(MOVEHISTORY_FONT_ALL) },
\r
258 { MF(CLOCK_FONT_TEENY), MF(MESSAGE_FONT_TEENY), MF(COORD_FONT_TEENY), MF(CONSOLE_FONT_TEENY), MF(COMMENT_FONT_TEENY), MF(EDITTAGS_FONT_TEENY), MF(MOVEHISTORY_FONT_ALL) },
\r
259 { MF(CLOCK_FONT_DINKY), MF(MESSAGE_FONT_DINKY), MF(COORD_FONT_DINKY), MF(CONSOLE_FONT_DINKY), MF(COMMENT_FONT_DINKY), MF(EDITTAGS_FONT_DINKY), MF(MOVEHISTORY_FONT_ALL) },
\r
260 { MF(CLOCK_FONT_PETITE), MF(MESSAGE_FONT_PETITE), MF(COORD_FONT_PETITE), MF(CONSOLE_FONT_PETITE), MF(COMMENT_FONT_PETITE), MF(EDITTAGS_FONT_PETITE), MF(MOVEHISTORY_FONT_ALL) },
\r
261 { MF(CLOCK_FONT_SLIM), MF(MESSAGE_FONT_SLIM), MF(COORD_FONT_SLIM), MF(CONSOLE_FONT_SLIM), MF(COMMENT_FONT_SLIM), MF(EDITTAGS_FONT_SLIM), MF(MOVEHISTORY_FONT_ALL) },
\r
262 { MF(CLOCK_FONT_SMALL), MF(MESSAGE_FONT_SMALL), MF(COORD_FONT_SMALL), MF(CONSOLE_FONT_SMALL), MF(COMMENT_FONT_SMALL), MF(EDITTAGS_FONT_SMALL), MF(MOVEHISTORY_FONT_ALL) },
\r
263 { MF(CLOCK_FONT_MEDIOCRE), MF(MESSAGE_FONT_MEDIOCRE), MF(COORD_FONT_MEDIOCRE), MF(CONSOLE_FONT_MEDIOCRE), MF(COMMENT_FONT_MEDIOCRE), MF(EDITTAGS_FONT_MEDIOCRE), MF(MOVEHISTORY_FONT_ALL) },
\r
264 { MF(CLOCK_FONT_MIDDLING), MF(MESSAGE_FONT_MIDDLING), MF(COORD_FONT_MIDDLING), MF(CONSOLE_FONT_MIDDLING), MF(COMMENT_FONT_MIDDLING), MF(EDITTAGS_FONT_MIDDLING), MF(MOVEHISTORY_FONT_ALL) },
\r
265 { MF(CLOCK_FONT_AVERAGE), MF(MESSAGE_FONT_AVERAGE), MF(COORD_FONT_AVERAGE), MF(CONSOLE_FONT_AVERAGE), MF(COMMENT_FONT_AVERAGE), MF(EDITTAGS_FONT_AVERAGE), MF(MOVEHISTORY_FONT_ALL) },
\r
266 { MF(CLOCK_FONT_MODERATE), MF(MESSAGE_FONT_MODERATE), MF(COORD_FONT_MODERATE), MF(CONSOLE_FONT_MODERATE), MF(COMMENT_FONT_MODERATE), MF(EDITTAGS_FONT_MODERATE), MF(MOVEHISTORY_FONT_ALL) },
\r
267 { MF(CLOCK_FONT_MEDIUM), MF(MESSAGE_FONT_MEDIUM), MF(COORD_FONT_MEDIUM), MF(CONSOLE_FONT_MEDIUM), MF(COMMENT_FONT_MEDIUM), MF(EDITTAGS_FONT_MEDIUM), MF(MOVEHISTORY_FONT_ALL) },
\r
268 { MF(CLOCK_FONT_BULKY), MF(MESSAGE_FONT_BULKY), MF(COORD_FONT_BULKY), MF(CONSOLE_FONT_BULKY), MF(COMMENT_FONT_BULKY), MF(EDITTAGS_FONT_BULKY), MF(MOVEHISTORY_FONT_ALL) },
\r
269 { MF(CLOCK_FONT_LARGE), MF(MESSAGE_FONT_LARGE), MF(COORD_FONT_LARGE), MF(CONSOLE_FONT_LARGE), MF(COMMENT_FONT_LARGE), MF(EDITTAGS_FONT_LARGE), MF(MOVEHISTORY_FONT_ALL) },
\r
270 { MF(CLOCK_FONT_BIG), MF(MESSAGE_FONT_BIG), MF(COORD_FONT_BIG), MF(CONSOLE_FONT_BIG), MF(COMMENT_FONT_BIG), MF(EDITTAGS_FONT_BIG), MF(MOVEHISTORY_FONT_ALL) },
\r
271 { MF(CLOCK_FONT_HUGE), MF(MESSAGE_FONT_HUGE), MF(COORD_FONT_HUGE), MF(CONSOLE_FONT_HUGE), MF(COMMENT_FONT_HUGE), MF(EDITTAGS_FONT_HUGE), MF(MOVEHISTORY_FONT_ALL) },
\r
272 { MF(CLOCK_FONT_GIANT), MF(MESSAGE_FONT_GIANT), MF(COORD_FONT_GIANT), MF(CONSOLE_FONT_GIANT), MF(COMMENT_FONT_GIANT), MF(EDITTAGS_FONT_GIANT), MF(MOVEHISTORY_FONT_ALL) },
\r
273 { MF(CLOCK_FONT_COLOSSAL), MF(MESSAGE_FONT_COLOSSAL), MF(COORD_FONT_COLOSSAL), MF(CONSOLE_FONT_COLOSSAL), MF(COMMENT_FONT_COLOSSAL), MF(EDITTAGS_FONT_COLOSSAL), MF(MOVEHISTORY_FONT_ALL) },
\r
274 { MF(CLOCK_FONT_TITANIC), MF(MESSAGE_FONT_TITANIC), MF(COORD_FONT_TITANIC), MF(CONSOLE_FONT_TITANIC), MF(COMMENT_FONT_TITANIC), MF(EDITTAGS_FONT_TITANIC), MF(MOVEHISTORY_FONT_ALL) },
\r
277 MyFont *font[NUM_SIZES][NUM_FONTS];
\r
286 #define BUTTON_WIDTH (tinyLayout ? 16 : 32)
\r
287 #define N_BUTTONS 5
\r
289 MyButtonDesc buttonDesc[N_BUTTONS] =
\r
291 {"<<", IDM_ToStart, NULL, NULL},
\r
292 {"<", IDM_Backward, NULL, NULL},
\r
293 {"P", IDM_Pause, NULL, NULL},
\r
294 {">", IDM_Forward, NULL, NULL},
\r
295 {">>", IDM_ToEnd, NULL, NULL},
\r
298 int tinyLayout = 0, smallLayout = 0;
\r
299 #define MENU_BAR_ITEMS 6
\r
300 char *menuBarText[2][MENU_BAR_ITEMS+1] = {
\r
301 { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },
\r
302 { "&F", "&M", "&A", "&S", "&O", "&H", NULL },
\r
306 MySound sounds[(int)NSoundClasses];
\r
307 MyTextAttribs textAttribs[(int)NColorClasses];
\r
309 MyColorizeAttribs colorizeAttribs[] = {
\r
310 { (COLORREF)0, 0, "Shout Text" },
\r
311 { (COLORREF)0, 0, "SShout/CShout" },
\r
312 { (COLORREF)0, 0, "Channel 1 Text" },
\r
313 { (COLORREF)0, 0, "Channel Text" },
\r
314 { (COLORREF)0, 0, "Kibitz Text" },
\r
315 { (COLORREF)0, 0, "Tell Text" },
\r
316 { (COLORREF)0, 0, "Challenge Text" },
\r
317 { (COLORREF)0, 0, "Request Text" },
\r
318 { (COLORREF)0, 0, "Seek Text" },
\r
319 { (COLORREF)0, 0, "Normal Text" },
\r
320 { (COLORREF)0, 0, "None" }
\r
325 static char *commentTitle;
\r
326 static char *commentText;
\r
327 static int commentIndex;
\r
328 static Boolean editComment = FALSE;
\r
329 HWND commentDialog = NULL;
\r
330 BOOLEAN commentDialogUp = FALSE;
\r
331 static int commentX, commentY, commentH, commentW;
\r
333 static char *analysisTitle;
\r
334 static char *analysisText;
\r
335 HWND analysisDialog = NULL;
\r
336 BOOLEAN analysisDialogUp = FALSE;
\r
337 static int analysisX, analysisY, analysisH, analysisW;
\r
339 char errorTitle[MSG_SIZ];
\r
340 char errorMessage[2*MSG_SIZ];
\r
341 HWND errorDialog = NULL;
\r
342 BOOLEAN moveErrorMessageUp = FALSE;
\r
343 BOOLEAN consoleEcho = TRUE;
\r
344 CHARFORMAT consoleCF;
\r
345 COLORREF consoleBackgroundColor;
\r
347 char *programVersion;
\r
353 typedef int CPKind;
\r
362 SOCKET sock2; /* stderr socket for OpenRcmd */
\r
365 #define INPUT_SOURCE_BUF_SIZE 4096
\r
367 typedef struct _InputSource {
\r
374 char buf[INPUT_SOURCE_BUF_SIZE];
\r
378 InputCallback func;
\r
379 struct _InputSource *second; /* for stderr thread on CPRcmd */
\r
383 InputSource *consoleInputSource;
\r
388 VOID ConsoleOutput(char* data, int length, int forceVisible);
\r
389 VOID ConsoleCreate();
\r
391 ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
392 VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
\r
393 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
\r
394 VOID ParseCommSettings(char *arg, DCB *dcb);
\r
396 StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
397 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
\r
398 void ParseIcsTextMenu(char *icsTextMenuString);
\r
399 VOID PopUpMoveDialog(char firstchar);
\r
400 VOID PopUpNameDialog(char firstchar);
\r
401 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
\r
405 int GameListOptions();
\r
407 HWND moveHistoryDialog = NULL;
\r
408 BOOLEAN moveHistoryDialogUp = FALSE;
\r
410 WindowPlacement wpMoveHistory;
\r
412 HWND evalGraphDialog = NULL;
\r
413 BOOLEAN evalGraphDialogUp = FALSE;
\r
415 WindowPlacement wpEvalGraph;
\r
417 HWND engineOutputDialog = NULL;
\r
418 BOOLEAN engineOutputDialogUp = FALSE;
\r
420 WindowPlacement wpEngineOutput;
\r
422 VOID MoveHistoryPopUp();
\r
423 VOID MoveHistoryPopDown();
\r
424 VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
425 BOOL MoveHistoryIsUp();
\r
427 VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
428 VOID EvalGraphPopUp();
\r
429 VOID EvalGraphPopDown();
\r
430 BOOL EvalGraphIsUp();
\r
432 VOID EngineOutputPopUp();
\r
433 VOID EngineOutputPopDown();
\r
434 BOOL EngineOutputIsUp();
\r
435 VOID EngineOutputUpdate( FrontEndProgramStats * stats );
\r
437 VOID GothicPopUp(char *title, VariantClass variant);
\r
439 * Setting "frozen" should disable all user input other than deleting
\r
440 * the window. We do this while engines are initializing themselves.
\r
442 static int frozen = 0;
\r
443 static int oldMenuItemState[MENU_BAR_ITEMS];
\r
449 if (frozen) return;
\r
451 hmenu = GetMenu(hwndMain);
\r
452 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
453 oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
\r
455 DrawMenuBar(hwndMain);
\r
458 /* Undo a FreezeUI */
\r
464 if (!frozen) return;
\r
466 hmenu = GetMenu(hwndMain);
\r
467 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
468 EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
\r
470 DrawMenuBar(hwndMain);
\r
473 /*---------------------------------------------------------------------------*\
\r
477 \*---------------------------------------------------------------------------*/
\r
480 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
\r
481 LPSTR lpCmdLine, int nCmdShow)
\r
484 HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
\r
485 // INITCOMMONCONTROLSEX ex;
\r
489 LoadLibrary("RICHED32.DLL");
\r
490 consoleCF.cbSize = sizeof(CHARFORMAT);
\r
492 if (!InitApplication(hInstance)) {
\r
495 if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
\r
498 // InitCommonControlsEx(&ex);
\r
499 InitCommonControls();
\r
501 hAccelMain = LoadAccelerators (hInstance, szAppName);
\r
502 hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
\r
503 hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
\r
505 /* Acquire and dispatch messages until a WM_QUIT message is received. */
\r
507 while (GetMessage(&msg, /* message structure */
\r
508 NULL, /* handle of window receiving the message */
\r
509 0, /* lowest message to examine */
\r
510 0)) /* highest message to examine */
\r
512 if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
\r
513 !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
\r
514 !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
\r
515 !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
\r
516 !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
\r
517 !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
\r
518 !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
\r
519 !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) &&
\r
520 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
\r
521 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
\r
522 TranslateMessage(&msg); /* Translates virtual key codes */
\r
523 DispatchMessage(&msg); /* Dispatches message to window */
\r
528 return (msg.wParam); /* Returns the value from PostQuitMessage */
\r
531 /*---------------------------------------------------------------------------*\
\r
533 * Initialization functions
\r
535 \*---------------------------------------------------------------------------*/
\r
538 InitApplication(HINSTANCE hInstance)
\r
542 /* Fill in window class structure with parameters that describe the */
\r
545 wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
\r
546 wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
\r
547 wc.cbClsExtra = 0; /* No per-class extra data. */
\r
548 wc.cbWndExtra = 0; /* No per-window extra data. */
\r
549 wc.hInstance = hInstance; /* Owner of this class */
\r
550 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
551 wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
\r
552 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
\r
553 wc.lpszMenuName = szAppName; /* Menu name from .RC */
\r
554 wc.lpszClassName = szAppName; /* Name to register as */
\r
556 /* Register the window class and return success/failure code. */
\r
557 if (!RegisterClass(&wc)) return FALSE;
\r
559 wc.style = CS_HREDRAW | CS_VREDRAW;
\r
560 wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
\r
562 wc.cbWndExtra = DLGWINDOWEXTRA;
\r
563 wc.hInstance = hInstance;
\r
564 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
565 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
\r
566 wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
\r
567 wc.lpszMenuName = NULL;
\r
568 wc.lpszClassName = szConsoleName;
\r
570 if (!RegisterClass(&wc)) return FALSE;
\r
575 /* Set by InitInstance, used by EnsureOnScreen */
\r
576 int screenHeight, screenWidth;
\r
579 EnsureOnScreen(int *x, int *y)
\r
581 // int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
\r
582 /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
\r
583 if (*x > screenWidth - 32) *x = 0;
\r
584 if (*y > screenHeight - 32) *y = 0;
\r
585 if (*x < 0) *x = 0;
\r
586 if (*y < 0) *y = 0;
\r
587 // if (*x < 10) *x = 10;
\r
588 // if (*y < gap) *y = gap;
\r
592 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
\r
594 HWND hwnd; /* Main window handle. */
\r
596 WINDOWPLACEMENT wp;
\r
599 hInst = hInstance; /* Store instance handle in our global variable */
\r
601 if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
\r
602 *filepart = NULLCHAR;
\r
604 GetCurrentDirectory(MSG_SIZ, installDir);
\r
606 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise
\r
607 InitAppData(lpCmdLine); /* Get run-time parameters */
\r
608 if (appData.debugMode) {
\r
609 debugFP = fopen(appData.nameOfDebugFile, "w");
\r
610 setbuf(debugFP, NULL);
\r
615 // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()
\r
616 // InitEngineUCI( installDir, &second );
\r
618 /* Create a main window for this application instance. */
\r
619 hwnd = CreateWindow(szAppName, szTitle,
\r
620 (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
\r
621 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
\r
622 NULL, NULL, hInstance, NULL);
\r
625 /* If window could not be created, return "failure" */
\r
630 /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */
\r
631 if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {
\r
632 first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
634 if (first.programLogo == NULL && appData.debugMode) {
\r
635 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );
\r
637 } else if(appData.autoLogo) {
\r
638 if(appData.firstDirectory && appData.firstDirectory[0]) {
\r
640 sprintf(buf, "%s/logo.bmp", appData.firstDirectory);
\r
641 first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
645 if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {
\r
646 second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
648 if (second.programLogo == NULL && appData.debugMode) {
\r
649 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );
\r
651 } else if(appData.autoLogo) {
\r
652 if(appData.secondDirectory && appData.secondDirectory[0]) {
\r
654 sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);
\r
655 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
659 iconWhite = LoadIcon(hInstance, "icon_white");
\r
660 iconBlack = LoadIcon(hInstance, "icon_black");
\r
661 iconCurrent = iconWhite;
\r
662 InitDrawingColors();
\r
663 screenHeight = GetSystemMetrics(SM_CYSCREEN);
\r
664 screenWidth = GetSystemMetrics(SM_CXSCREEN);
\r
665 for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
\r
666 /* Compute window size for each board size, and use the largest
\r
667 size that fits on this screen as the default. */
\r
668 InitDrawingSizes((BoardSize)ibs, 0);
\r
669 if (boardSize == (BoardSize)-1 &&
\r
670 winHeight <= screenHeight
\r
671 - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10
\r
672 && winWidth <= screenWidth) {
\r
673 boardSize = (BoardSize)ibs;
\r
677 InitDrawingSizes(boardSize, 0);
\r
679 buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
\r
681 /* [AS] Load textures if specified */
\r
682 ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );
\r
684 if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {
\r
685 liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
686 liteBackTextureMode = appData.liteBackTextureMode;
\r
688 if (liteBackTexture == NULL && appData.debugMode) {
\r
689 fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );
\r
693 if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {
\r
694 darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
695 darkBackTextureMode = appData.darkBackTextureMode;
\r
697 if (darkBackTexture == NULL && appData.debugMode) {
\r
698 fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );
\r
702 mysrandom( (unsigned) time(NULL) );
\r
704 /* [AS] Restore layout */
\r
705 if( wpMoveHistory.visible ) {
\r
706 MoveHistoryPopUp();
\r
709 if( wpEvalGraph.visible ) {
\r
713 if( wpEngineOutput.visible ) {
\r
714 EngineOutputPopUp();
\r
719 /* Make the window visible; update its client area; and return "success" */
\r
720 EnsureOnScreen(&boardX, &boardY);
\r
721 wp.length = sizeof(WINDOWPLACEMENT);
\r
723 wp.showCmd = nCmdShow;
\r
724 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
\r
725 wp.rcNormalPosition.left = boardX;
\r
726 wp.rcNormalPosition.right = boardX + winWidth;
\r
727 wp.rcNormalPosition.top = boardY;
\r
728 wp.rcNormalPosition.bottom = boardY + winHeight;
\r
729 SetWindowPlacement(hwndMain, &wp);
\r
731 SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
732 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
735 /* [AS] Disable the FRC stuff if not playing the proper variant */
\r
736 if( gameInfo.variant != VariantFischeRandom ) {
\r
737 EnableMenuItem( GetMenu(hwndMain), IDM_NewGameFRC, MF_GRAYED );
\r
742 SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
743 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
745 ShowWindow(hwndConsole, nCmdShow);
\r
747 UpdateWindow(hwnd);
\r
755 ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
\r
756 ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
\r
757 ArgSettingsFilename
\r
765 String *pString; // ArgString
\r
766 int *pInt; // ArgInt
\r
767 float *pFloat; // ArgFloat
\r
768 Boolean *pBoolean; // ArgBoolean
\r
769 COLORREF *pColor; // ArgColor
\r
770 ColorClass cc; // ArgAttribs
\r
771 String *pFilename; // ArgFilename
\r
772 BoardSize *pBoardSize; // ArgBoardSize
\r
773 int whichFont; // ArgFont
\r
774 DCB *pDCB; // ArgCommSettings
\r
775 String *pFilename; // ArgSettingsFilename
\r
783 ArgDescriptor argDescriptors[] = {
\r
784 /* positional arguments */
\r
785 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
786 { "", ArgNone, NULL },
\r
787 /* keyword arguments */
\r
788 { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },
\r
789 { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },
\r
790 { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },
\r
791 { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },
\r
792 { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },
\r
793 { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },
\r
794 { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },
\r
795 { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },
\r
796 { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },
\r
797 { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },
\r
798 { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },
\r
799 { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },
\r
800 { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },
\r
801 { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },
\r
802 { "initString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
803 { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
804 { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },
\r
805 { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,
\r
807 { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,
\r
809 { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,
\r
811 { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },
\r
812 { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,
\r
814 { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },
\r
815 { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
816 { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
817 { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
818 { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
819 { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },
\r
820 { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },
\r
821 { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
822 { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
823 { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
824 { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
825 { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
826 { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
827 { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
828 { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
829 { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
830 { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
831 /*!!bitmapDirectory?*/
\r
832 { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
833 { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
834 { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
835 { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
836 { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },
\r
837 { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },
\r
838 { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },
\r
839 { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },
\r
840 { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },
\r
841 { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },
\r
842 { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },
\r
843 { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },
\r
844 { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
845 { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
846 { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
847 { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
848 { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
849 { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
850 { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
851 { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
852 { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
853 { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
854 { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
855 { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
856 { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },
\r
857 { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },
\r
858 { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
859 { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
860 { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },
\r
861 { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },
\r
862 { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },
\r
863 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
864 { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
865 { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
866 { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
867 { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },
\r
868 { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },
\r
869 { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },
\r
870 { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },
\r
871 { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
872 { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
873 { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
874 { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
875 { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
876 { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
877 { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
878 { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
879 { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },
\r
880 { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },
\r
881 { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
882 { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
883 { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
884 { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
885 { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },
\r
886 { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },
\r
887 { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
888 { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
889 { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },
\r
890 { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },
\r
891 { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
892 { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
893 { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },
\r
894 { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },
\r
895 { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
896 { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
897 { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
898 { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
899 { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
900 { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
901 { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },
\r
902 { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },
\r
903 { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
904 { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
905 { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },
\r
906 { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },
\r
907 { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
908 { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
909 { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },
\r
910 { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },
\r
911 { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
912 { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
913 { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },
\r
914 { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },
\r
915 { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
916 { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
917 { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },
\r
918 { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },
\r
919 { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
920 { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
921 { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },
\r
922 { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
923 { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
924 { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
925 { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors,
\r
926 FALSE }, /* only so that old WinBoard.ini files from betas can be read */
\r
927 { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },
\r
928 { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },
\r
929 { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },
\r
930 { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },
\r
931 { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },
\r
932 { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },
\r
933 { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE }, /* [AS] */
\r
934 { "boardSize", ArgBoardSize, (LPVOID) &boardSize,
\r
935 TRUE }, /* must come after all fonts */
\r
936 { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },
\r
937 { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,
\r
938 FALSE }, /* historical; kept only so old winboard.ini files will parse */
\r
939 { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },
\r
940 { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },
\r
941 { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
942 { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
943 { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },
\r
944 { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },
\r
945 { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
946 { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
947 { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },
\r
948 { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },
\r
949 { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
950 { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
951 { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },
\r
952 { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },
\r
953 { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
954 { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
955 { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },
\r
956 { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },
\r
957 { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
958 { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
959 { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },
\r
960 { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },
\r
961 { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
962 { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
963 { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },
\r
964 { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
965 { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
966 { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
968 { "cmailGameName", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
969 { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
971 { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },
\r
972 { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
973 { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
974 { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
975 { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },
\r
976 { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
977 { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
978 { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
979 { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },
\r
980 { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },
\r
981 { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
982 { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
983 { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },
\r
984 { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },
\r
985 { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
986 { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
987 { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },
\r
988 { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },
\r
989 { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
990 { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
991 { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },
\r
992 { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },
\r
993 { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
994 { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
995 { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },
\r
996 { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },
\r
997 { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
998 { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
999 { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },
\r
1000 { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },
\r
1001 { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },
\r
1002 { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1003 { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1004 { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },
\r
1005 { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},
\r
1006 { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},
\r
1007 { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1008 { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1009 { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},
\r
1010 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1011 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1012 { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },
\r
1013 { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1014 { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1015 { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },
\r
1016 { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },
\r
1017 { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1018 { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1019 { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },
\r
1020 { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },
\r
1021 { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },
\r
1022 { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1023 { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1024 { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },
\r
1025 { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },
\r
1026 { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1027 { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1028 { "highlightLastMove", ArgBoolean,
\r
1029 (LPVOID) &appData.highlightLastMove, TRUE },
\r
1030 { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1031 { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1032 { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1033 { "highlightDragging", ArgBoolean,
\r
1034 (LPVOID) &appData.highlightDragging, TRUE },
\r
1035 { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },
\r
1036 { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1037 { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1038 { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },
\r
1039 { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },
\r
1040 { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1041 { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1042 { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },
\r
1043 { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },
\r
1044 { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },
\r
1045 { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },
\r
1046 { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },
\r
1047 { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },
\r
1048 { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },
\r
1049 { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },
\r
1050 { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },
\r
1051 { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },
\r
1052 { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },
\r
1053 { "soundShout", ArgFilename,
\r
1054 (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },
\r
1055 { "soundSShout", ArgFilename,
\r
1056 (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },
\r
1057 { "soundChannel1", ArgFilename,
\r
1058 (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },
\r
1059 { "soundChannel", ArgFilename,
\r
1060 (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },
\r
1061 { "soundKibitz", ArgFilename,
\r
1062 (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },
\r
1063 { "soundTell", ArgFilename,
\r
1064 (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },
\r
1065 { "soundChallenge", ArgFilename,
\r
1066 (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },
\r
1067 { "soundRequest", ArgFilename,
\r
1068 (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },
\r
1069 { "soundSeek", ArgFilename,
\r
1070 (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },
\r
1071 { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },
\r
1072 { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },
\r
1073 { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },
\r
1074 { "soundIcsLoss", ArgFilename,
\r
1075 (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },
\r
1076 { "soundIcsDraw", ArgFilename,
\r
1077 (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },
\r
1078 { "soundIcsUnfinished", ArgFilename,
\r
1079 (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},
\r
1080 { "soundIcsAlarm", ArgFilename,
\r
1081 (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },
\r
1082 { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },
\r
1083 { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },
\r
1084 { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1085 { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1086 { "reuseChessPrograms", ArgBoolean,
\r
1087 (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */
\r
1088 { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },
\r
1089 { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },
\r
1090 { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1091 { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1092 { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },
\r
1093 { "x", ArgInt, (LPVOID) &boardX, TRUE },
\r
1094 { "y", ArgInt, (LPVOID) &boardY, TRUE },
\r
1095 { "icsX", ArgInt, (LPVOID) &consoleX, TRUE },
\r
1096 { "icsY", ArgInt, (LPVOID) &consoleY, TRUE },
\r
1097 { "icsW", ArgInt, (LPVOID) &consoleW, TRUE },
\r
1098 { "icsH", ArgInt, (LPVOID) &consoleH, TRUE },
\r
1099 { "analysisX", ArgInt, (LPVOID) &analysisX, TRUE },
\r
1100 { "analysisY", ArgInt, (LPVOID) &analysisY, TRUE },
\r
1101 { "analysisW", ArgInt, (LPVOID) &analysisW, TRUE },
\r
1102 { "analysisH", ArgInt, (LPVOID) &analysisH, TRUE },
\r
1103 { "commentX", ArgInt, (LPVOID) &commentX, TRUE },
\r
1104 { "commentY", ArgInt, (LPVOID) &commentY, TRUE },
\r
1105 { "commentW", ArgInt, (LPVOID) &commentW, TRUE },
\r
1106 { "commentH", ArgInt, (LPVOID) &commentH, TRUE },
\r
1107 { "tagsX", ArgInt, (LPVOID) &editTagsX, TRUE },
\r
1108 { "tagsY", ArgInt, (LPVOID) &editTagsY, TRUE },
\r
1109 { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },
\r
1110 { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },
\r
1111 { "gameListX", ArgInt, (LPVOID) &gameListX, TRUE },
\r
1112 { "gameListY", ArgInt, (LPVOID) &gameListY, TRUE },
\r
1113 { "gameListW", ArgInt, (LPVOID) &gameListW, TRUE },
\r
1114 { "gameListH", ArgInt, (LPVOID) &gameListH, TRUE },
\r
1115 { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1116 { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1117 { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },
\r
1118 { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },
\r
1119 { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },
\r
1120 { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1121 { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1122 { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },
\r
1123 { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },
\r
1124 { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,
\r
1126 { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,
\r
1128 { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1129 { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1130 { "variant", ArgString, (LPVOID) &appData.variant, FALSE },
\r
1131 { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion, FALSE },
\r
1132 { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,FALSE },
\r
1133 { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },
\r
1134 { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },
\r
1135 { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1136 { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1137 /* [AS] New features */
\r
1138 { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE },
\r
1139 { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE },
\r
1140 { "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE },
\r
1141 { "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE },
\r
1142 { "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE },
\r
1143 { "darkBackTextureFile", ArgString, (LPVOID) &appData.darkBackTextureFile, TRUE },
\r
1144 { "liteBackTextureMode", ArgInt, (LPVOID) &appData.liteBackTextureMode, TRUE },
\r
1145 { "darkBackTextureMode", ArgInt, (LPVOID) &appData.darkBackTextureMode, TRUE },
\r
1146 { "renderPiecesWithFont", ArgString, (LPVOID) &appData.renderPiecesWithFont, TRUE },
\r
1147 { "fontPieceToCharTable", ArgString, (LPVOID) &appData.fontToPieceTable, TRUE },
\r
1148 { "fontPieceBackColorWhite", ArgColor, (LPVOID) &appData.fontBackColorWhite, TRUE },
\r
1149 { "fontPieceForeColorWhite", ArgColor, (LPVOID) &appData.fontForeColorWhite, TRUE },
\r
1150 { "fontPieceBackColorBlack", ArgColor, (LPVOID) &appData.fontBackColorBlack, TRUE },
\r
1151 { "fontPieceForeColorBlack", ArgColor, (LPVOID) &appData.fontForeColorBlack, TRUE },
\r
1152 { "fontPieceSize", ArgInt, (LPVOID) &appData.fontPieceSize, TRUE },
\r
1153 { "overrideLineGap", ArgInt, (LPVOID) &appData.overrideLineGap, TRUE },
\r
1154 { "adjudicateLossThreshold", ArgInt, (LPVOID) &appData.adjudicateLossThreshold, TRUE },
\r
1155 { "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE },
\r
1156 { "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE },
\r
1157 { "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1158 { "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1159 { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },
\r
1160 { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE },
\r
1161 { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE },
\r
1162 { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE },
\r
1163 { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE },
\r
1164 { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE },
\r
1165 { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE },
\r
1166 { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE },
\r
1167 { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE },
\r
1168 { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE },
\r
1169 { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE },
\r
1170 { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE },
\r
1171 { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE },
\r
1172 { "firstIsUCI", ArgBoolean, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1173 { "fUCI", ArgTrue, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1174 { "secondIsUCI", ArgBoolean, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1175 { "sUCI", ArgTrue, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1176 { "firstHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1177 { "fNoOwnBookUCI", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1178 { "firstXBook", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1179 { "secondHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1180 { "sNoOwnBookUCI", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1181 { "secondXBook", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1182 { "polyglotDir", ArgFilename, (LPVOID) &appData.polyglotDir, TRUE },
\r
1183 { "usePolyglotBook", ArgBoolean, (LPVOID) &appData.usePolyglotBook, TRUE },
\r
1184 { "polyglotBook", ArgFilename, (LPVOID) &appData.polyglotBook, TRUE },
\r
1185 { "defaultHashSize", ArgInt, (LPVOID) &appData.defaultHashSize, TRUE },
\r
1186 { "defaultCacheSizeEGTB", ArgInt, (LPVOID) &appData.defaultCacheSizeEGTB, TRUE },
\r
1187 { "defaultPathEGTB", ArgFilename, (LPVOID) &appData.defaultPathEGTB, TRUE },
\r
1189 /* [AS] Layout stuff */
\r
1190 { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },
\r
1191 { "moveHistoryX", ArgInt, (LPVOID) &wpMoveHistory.x, TRUE },
\r
1192 { "moveHistoryY", ArgInt, (LPVOID) &wpMoveHistory.y, TRUE },
\r
1193 { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },
\r
1194 { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },
\r
1196 { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },
\r
1197 { "evalGraphX", ArgInt, (LPVOID) &wpEvalGraph.x, TRUE },
\r
1198 { "evalGraphY", ArgInt, (LPVOID) &wpEvalGraph.y, TRUE },
\r
1199 { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },
\r
1200 { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },
\r
1202 { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },
\r
1203 { "engineOutputX", ArgInt, (LPVOID) &wpEngineOutput.x, TRUE },
\r
1204 { "engineOutputY", ArgInt, (LPVOID) &wpEngineOutput.y, TRUE },
\r
1205 { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },
\r
1206 { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },
\r
1208 /* [HGM] board-size, adjudication and misc. options */
\r
1209 { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE },
\r
1210 { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE },
\r
1211 { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE },
\r
1212 { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE },
\r
1213 { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE },
\r
1214 { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE },
\r
1215 { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE },
\r
1216 { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE },
\r
1217 { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE },
\r
1218 { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE },
\r
1219 { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE },
\r
1220 { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE },
\r
1221 { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE },
\r
1222 { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE },
\r
1223 { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE },
\r
1224 { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE },
\r
1225 { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE },
\r
1226 { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE },
\r
1227 { "userName", ArgString, (LPVOID) &appData.userName, FALSE },
\r
1228 { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE },
\r
1229 { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE },
\r
1230 { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE },
\r
1231 { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE },
\r
1232 { "niceEngines", ArgInt, (LPVOID) &appData.niceEngines, TRUE },
\r
1233 { "firstLogo", ArgFilename, (LPVOID) &appData.firstLogo, FALSE },
\r
1234 { "secondLogo", ArgFilename, (LPVOID) &appData.secondLogo, FALSE },
\r
1235 { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE },
\r
1236 { "firstOptions", ArgString, (LPVOID) &appData.firstOptions, FALSE },
\r
1237 { "secondOptions", ArgString, (LPVOID) &appData.secondOptions, FALSE },
\r
1240 { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },
\r
1241 { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },
\r
1242 { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1243 { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1244 { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },
\r
1245 { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },
\r
1246 { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1247 { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1248 { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },
\r
1249 { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },
\r
1250 { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },
\r
1251 { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE },
\r
1252 { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,
\r
1254 { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE },
\r
1255 { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE },
\r
1256 { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE },
\r
1257 { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1258 { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1259 { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE },
\r
1260 { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,
\r
1262 { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1263 { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1264 { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1265 { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE },
\r
1266 { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE },
\r
1267 { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1268 { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1269 { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1270 { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1271 { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE },
\r
1272 { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE },
\r
1273 { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1274 { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1275 { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },
\r
1276 { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },
\r
1277 { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },
\r
1278 /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */
\r
1279 { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },
\r
1281 /* [HGM] options for broadcasting and time odds */
\r
1282 { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },
\r
1283 { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },
\r
1284 { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },
\r
1285 { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },
\r
1286 { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },
\r
1287 { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },
\r
1288 { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },
\r
1289 { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },
\r
1290 { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },
\r
1291 { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },
\r
1292 { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE },
\r
1293 { NULL, ArgNone, NULL, FALSE }
\r
1297 /* Kludge for indirection files on command line */
\r
1298 char* lastIndirectionFilename;
\r
1299 ArgDescriptor argDescriptorIndirection =
\r
1300 { "", ArgSettingsFilename, (LPVOID) NULL, FALSE };
\r
1304 ExitArgError(char *msg, char *badArg)
\r
1306 char buf[MSG_SIZ];
\r
1308 sprintf(buf, "%s %s", msg, badArg);
\r
1309 DisplayFatalError(buf, 0, 2);
\r
1313 /* Command line font name parser. NULL name means do nothing.
\r
1314 Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"
\r
1315 For backward compatibility, syntax without the colon is also
\r
1316 accepted, but font names with digits in them won't work in that case.
\r
1319 ParseFontName(char *name, MyFontParams *mfp)
\r
1322 if (name == NULL) return;
\r
1324 q = strchr(p, ':');
\r
1326 if (q - p >= sizeof(mfp->faceName))
\r
1327 ExitArgError("Font name too long:", name);
\r
1328 memcpy(mfp->faceName, p, q - p);
\r
1329 mfp->faceName[q - p] = NULLCHAR;
\r
1332 q = mfp->faceName;
\r
1333 while (*p && !isdigit(*p)) {
\r
1335 if (q - mfp->faceName >= sizeof(mfp->faceName))
\r
1336 ExitArgError("Font name too long:", name);
\r
1338 while (q > mfp->faceName && q[-1] == ' ') q--;
\r
1341 if (!*p) ExitArgError("Font point size missing:", name);
\r
1342 mfp->pointSize = (float) atof(p);
\r
1343 mfp->bold = (strchr(p, 'b') != NULL);
\r
1344 mfp->italic = (strchr(p, 'i') != NULL);
\r
1345 mfp->underline = (strchr(p, 'u') != NULL);
\r
1346 mfp->strikeout = (strchr(p, 's') != NULL);
\r
1349 /* Color name parser.
\r
1350 X version accepts X color names, but this one
\r
1351 handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */
\r
1353 ParseColorName(char *name)
\r
1355 int red, green, blue, count;
\r
1356 char buf[MSG_SIZ];
\r
1358 count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);
\r
1360 count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d",
\r
1361 &red, &green, &blue);
\r
1364 sprintf(buf, "Can't parse color name %s", name);
\r
1365 DisplayError(buf, 0);
\r
1366 return RGB(0, 0, 0);
\r
1368 return PALETTERGB(red, green, blue);
\r
1372 void ParseAttribs(COLORREF *color, int *effects, char* argValue)
\r
1374 char *e = argValue;
\r
1378 if (*e == 'b') eff |= CFE_BOLD;
\r
1379 else if (*e == 'i') eff |= CFE_ITALIC;
\r
1380 else if (*e == 'u') eff |= CFE_UNDERLINE;
\r
1381 else if (*e == 's') eff |= CFE_STRIKEOUT;
\r
1382 else if (*e == '#' || isdigit(*e)) break;
\r
1386 *color = ParseColorName(e);
\r
1391 ParseBoardSize(char *name)
\r
1393 BoardSize bs = SizeTiny;
\r
1394 while (sizeInfo[bs].name != NULL) {
\r
1395 if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;
\r
1398 ExitArgError("Unrecognized board size value", name);
\r
1399 return bs; /* not reached */
\r
1404 StringGet(void *getClosure)
\r
1406 char **p = (char **) getClosure;
\r
1411 FileGet(void *getClosure)
\r
1414 FILE* f = (FILE*) getClosure;
\r
1417 if (c == '\r') c = getc(f); // work around DOS format files by bypassing the '\r' completely
\r
1424 /* Parse settings file named "name". If file found, return the
\r
1425 full name in fullname and return TRUE; else return FALSE */
\r
1427 ParseSettingsFile(char *name, char fullname[MSG_SIZ])
\r
1432 if (SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy)) {
\r
1433 f = fopen(fullname, "r");
\r
1435 ParseArgs(FileGet, f);
\r
1444 ParseArgs(GetFunc get, void *cl)
\r
1446 char argName[ARG_MAX];
\r
1447 char argValue[ARG_MAX];
\r
1448 ArgDescriptor *ad;
\r
1457 while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);
\r
1458 if (ch == NULLCHAR) break;
\r
1460 /* Comment to end of line */
\r
1462 while (ch != '\n' && ch != NULLCHAR) ch = get(cl);
\r
1464 } else if (ch == '/' || ch == '-') {
\r
1467 while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&
\r
1468 ch != '\n' && ch != '\t') {
\r
1474 for (ad = argDescriptors; ad->argName != NULL; ad++)
\r
1475 if (strcmp(ad->argName, argName + 1) == 0) break;
\r
1477 if (ad->argName == NULL)
\r
1478 ExitArgError("Unrecognized argument", argName);
\r
1480 } else if (ch == '@') {
\r
1481 /* Indirection file */
\r
1482 ad = &argDescriptorIndirection;
\r
1485 /* Positional argument */
\r
1486 ad = &argDescriptors[posarg++];
\r
1487 strcpy(argName, ad->argName);
\r
1490 if (ad->argType == ArgTrue) {
\r
1491 *(Boolean *) ad->argLoc = TRUE;
\r
1494 if (ad->argType == ArgFalse) {
\r
1495 *(Boolean *) ad->argLoc = FALSE;
\r
1499 while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
\r
1500 if (ch == NULLCHAR || ch == '\n') {
\r
1501 ExitArgError("No value provided for argument", argName);
\r
1505 // Quoting with { }. No characters have to (or can) be escaped.
\r
1506 // Thus the string cannot contain a '}' character.
\r
1526 } else if (ch == '\'' || ch == '"') {
\r
1527 // Quoting with ' ' or " ", with \ as escape character.
\r
1528 // Inconvenient for long strings that may contain Windows filenames.
\r
1545 if (ch == start) {
\r
1554 if (ad->argType == ArgFilename
\r
1555 || ad->argType == ArgSettingsFilename) {
\r
1561 ExitArgError("Incomplete \\ escape in value for", argName);
\r
1585 for (i = 0; i < 3; i++) {
\r
1586 if (ch >= '0' && ch <= '7') {
\r
1587 octval = octval*8 + (ch - '0');
\r
1594 *q++ = (char) octval;
\r
1605 while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {
\r
1612 switch (ad->argType) {
\r
1614 *(int *) ad->argLoc = atoi(argValue);
\r
1618 *(float *) ad->argLoc = (float) atof(argValue);
\r
1623 *(char **) ad->argLoc = strdup(argValue);
\r
1626 case ArgSettingsFilename:
\r
1628 char fullname[MSG_SIZ];
\r
1629 if (ParseSettingsFile(argValue, fullname)) {
\r
1630 if (ad->argLoc != NULL) {
\r
1631 *(char **) ad->argLoc = strdup(fullname);
\r
1634 if (ad->argLoc != NULL) {
\r
1636 ExitArgError("Failed to open indirection file", argValue);
\r
1643 switch (argValue[0]) {
\r
1646 *(Boolean *) ad->argLoc = TRUE;
\r
1650 *(Boolean *) ad->argLoc = FALSE;
\r
1653 ExitArgError("Unrecognized boolean argument value", argValue);
\r
1659 *(COLORREF *)ad->argLoc = ParseColorName(argValue);
\r
1662 case ArgAttribs: {
\r
1663 ColorClass cc = (ColorClass)ad->argLoc;
\r
1664 ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);
\r
1668 case ArgBoardSize:
\r
1669 *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);
\r
1673 ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);
\r
1676 case ArgCommSettings:
\r
1677 ParseCommSettings(argValue, &dcb);
\r
1681 ExitArgError("Unrecognized argument", argValue);
\r
1690 LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
\r
1692 HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
\r
1693 lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);
\r
1696 lf->lfEscapement = 0;
\r
1697 lf->lfOrientation = 0;
\r
1698 lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;
\r
1699 lf->lfItalic = mfp->italic;
\r
1700 lf->lfUnderline = mfp->underline;
\r
1701 lf->lfStrikeOut = mfp->strikeout;
\r
1702 lf->lfCharSet = DEFAULT_CHARSET;
\r
1703 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
1704 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
1705 lf->lfQuality = DEFAULT_QUALITY;
\r
1706 lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
\r
1707 strcpy(lf->lfFaceName, mfp->faceName);
\r
1711 CreateFontInMF(MyFont *mf)
\r
1713 LFfromMFP(&mf->lf, &mf->mfp);
\r
1714 if (mf->hf) DeleteObject(mf->hf);
\r
1715 mf->hf = CreateFontIndirect(&mf->lf);
\r
1719 SetDefaultTextAttribs()
\r
1722 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1723 ParseAttribs(&textAttribs[cc].color,
\r
1724 &textAttribs[cc].effects,
\r
1725 defaultTextAttribs[cc]);
\r
1730 SetDefaultSounds()
\r
1734 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1735 textAttribs[cc].sound.name = strdup("");
\r
1736 textAttribs[cc].sound.data = NULL;
\r
1738 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1739 sounds[sc].name = strdup("");
\r
1740 sounds[sc].data = NULL;
\r
1742 sounds[(int)SoundBell].name = strdup(SOUND_BELL);
\r
1750 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1751 MyLoadSound(&textAttribs[cc].sound);
\r
1753 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1754 MyLoadSound(&sounds[sc]);
\r
1759 InitAppData(LPSTR lpCmdLine)
\r
1762 char buf[ARG_MAX], currDir[MSG_SIZ];
\r
1765 programName = szAppName;
\r
1767 /* Initialize to defaults */
\r
1768 lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);
\r
1769 darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);
\r
1770 whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);
\r
1771 blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);
\r
1772 highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);
\r
1773 premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);
\r
1774 consoleBackgroundColor = ParseColorName(COLOR_BKGD);
\r
1775 SetDefaultTextAttribs();
\r
1776 SetDefaultSounds();
\r
1777 appData.movesPerSession = MOVES_PER_SESSION;
\r
1778 appData.initString = INIT_STRING;
\r
1779 appData.secondInitString = INIT_STRING;
\r
1780 appData.firstComputerString = COMPUTER_STRING;
\r
1781 appData.secondComputerString = COMPUTER_STRING;
\r
1782 appData.firstChessProgram = FIRST_CHESS_PROGRAM;
\r
1783 appData.secondChessProgram = SECOND_CHESS_PROGRAM;
\r
1784 appData.firstPlaysBlack = FALSE;
\r
1785 appData.noChessProgram = FALSE;
\r
1786 chessProgram = FALSE;
\r
1787 appData.firstHost = FIRST_HOST;
\r
1788 appData.secondHost = SECOND_HOST;
\r
1789 appData.firstDirectory = FIRST_DIRECTORY;
\r
1790 appData.secondDirectory = SECOND_DIRECTORY;
\r
1791 appData.bitmapDirectory = "";
\r
1792 appData.remoteShell = REMOTE_SHELL;
\r
1793 appData.remoteUser = "";
\r
1794 appData.timeDelay = TIME_DELAY;
\r
1795 appData.timeControl = TIME_CONTROL;
\r
1796 appData.timeIncrement = TIME_INCREMENT;
\r
1797 appData.icsActive = FALSE;
\r
1798 appData.icsHost = "";
\r
1799 appData.icsPort = ICS_PORT;
\r
1800 appData.icsCommPort = ICS_COMM_PORT;
\r
1801 appData.icsLogon = ICS_LOGON;
\r
1802 appData.icsHelper = "";
\r
1803 appData.useTelnet = FALSE;
\r
1804 appData.telnetProgram = TELNET_PROGRAM;
\r
1805 appData.gateway = "";
\r
1806 appData.loadGameFile = "";
\r
1807 appData.loadGameIndex = 0;
\r
1808 appData.saveGameFile = "";
\r
1809 appData.autoSaveGames = FALSE;
\r
1810 appData.loadPositionFile = "";
\r
1811 appData.loadPositionIndex = 1;
\r
1812 appData.savePositionFile = "";
\r
1813 appData.matchMode = FALSE;
\r
1814 appData.matchGames = 0;
\r
1815 appData.monoMode = FALSE;
\r
1816 appData.debugMode = FALSE;
\r
1817 appData.clockMode = TRUE;
\r
1818 boardSize = (BoardSize) -1; /* determine by screen size */
\r
1819 appData.Iconic = FALSE; /*unused*/
\r
1820 appData.searchTime = "";
\r
1821 appData.searchDepth = 0;
\r
1822 appData.showCoords = FALSE;
\r
1823 appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/
\r
1824 appData.autoCallFlag = FALSE;
\r
1825 appData.flipView = FALSE;
\r
1826 appData.autoFlipView = TRUE;
\r
1827 appData.cmailGameName = "";
\r
1828 appData.alwaysPromoteToQueen = FALSE;
\r
1829 appData.oldSaveStyle = FALSE;
\r
1830 appData.quietPlay = FALSE;
\r
1831 appData.showThinking = FALSE;
\r
1832 appData.ponderNextMove = TRUE;
\r
1833 appData.periodicUpdates = TRUE;
\r
1834 appData.popupExitMessage = TRUE;
\r
1835 appData.popupMoveErrors = FALSE;
\r
1836 appData.autoObserve = FALSE;
\r
1837 appData.autoComment = FALSE;
\r
1838 appData.animate = TRUE;
\r
1839 appData.animSpeed = 10;
\r
1840 appData.animateDragging = TRUE;
\r
1841 appData.highlightLastMove = TRUE;
\r
1842 appData.getMoveList = TRUE;
\r
1843 appData.testLegality = TRUE;
\r
1844 appData.premove = TRUE;
\r
1845 appData.premoveWhite = FALSE;
\r
1846 appData.premoveWhiteText = "";
\r
1847 appData.premoveBlack = FALSE;
\r
1848 appData.premoveBlackText = "";
\r
1849 appData.icsAlarm = TRUE;
\r
1850 appData.icsAlarmTime = 5000;
\r
1851 appData.autoRaiseBoard = TRUE;
\r
1852 appData.localLineEditing = TRUE;
\r
1853 appData.colorize = TRUE;
\r
1854 appData.reuseFirst = TRUE;
\r
1855 appData.reuseSecond = TRUE;
\r
1856 appData.blindfold = FALSE;
\r
1857 appData.icsEngineAnalyze = FALSE;
\r
1858 memset(&dcb, 0, sizeof(DCB)); // required by VS 2002 +
\r
1859 dcb.DCBlength = sizeof(DCB);
\r
1860 dcb.BaudRate = 9600;
\r
1861 dcb.fBinary = TRUE;
\r
1862 dcb.fParity = FALSE;
\r
1863 dcb.fOutxCtsFlow = FALSE;
\r
1864 dcb.fOutxDsrFlow = FALSE;
\r
1865 dcb.fDtrControl = DTR_CONTROL_ENABLE;
\r
1866 dcb.fDsrSensitivity = FALSE;
\r
1867 dcb.fTXContinueOnXoff = TRUE;
\r
1868 dcb.fOutX = FALSE;
\r
1870 dcb.fNull = FALSE;
\r
1871 dcb.fRtsControl = RTS_CONTROL_ENABLE;
\r
1872 dcb.fAbortOnError = FALSE;
\r
1874 dcb.Parity = SPACEPARITY;
\r
1875 dcb.StopBits = ONESTOPBIT;
\r
1876 settingsFileName = SETTINGS_FILE;
\r
1877 saveSettingsOnExit = TRUE;
\r
1878 boardX = CW_USEDEFAULT;
\r
1879 boardY = CW_USEDEFAULT;
\r
1880 consoleX = CW_USEDEFAULT;
\r
1881 consoleY = CW_USEDEFAULT;
\r
1882 consoleW = CW_USEDEFAULT;
\r
1883 consoleH = CW_USEDEFAULT;
\r
1884 analysisX = CW_USEDEFAULT;
\r
1885 analysisY = CW_USEDEFAULT;
\r
1886 analysisW = CW_USEDEFAULT;
\r
1887 analysisH = CW_USEDEFAULT;
\r
1888 commentX = CW_USEDEFAULT;
\r
1889 commentY = CW_USEDEFAULT;
\r
1890 commentW = CW_USEDEFAULT;
\r
1891 commentH = CW_USEDEFAULT;
\r
1892 editTagsX = CW_USEDEFAULT;
\r
1893 editTagsY = CW_USEDEFAULT;
\r
1894 editTagsW = CW_USEDEFAULT;
\r
1895 editTagsH = CW_USEDEFAULT;
\r
1896 gameListX = CW_USEDEFAULT;
\r
1897 gameListY = CW_USEDEFAULT;
\r
1898 gameListW = CW_USEDEFAULT;
\r
1899 gameListH = CW_USEDEFAULT;
\r
1900 icsTextMenuString = ICS_TEXT_MENU_DEFAULT;
\r
1901 icsNames = ICS_NAMES;
\r
1902 firstChessProgramNames = FCP_NAMES;
\r
1903 secondChessProgramNames = SCP_NAMES;
\r
1904 appData.initialMode = "";
\r
1905 appData.variant = "normal";
\r
1906 appData.firstProtocolVersion = PROTOVER;
\r
1907 appData.secondProtocolVersion = PROTOVER;
\r
1908 appData.showButtonBar = TRUE;
\r
1910 /* [AS] New properties (see comments in header file) */
\r
1911 appData.firstScoreIsAbsolute = FALSE;
\r
1912 appData.secondScoreIsAbsolute = FALSE;
\r
1913 appData.saveExtendedInfoInPGN = FALSE;
\r
1914 appData.hideThinkingFromHuman = FALSE;
\r
1915 appData.liteBackTextureFile = "";
\r
1916 appData.liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
1917 appData.darkBackTextureFile = "";
\r
1918 appData.darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
1919 appData.renderPiecesWithFont = "";
\r
1920 appData.fontToPieceTable = "";
\r
1921 appData.fontBackColorWhite = 0;
\r
1922 appData.fontForeColorWhite = 0;
\r
1923 appData.fontBackColorBlack = 0;
\r
1924 appData.fontForeColorBlack = 0;
\r
1925 appData.fontPieceSize = 80;
\r
1926 appData.overrideLineGap = 1;
\r
1927 appData.adjudicateLossThreshold = 0;
\r
1928 appData.delayBeforeQuit = 0;
\r
1929 appData.delayAfterQuit = 0;
\r
1930 appData.nameOfDebugFile = "winboard.debug";
\r
1931 appData.pgnEventHeader = "Computer Chess Game";
\r
1932 appData.defaultFrcPosition = -1;
\r
1933 appData.gameListTags = GLT_DEFAULT_TAGS;
\r
1934 appData.saveOutOfBookInfo = TRUE;
\r
1935 appData.showEvalInMoveHistory = TRUE;
\r
1936 appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );
\r
1937 appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );
\r
1938 appData.highlightMoveWithArrow = FALSE;
\r
1939 appData.highlightArrowColor = ParseColorName( "#FFFF80" );
\r
1940 appData.useStickyWindows = TRUE;
\r
1941 appData.adjudicateDrawMoves = 0;
\r
1942 appData.autoDisplayComment = TRUE;
\r
1943 appData.autoDisplayTags = TRUE;
\r
1944 appData.firstIsUCI = FALSE;
\r
1945 appData.secondIsUCI = FALSE;
\r
1946 appData.firstHasOwnBookUCI = TRUE;
\r
1947 appData.secondHasOwnBookUCI = TRUE;
\r
1948 appData.polyglotDir = "";
\r
1949 appData.usePolyglotBook = FALSE;
\r
1950 appData.polyglotBook = "";
\r
1951 appData.defaultHashSize = 64;
\r
1952 appData.defaultCacheSizeEGTB = 4;
\r
1953 appData.defaultPathEGTB = "c:\\egtb";
\r
1954 appData.firstOptions = "";
\r
1955 appData.secondOptions = "";
\r
1957 InitWindowPlacement( &wpMoveHistory );
\r
1958 InitWindowPlacement( &wpEvalGraph );
\r
1959 InitWindowPlacement( &wpEngineOutput );
\r
1961 /* [HGM] User-selectable board size, adjudication control, miscellaneous */
\r
1962 appData.NrFiles = -1;
\r
1963 appData.NrRanks = -1;
\r
1964 appData.holdingsSize = -1;
\r
1965 appData.testClaims = FALSE;
\r
1966 appData.checkMates = FALSE;
\r
1967 appData.materialDraws= FALSE;
\r
1968 appData.trivialDraws = FALSE;
\r
1969 appData.ruleMoves = 51;
\r
1970 appData.drawRepeats = 6;
\r
1971 appData.matchPause = 10000;
\r
1972 appData.alphaRank = FALSE;
\r
1973 appData.allWhite = FALSE;
\r
1974 appData.upsideDown = FALSE;
\r
1975 appData.serverPause = 15;
\r
1976 appData.serverMovesName = NULL;
\r
1977 appData.suppressLoadMoves = FALSE;
\r
1978 appData.firstTimeOdds = 1;
\r
1979 appData.secondTimeOdds = 1;
\r
1980 appData.firstAccumulateTC = 1; // combine previous and current sessions
\r
1981 appData.secondAccumulateTC = 1;
\r
1982 appData.firstNPS = -1; // [HGM] nps: use wall-clock time
\r
1983 appData.secondNPS = -1;
\r
1984 appData.engineComments = 1;
\r
1985 appData.smpCores = 1; // [HGM] SMP: max nr of cores
\r
1986 appData.egtFormats = "";
\r
1989 appData.zippyTalk = ZIPPY_TALK;
\r
1990 appData.zippyPlay = ZIPPY_PLAY;
\r
1991 appData.zippyLines = ZIPPY_LINES;
\r
1992 appData.zippyPinhead = ZIPPY_PINHEAD;
\r
1993 appData.zippyPassword = ZIPPY_PASSWORD;
\r
1994 appData.zippyPassword2 = ZIPPY_PASSWORD2;
\r
1995 appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;
\r
1996 appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;
\r
1997 appData.zippyUseI = ZIPPY_USE_I;
\r
1998 appData.zippyBughouse = ZIPPY_BUGHOUSE;
\r
1999 appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;
\r
2000 appData.zippyGameEnd = ZIPPY_GAME_END;
\r
2001 appData.zippyGameStart = ZIPPY_GAME_START;
\r
2002 appData.zippyAdjourn = ZIPPY_ADJOURN;
\r
2003 appData.zippyAbort = ZIPPY_ABORT;
\r
2004 appData.zippyVariants = ZIPPY_VARIANTS;
\r
2005 appData.zippyMaxGames = ZIPPY_MAX_GAMES;
\r
2006 appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;
\r
2009 /* Point font array elements to structures and
\r
2010 parse default font names */
\r
2011 for (i=0; i<NUM_FONTS; i++) {
\r
2012 for (j=0; j<NUM_SIZES; j++) {
\r
2013 font[j][i] = &fontRec[j][i];
\r
2014 ParseFontName(font[j][i]->def, &font[j][i]->mfp);
\r
2018 /* Parse default settings file if any */
\r
2019 if (ParseSettingsFile(settingsFileName, buf)) {
\r
2020 settingsFileName = strdup(buf);
\r
2023 /* Parse command line */
\r
2024 ParseArgs(StringGet, &lpCmdLine);
\r
2026 /* [HGM] make sure board size is acceptable */
\r
2027 if(appData.NrFiles > BOARD_SIZE ||
\r
2028 appData.NrRanks > BOARD_SIZE )
\r
2029 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
2031 /* [HGM] After parsing the options from the .ini file, and overruling them
\r
2032 * with options from the command line, we now make an even higher priority
\r
2033 * overrule by WB options attached to the engine command line. This so that
\r
2034 * tournament managers can use WB options (such as /timeOdds) that follow
\r
2037 if(appData.firstChessProgram != NULL) {
\r
2038 char *p = StrStr(appData.firstChessProgram, "WBopt");
\r
2039 static char *f = "first";
\r
2040 char buf[MSG_SIZ], *q = buf;
\r
2041 if(p != NULL) { // engine command line contains WinBoard options
\r
2042 sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"
\r
2043 ParseArgs(StringGet, &q);
\r
2044 p[-1] = 0; // cut them offengine command line
\r
2047 // now do same for second chess program
\r
2048 if(appData.secondChessProgram != NULL) {
\r
2049 char *p = StrStr(appData.secondChessProgram, "WBopt");
\r
2050 static char *s = "second";
\r
2051 char buf[MSG_SIZ], *q = buf;
\r
2052 if(p != NULL) { // engine command line contains WinBoard options
\r
2053 sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"
\r
2054 ParseArgs(StringGet, &q);
\r
2055 p[-1] = 0; // cut them offengine command line
\r
2060 /* Propagate options that affect others */
\r
2061 if (appData.matchMode || appData.matchGames) chessProgram = TRUE;
\r
2062 if (appData.icsActive || appData.noChessProgram) {
\r
2063 chessProgram = FALSE; /* not local chess program mode */
\r
2066 /* Open startup dialog if needed */
\r
2067 if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||
\r
2068 (appData.icsActive && *appData.icsHost == NULLCHAR) ||
\r
2069 (chessProgram && (*appData.firstChessProgram == NULLCHAR ||
\r
2070 *appData.secondChessProgram == NULLCHAR))) {
\r
2073 lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);
\r
2074 DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);
\r
2075 FreeProcInstance(lpProc);
\r
2078 /* Make sure save files land in the right (?) directory */
\r
2079 if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {
\r
2080 appData.saveGameFile = strdup(buf);
\r
2082 if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {
\r
2083 appData.savePositionFile = strdup(buf);
\r
2086 /* Finish initialization for fonts and sounds */
\r
2087 for (i=0; i<NUM_FONTS; i++) {
\r
2088 for (j=0; j<NUM_SIZES; j++) {
\r
2089 CreateFontInMF(font[j][i]);
\r
2092 /* xboard, and older WinBoards, controlled the move sound with the
\r
2093 appData.ringBellAfterMoves option. In the current WinBoard, we
\r
2094 always turn the option on (so that the backend will call us),
\r
2095 then let the user turn the sound off by setting it to silence if
\r
2096 desired. To accommodate old winboard.ini files saved by old
\r
2097 versions of WinBoard, we also turn off the sound if the option
\r
2098 was initially set to false. */
\r
2099 if (!appData.ringBellAfterMoves) {
\r
2100 sounds[(int)SoundMove].name = strdup("");
\r
2101 appData.ringBellAfterMoves = TRUE;
\r
2103 GetCurrentDirectory(MSG_SIZ, currDir);
\r
2104 SetCurrentDirectory(installDir);
\r
2106 SetCurrentDirectory(currDir);
\r
2108 p = icsTextMenuString;
\r
2109 if (p[0] == '@') {
\r
2110 FILE* f = fopen(p + 1, "r");
\r
2112 DisplayFatalError(p + 1, errno, 2);
\r
2115 i = fread(buf, 1, sizeof(buf)-1, f);
\r
2117 buf[i] = NULLCHAR;
\r
2120 ParseIcsTextMenu(strdup(p));
\r
2127 HMENU hmenu = GetMenu(hwndMain);
\r
2129 (void) EnableMenuItem(hmenu, IDM_CommPort,
\r
2130 MF_BYCOMMAND|((appData.icsActive &&
\r
2131 *appData.icsCommPort != NULLCHAR) ?
\r
2132 MF_ENABLED : MF_GRAYED));
\r
2133 (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,
\r
2134 MF_BYCOMMAND|(saveSettingsOnExit ?
\r
2135 MF_CHECKED : MF_UNCHECKED));
\r
2140 SaveSettings(char* name)
\r
2143 ArgDescriptor *ad;
\r
2144 WINDOWPLACEMENT wp;
\r
2145 char dir[MSG_SIZ];
\r
2147 if (!hwndMain) return;
\r
2149 GetCurrentDirectory(MSG_SIZ, dir);
\r
2150 SetCurrentDirectory(installDir);
\r
2151 f = fopen(name, "w");
\r
2152 SetCurrentDirectory(dir);
\r
2154 DisplayError(name, errno);
\r
2157 fprintf(f, ";\n");
\r
2158 fprintf(f, "; %s %s.%s Save Settings file\n", PRODUCT, VERSION, PATCHLEVEL);
\r
2159 fprintf(f, ";\n");
\r
2160 fprintf(f, "; You can edit the values of options that are already set in this file,\n");
\r
2161 fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");
\r
2162 fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");
\r
2163 fprintf(f, ";\n");
\r
2165 wp.length = sizeof(WINDOWPLACEMENT);
\r
2166 GetWindowPlacement(hwndMain, &wp);
\r
2167 boardX = wp.rcNormalPosition.left;
\r
2168 boardY = wp.rcNormalPosition.top;
\r
2170 if (hwndConsole) {
\r
2171 GetWindowPlacement(hwndConsole, &wp);
\r
2172 consoleX = wp.rcNormalPosition.left;
\r
2173 consoleY = wp.rcNormalPosition.top;
\r
2174 consoleW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2175 consoleH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2178 if (analysisDialog) {
\r
2179 GetWindowPlacement(analysisDialog, &wp);
\r
2180 analysisX = wp.rcNormalPosition.left;
\r
2181 analysisY = wp.rcNormalPosition.top;
\r
2182 analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2183 analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2186 if (commentDialog) {
\r
2187 GetWindowPlacement(commentDialog, &wp);
\r
2188 commentX = wp.rcNormalPosition.left;
\r
2189 commentY = wp.rcNormalPosition.top;
\r
2190 commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2191 commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2194 if (editTagsDialog) {
\r
2195 GetWindowPlacement(editTagsDialog, &wp);
\r
2196 editTagsX = wp.rcNormalPosition.left;
\r
2197 editTagsY = wp.rcNormalPosition.top;
\r
2198 editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2199 editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2202 if (gameListDialog) {
\r
2203 GetWindowPlacement(gameListDialog, &wp);
\r
2204 gameListX = wp.rcNormalPosition.left;
\r
2205 gameListY = wp.rcNormalPosition.top;
\r
2206 gameListW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2207 gameListH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2210 /* [AS] Move history */
\r
2211 wpMoveHistory.visible = MoveHistoryIsUp();
\r
2213 if( moveHistoryDialog ) {
\r
2214 GetWindowPlacement(moveHistoryDialog, &wp);
\r
2215 wpMoveHistory.x = wp.rcNormalPosition.left;
\r
2216 wpMoveHistory.y = wp.rcNormalPosition.top;
\r
2217 wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2218 wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2221 /* [AS] Eval graph */
\r
2222 wpEvalGraph.visible = EvalGraphIsUp();
\r
2224 if( evalGraphDialog ) {
\r
2225 GetWindowPlacement(evalGraphDialog, &wp);
\r
2226 wpEvalGraph.x = wp.rcNormalPosition.left;
\r
2227 wpEvalGraph.y = wp.rcNormalPosition.top;
\r
2228 wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2229 wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2232 /* [AS] Engine output */
\r
2233 wpEngineOutput.visible = EngineOutputIsUp();
\r
2235 if( engineOutputDialog ) {
\r
2236 GetWindowPlacement(engineOutputDialog, &wp);
\r
2237 wpEngineOutput.x = wp.rcNormalPosition.left;
\r
2238 wpEngineOutput.y = wp.rcNormalPosition.top;
\r
2239 wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2240 wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2243 for (ad = argDescriptors; ad->argName != NULL; ad++) {
\r
2244 if (!ad->save) continue;
\r
2245 switch (ad->argType) {
\r
2248 char *p = *(char **)ad->argLoc;
\r
2249 if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {
\r
2250 /* Quote multiline values or \-containing values
\r
2251 with { } if possible */
\r
2252 fprintf(f, "/%s={%s}\n", ad->argName, p);
\r
2254 /* Else quote with " " */
\r
2255 fprintf(f, "/%s=\"", ad->argName);
\r
2257 if (*p == '\n') fprintf(f, "\n");
\r
2258 else if (*p == '\r') fprintf(f, "\\r");
\r
2259 else if (*p == '\t') fprintf(f, "\\t");
\r
2260 else if (*p == '\b') fprintf(f, "\\b");
\r
2261 else if (*p == '\f') fprintf(f, "\\f");
\r
2262 else if (*p < ' ') fprintf(f, "\\%03o", *p);
\r
2263 else if (*p == '\"') fprintf(f, "\\\"");
\r
2264 else if (*p == '\\') fprintf(f, "\\\\");
\r
2268 fprintf(f, "\"\n");
\r
2273 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);
\r
2276 fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);
\r
2279 fprintf(f, "/%s=%s\n", ad->argName,
\r
2280 (*(Boolean *)ad->argLoc) ? "true" : "false");
\r
2283 if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2286 if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2290 COLORREF color = *(COLORREF *)ad->argLoc;
\r
2291 fprintf(f, "/%s=#%02lx%02lx%02lx\n", ad->argName,
\r
2292 color&0xff, (color>>8)&0xff, (color>>16)&0xff);
\r
2297 MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];
\r
2298 fprintf(f, "/%s=\"%s%s%s%s%s#%02lx%02lx%02lx\"\n", ad->argName,
\r
2299 (ta->effects & CFE_BOLD) ? "b" : "",
\r
2300 (ta->effects & CFE_ITALIC) ? "i" : "",
\r
2301 (ta->effects & CFE_UNDERLINE) ? "u" : "",
\r
2302 (ta->effects & CFE_STRIKEOUT) ? "s" : "",
\r
2303 (ta->effects) ? " " : "",
\r
2304 ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);
\r
2308 if (strchr(*(char **)ad->argLoc, '\"')) {
\r
2309 fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);
\r
2311 fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);
\r
2314 case ArgBoardSize:
\r
2315 fprintf(f, "/%s=%s\n", ad->argName,
\r
2316 sizeInfo[*(BoardSize *)ad->argLoc].name);
\r
2321 for (bs=0; bs<NUM_SIZES; bs++) {
\r
2322 MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;
\r
2323 fprintf(f, "/size=%s ", sizeInfo[bs].name);
\r
2324 fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n",
\r
2325 ad->argName, mfp->faceName, mfp->pointSize,
\r
2326 mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",
\r
2327 mfp->bold ? "b" : "",
\r
2328 mfp->italic ? "i" : "",
\r
2329 mfp->underline ? "u" : "",
\r
2330 mfp->strikeout ? "s" : "");
\r
2334 case ArgCommSettings:
\r
2335 PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);
\r
2337 case ArgSettingsFilename: ;
\r
2345 /*---------------------------------------------------------------------------*\
\r
2347 * GDI board drawing routines
\r
2349 \*---------------------------------------------------------------------------*/
\r
2351 /* [AS] Draw square using background texture */
\r
2352 static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )
\r
2357 return; /* Should never happen! */
\r
2360 SetGraphicsMode( dst, GM_ADVANCED );
\r
2367 /* X reflection */
\r
2372 x.eDx = (FLOAT) dw + dx - 1;
\r
2375 SetWorldTransform( dst, &x );
\r
2378 /* Y reflection */
\r
2384 x.eDy = (FLOAT) dh + dy - 1;
\r
2386 SetWorldTransform( dst, &x );
\r
2394 x.eDx = (FLOAT) dx;
\r
2395 x.eDy = (FLOAT) dy;
\r
2398 SetWorldTransform( dst, &x );
\r
2402 BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );
\r
2410 SetWorldTransform( dst, &x );
\r
2412 ModifyWorldTransform( dst, 0, MWT_IDENTITY );
\r
2415 /* [AS] [HGM] Make room for more piece types, so all pieces can be different */
\r
2417 PM_WP = (int) WhitePawn,
\r
2418 PM_WN = (int) WhiteKnight,
\r
2419 PM_WB = (int) WhiteBishop,
\r
2420 PM_WR = (int) WhiteRook,
\r
2421 PM_WQ = (int) WhiteQueen,
\r
2422 PM_WF = (int) WhiteFerz,
\r
2423 PM_WW = (int) WhiteWazir,
\r
2424 PM_WE = (int) WhiteAlfil,
\r
2425 PM_WM = (int) WhiteMan,
\r
2426 PM_WO = (int) WhiteCannon,
\r
2427 PM_WU = (int) WhiteUnicorn,
\r
2428 PM_WH = (int) WhiteNightrider,
\r
2429 PM_WA = (int) WhiteAngel,
\r
2430 PM_WC = (int) WhiteMarshall,
\r
2431 PM_WAB = (int) WhiteCardinal,
\r
2432 PM_WD = (int) WhiteDragon,
\r
2433 PM_WL = (int) WhiteLance,
\r
2434 PM_WS = (int) WhiteCobra,
\r
2435 PM_WV = (int) WhiteFalcon,
\r
2436 PM_WSG = (int) WhiteSilver,
\r
2437 PM_WG = (int) WhiteGrasshopper,
\r
2438 PM_WK = (int) WhiteKing,
\r
2439 PM_BP = (int) BlackPawn,
\r
2440 PM_BN = (int) BlackKnight,
\r
2441 PM_BB = (int) BlackBishop,
\r
2442 PM_BR = (int) BlackRook,
\r
2443 PM_BQ = (int) BlackQueen,
\r
2444 PM_BF = (int) BlackFerz,
\r
2445 PM_BW = (int) BlackWazir,
\r
2446 PM_BE = (int) BlackAlfil,
\r
2447 PM_BM = (int) BlackMan,
\r
2448 PM_BO = (int) BlackCannon,
\r
2449 PM_BU = (int) BlackUnicorn,
\r
2450 PM_BH = (int) BlackNightrider,
\r
2451 PM_BA = (int) BlackAngel,
\r
2452 PM_BC = (int) BlackMarshall,
\r
2453 PM_BG = (int) BlackGrasshopper,
\r
2454 PM_BAB = (int) BlackCardinal,
\r
2455 PM_BD = (int) BlackDragon,
\r
2456 PM_BL = (int) BlackLance,
\r
2457 PM_BS = (int) BlackCobra,
\r
2458 PM_BV = (int) BlackFalcon,
\r
2459 PM_BSG = (int) BlackSilver,
\r
2460 PM_BK = (int) BlackKing
\r
2463 static HFONT hPieceFont = NULL;
\r
2464 static HBITMAP hPieceMask[(int) EmptySquare];
\r
2465 static HBITMAP hPieceFace[(int) EmptySquare];
\r
2466 static int fontBitmapSquareSize = 0;
\r
2467 static char pieceToFontChar[(int) EmptySquare] =
\r
2468 { 'p', 'n', 'b', 'r', 'q',
\r
2469 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',
\r
2470 'k', 'o', 'm', 'v', 't', 'w',
\r
2471 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',
\r
2474 extern BOOL SetCharTable( char *table, const char * map );
\r
2475 /* [HGM] moved to backend.c */
\r
2477 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )
\r
2480 BYTE r1 = GetRValue( color );
\r
2481 BYTE g1 = GetGValue( color );
\r
2482 BYTE b1 = GetBValue( color );
\r
2488 /* Create a uniform background first */
\r
2489 hbrush = CreateSolidBrush( color );
\r
2490 SetRect( &rc, 0, 0, squareSize, squareSize );
\r
2491 FillRect( hdc, &rc, hbrush );
\r
2492 DeleteObject( hbrush );
\r
2495 /* Vertical gradient, good for pawn, knight and rook, less for queen and king */
\r
2496 int steps = squareSize / 2;
\r
2499 for( i=0; i<steps; i++ ) {
\r
2500 BYTE r = r1 - (r1-r2) * i / steps;
\r
2501 BYTE g = g1 - (g1-g2) * i / steps;
\r
2502 BYTE b = b1 - (b1-b2) * i / steps;
\r
2504 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2505 SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );
\r
2506 FillRect( hdc, &rc, hbrush );
\r
2507 DeleteObject(hbrush);
\r
2510 else if( mode == 2 ) {
\r
2511 /* Diagonal gradient, good more or less for every piece */
\r
2512 POINT triangle[3];
\r
2513 HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );
\r
2514 HBRUSH hbrush_old;
\r
2515 int steps = squareSize;
\r
2518 triangle[0].x = squareSize - steps;
\r
2519 triangle[0].y = squareSize;
\r
2520 triangle[1].x = squareSize;
\r
2521 triangle[1].y = squareSize;
\r
2522 triangle[2].x = squareSize;
\r
2523 triangle[2].y = squareSize - steps;
\r
2525 for( i=0; i<steps; i++ ) {
\r
2526 BYTE r = r1 - (r1-r2) * i / steps;
\r
2527 BYTE g = g1 - (g1-g2) * i / steps;
\r
2528 BYTE b = b1 - (b1-b2) * i / steps;
\r
2530 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2531 hbrush_old = SelectObject( hdc, hbrush );
\r
2532 Polygon( hdc, triangle, 3 );
\r
2533 SelectObject( hdc, hbrush_old );
\r
2534 DeleteObject(hbrush);
\r
2539 SelectObject( hdc, hpen );
\r
2544 [AS] The method I use to create the bitmaps it a bit tricky, but it
\r
2545 seems to work ok. The main problem here is to find the "inside" of a chess
\r
2546 piece: follow the steps as explained below.
\r
2548 static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
\r
2552 COLORREF chroma = RGB(0xFF,0x00,0xFF);
\r
2556 int backColor = whitePieceColor;
\r
2557 int foreColor = blackPieceColor;
\r
2559 if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {
\r
2560 backColor = appData.fontBackColorWhite;
\r
2561 foreColor = appData.fontForeColorWhite;
\r
2563 else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {
\r
2564 backColor = appData.fontBackColorBlack;
\r
2565 foreColor = appData.fontForeColorBlack;
\r
2569 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2571 hbm_old = SelectObject( hdc, hbm );
\r
2575 rc.right = squareSize;
\r
2576 rc.bottom = squareSize;
\r
2578 /* Step 1: background is now black */
\r
2579 FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );
\r
2581 GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );
\r
2583 pt.x = (squareSize - sz.cx) / 2;
\r
2584 pt.y = (squareSize - sz.cy) / 2;
\r
2586 SetBkMode( hdc, TRANSPARENT );
\r
2587 SetTextColor( hdc, chroma );
\r
2588 /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */
\r
2589 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2591 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
\r
2592 /* Step 3: the area outside the piece is filled with white */
\r
2593 // FloodFill( hdc, 0, 0, chroma );
\r
2594 ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );
\r
2595 ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big
\r
2596 ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );
\r
2597 ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );
\r
2598 SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
\r
2600 Step 4: this is the tricky part, the area inside the piece is filled with black,
\r
2601 but if the start point is not inside the piece we're lost!
\r
2602 There should be a better way to do this... if we could create a region or path
\r
2603 from the fill operation we would be fine for example.
\r
2605 // FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );
\r
2606 ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );
\r
2608 { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */
\r
2609 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2610 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2612 SelectObject( dc2, bm2 );
\r
2613 BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy
\r
2614 BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2615 BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2616 BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2617 BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2620 DeleteObject( bm2 );
\r
2623 SetTextColor( hdc, 0 );
\r
2625 Step 5: some fonts have "disconnected" areas that are skipped by the fill:
\r
2626 draw the piece again in black for safety.
\r
2628 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2630 SelectObject( hdc, hbm_old );
\r
2632 if( hPieceMask[index] != NULL ) {
\r
2633 DeleteObject( hPieceMask[index] );
\r
2636 hPieceMask[index] = hbm;
\r
2639 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2641 SelectObject( hdc, hbm );
\r
2644 HDC dc1 = CreateCompatibleDC( hdc_window );
\r
2645 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2646 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2648 SelectObject( dc1, hPieceMask[index] );
\r
2649 SelectObject( dc2, bm2 );
\r
2650 FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );
\r
2651 BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );
\r
2654 Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves
\r
2655 the piece background and deletes (makes transparent) the rest.
\r
2656 Thanks to that mask, we are free to paint the background with the greates
\r
2657 freedom, as we'll be able to mask off the unwanted parts when finished.
\r
2658 We use this, to make gradients and give the pieces a "roundish" look.
\r
2660 SetPieceBackground( hdc, backColor, 2 );
\r
2661 BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );
\r
2665 DeleteObject( bm2 );
\r
2668 SetTextColor( hdc, foreColor );
\r
2669 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2671 SelectObject( hdc, hbm_old );
\r
2673 if( hPieceFace[index] != NULL ) {
\r
2674 DeleteObject( hPieceFace[index] );
\r
2677 hPieceFace[index] = hbm;
\r
2680 static int TranslatePieceToFontPiece( int piece )
\r
2710 case BlackMarshall:
\r
2714 case BlackNightrider:
\r
2720 case BlackUnicorn:
\r
2724 case BlackGrasshopper:
\r
2736 case BlackCardinal:
\r
2743 case WhiteMarshall:
\r
2747 case WhiteNightrider:
\r
2753 case WhiteUnicorn:
\r
2757 case WhiteGrasshopper:
\r
2769 case WhiteCardinal:
\r
2778 void CreatePiecesFromFont()
\r
2781 HDC hdc_window = NULL;
\r
2787 if( fontBitmapSquareSize < 0 ) {
\r
2788 /* Something went seriously wrong in the past: do not try to recreate fonts! */
\r
2792 if( appData.renderPiecesWithFont == NULL || appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {
\r
2793 fontBitmapSquareSize = -1;
\r
2797 if( fontBitmapSquareSize != squareSize ) {
\r
2798 hdc_window = GetDC( hwndMain );
\r
2799 hdc = CreateCompatibleDC( hdc_window );
\r
2801 if( hPieceFont != NULL ) {
\r
2802 DeleteObject( hPieceFont );
\r
2805 for( i=0; i<=(int)BlackKing; i++ ) {
\r
2806 hPieceMask[i] = NULL;
\r
2807 hPieceFace[i] = NULL;
\r
2813 if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {
\r
2814 fontHeight = appData.fontPieceSize;
\r
2817 fontHeight = (fontHeight * squareSize) / 100;
\r
2819 lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
\r
2821 lf.lfEscapement = 0;
\r
2822 lf.lfOrientation = 0;
\r
2823 lf.lfWeight = FW_NORMAL;
\r
2825 lf.lfUnderline = 0;
\r
2826 lf.lfStrikeOut = 0;
\r
2827 lf.lfCharSet = DEFAULT_CHARSET;
\r
2828 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
2829 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
2830 lf.lfQuality = PROOF_QUALITY;
\r
2831 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
\r
2832 strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );
\r
2833 lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';
\r
2835 hPieceFont = CreateFontIndirect( &lf );
\r
2837 if( hPieceFont == NULL ) {
\r
2838 fontBitmapSquareSize = -2;
\r
2841 /* Setup font-to-piece character table */
\r
2842 if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {
\r
2843 /* No (or wrong) global settings, try to detect the font */
\r
2844 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {
\r
2846 SetCharTable(pieceToFontChar, "phbrqkojntwl");
\r
2848 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {
\r
2849 /* DiagramTT* family */
\r
2850 SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");
\r
2852 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {
\r
2853 /* Fairy symbols */
\r
2854 SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
\r
2856 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {
\r
2857 /* Good Companion (Some characters get warped as literal :-( */
\r
2858 char s[] = "1cmWG0ñueOS¯®oYI23wgQU";
\r
2859 s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;
\r
2860 SetCharTable(pieceToFontChar, s);
\r
2863 /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */
\r
2864 SetCharTable(pieceToFontChar, "pnbrqkomvtwl");
\r
2868 /* Create bitmaps */
\r
2869 hfont_old = SelectObject( hdc, hPieceFont );
\r
2871 CreatePieceMaskFromFont( hdc_window, hdc, PM_WP );
\r
2872 CreatePieceMaskFromFont( hdc_window, hdc, PM_WN );
\r
2873 CreatePieceMaskFromFont( hdc_window, hdc, PM_WB );
\r
2874 CreatePieceMaskFromFont( hdc_window, hdc, PM_WR );
\r
2875 CreatePieceMaskFromFont( hdc_window, hdc, PM_WQ );
\r
2876 CreatePieceMaskFromFont( hdc_window, hdc, PM_WK );
\r
2877 CreatePieceMaskFromFont( hdc_window, hdc, PM_BP );
\r
2878 CreatePieceMaskFromFont( hdc_window, hdc, PM_BN );
\r
2879 CreatePieceMaskFromFont( hdc_window, hdc, PM_BB );
\r
2880 CreatePieceMaskFromFont( hdc_window, hdc, PM_BR );
\r
2881 CreatePieceMaskFromFont( hdc_window, hdc, PM_BQ );
\r
2882 CreatePieceMaskFromFont( hdc_window, hdc, PM_BK );
\r
2884 CreatePieceMaskFromFont( hdc_window, hdc, PM_WA );
\r
2885 CreatePieceMaskFromFont( hdc_window, hdc, PM_WC );
\r
2886 CreatePieceMaskFromFont( hdc_window, hdc, PM_WF );
\r
2887 CreatePieceMaskFromFont( hdc_window, hdc, PM_WH );
\r
2888 CreatePieceMaskFromFont( hdc_window, hdc, PM_WE );
\r
2889 CreatePieceMaskFromFont( hdc_window, hdc, PM_WW );
\r
2890 CreatePieceMaskFromFont( hdc_window, hdc, PM_WU );
\r
2891 CreatePieceMaskFromFont( hdc_window, hdc, PM_WO );
\r
2892 CreatePieceMaskFromFont( hdc_window, hdc, PM_WG );
\r
2893 CreatePieceMaskFromFont( hdc_window, hdc, PM_WM );
\r
2894 CreatePieceMaskFromFont( hdc_window, hdc, PM_WSG );
\r
2895 CreatePieceMaskFromFont( hdc_window, hdc, PM_WV );
\r
2896 CreatePieceMaskFromFont( hdc_window, hdc, PM_WAB );
\r
2897 CreatePieceMaskFromFont( hdc_window, hdc, PM_WD );
\r
2898 CreatePieceMaskFromFont( hdc_window, hdc, PM_WL );
\r
2899 CreatePieceMaskFromFont( hdc_window, hdc, PM_WS );
\r
2900 CreatePieceMaskFromFont( hdc_window, hdc, PM_BA );
\r
2901 CreatePieceMaskFromFont( hdc_window, hdc, PM_BC );
\r
2902 CreatePieceMaskFromFont( hdc_window, hdc, PM_BF );
\r
2903 CreatePieceMaskFromFont( hdc_window, hdc, PM_BH );
\r
2904 CreatePieceMaskFromFont( hdc_window, hdc, PM_BE );
\r
2905 CreatePieceMaskFromFont( hdc_window, hdc, PM_BW );
\r
2906 CreatePieceMaskFromFont( hdc_window, hdc, PM_BU );
\r
2907 CreatePieceMaskFromFont( hdc_window, hdc, PM_BO );
\r
2908 CreatePieceMaskFromFont( hdc_window, hdc, PM_BG );
\r
2909 CreatePieceMaskFromFont( hdc_window, hdc, PM_BM );
\r
2910 CreatePieceMaskFromFont( hdc_window, hdc, PM_BSG );
\r
2911 CreatePieceMaskFromFont( hdc_window, hdc, PM_BV );
\r
2912 CreatePieceMaskFromFont( hdc_window, hdc, PM_BAB );
\r
2913 CreatePieceMaskFromFont( hdc_window, hdc, PM_BD );
\r
2914 CreatePieceMaskFromFont( hdc_window, hdc, PM_BL );
\r
2915 CreatePieceMaskFromFont( hdc_window, hdc, PM_BS );
\r
2917 for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */
\r
2918 if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */
\r
2919 CreatePieceMaskFromFont( hdc_window, hdc, i );
\r
2921 SelectObject( hdc, hfont_old );
\r
2923 fontBitmapSquareSize = squareSize;
\r
2927 if( hdc != NULL ) {
\r
2931 if( hdc_window != NULL ) {
\r
2932 ReleaseDC( hwndMain, hdc_window );
\r
2937 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)
\r
2941 sprintf(name, "%s%d%s", piece, squareSize, suffix);
\r
2942 if (gameInfo.event &&
\r
2943 strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&
\r
2944 strcmp(name, "k80s") == 0) {
\r
2945 strcpy(name, "tim");
\r
2947 return LoadBitmap(hinst, name);
\r
2951 /* Insert a color into the program's logical palette
\r
2952 structure. This code assumes the given color is
\r
2953 the result of the RGB or PALETTERGB macro, and it
\r
2954 knows how those macros work (which is documented).
\r
2957 InsertInPalette(COLORREF color)
\r
2959 LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);
\r
2961 if (pLogPal->palNumEntries++ >= PALETTESIZE) {
\r
2962 DisplayFatalError("Too many colors", 0, 1);
\r
2963 pLogPal->palNumEntries--;
\r
2967 pe->peFlags = (char) 0;
\r
2968 pe->peRed = (char) (0xFF & color);
\r
2969 pe->peGreen = (char) (0xFF & (color >> 8));
\r
2970 pe->peBlue = (char) (0xFF & (color >> 16));
\r
2976 InitDrawingColors()
\r
2978 if (pLogPal == NULL) {
\r
2979 /* Allocate enough memory for a logical palette with
\r
2980 * PALETTESIZE entries and set the size and version fields
\r
2981 * of the logical palette structure.
\r
2983 pLogPal = (NPLOGPALETTE)
\r
2984 LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +
\r
2985 (sizeof(PALETTEENTRY) * (PALETTESIZE))));
\r
2986 pLogPal->palVersion = 0x300;
\r
2988 pLogPal->palNumEntries = 0;
\r
2990 InsertInPalette(lightSquareColor);
\r
2991 InsertInPalette(darkSquareColor);
\r
2992 InsertInPalette(whitePieceColor);
\r
2993 InsertInPalette(blackPieceColor);
\r
2994 InsertInPalette(highlightSquareColor);
\r
2995 InsertInPalette(premoveHighlightColor);
\r
2997 /* create a logical color palette according the information
\r
2998 * in the LOGPALETTE structure.
\r
3000 hPal = CreatePalette((LPLOGPALETTE) pLogPal);
\r
3002 lightSquareBrush = CreateSolidBrush(lightSquareColor);
\r
3003 blackSquareBrush = CreateSolidBrush(blackPieceColor);
\r
3004 darkSquareBrush = CreateSolidBrush(darkSquareColor);
\r
3005 whitePieceBrush = CreateSolidBrush(whitePieceColor);
\r
3006 blackPieceBrush = CreateSolidBrush(blackPieceColor);
\r
3007 iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
\r
3009 /* [AS] Force rendering of the font-based pieces */
\r
3010 if( fontBitmapSquareSize > 0 ) {
\r
3011 fontBitmapSquareSize = 0;
\r
3017 BoardWidth(int boardSize, int n)
\r
3018 { /* [HGM] argument n added to allow different width and height */
\r
3019 int lineGap = sizeInfo[boardSize].lineGap;
\r
3021 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3022 lineGap = appData.overrideLineGap;
\r
3025 return (n + 1) * lineGap +
\r
3026 n * sizeInfo[boardSize].squareSize;
\r
3029 /* Respond to board resize by dragging edge */
\r
3031 ResizeBoard(int newSizeX, int newSizeY, int flags)
\r
3033 BoardSize newSize = NUM_SIZES - 1;
\r
3034 static int recurse = 0;
\r
3035 if (IsIconic(hwndMain)) return;
\r
3036 if (recurse > 0) return;
\r
3038 while (newSize > 0) {
\r
3039 InitDrawingSizes(newSize+1000, 0); // [HGM] kludge to update sizeInfo without visible effects
\r
3040 if(newSizeX >= sizeInfo[newSize].cliWidth &&
\r
3041 newSizeY >= sizeInfo[newSize].cliHeight) break;
\r
3044 boardSize = newSize;
\r
3045 InitDrawingSizes(boardSize, flags);
\r
3052 InitDrawingSizes(BoardSize boardSize, int flags)
\r
3054 int i, boardWidth, boardHeight; /* [HGM] height treated separately */
\r
3055 ChessSquare piece;
\r
3056 static int oldBoardSize = -1, oldTinyLayout = 0;
\r
3058 SIZE clockSize, messageSize;
\r
3060 char buf[MSG_SIZ];
\r
3062 HMENU hmenu = GetMenu(hwndMain);
\r
3063 RECT crect, wrect;
\r
3065 LOGBRUSH logbrush;
\r
3067 int suppressVisibleEffects = 0; // [HGM] kludge to request updating sizeInfo only
\r
3068 if((int)boardSize >= 1000 ) { boardSize -= 1000; suppressVisibleEffects = 1; }
\r
3070 /* [HGM] call with -2 uses old size (for if nr of files, ranks changes) */
\r
3071 if(boardSize == (BoardSize)(-2) ) boardSize = oldBoardSize;
\r
3073 tinyLayout = sizeInfo[boardSize].tinyLayout;
\r
3074 smallLayout = sizeInfo[boardSize].smallLayout;
\r
3075 squareSize = sizeInfo[boardSize].squareSize;
\r
3076 lineGap = sizeInfo[boardSize].lineGap;
\r
3077 minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted */
\r
3079 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3080 lineGap = appData.overrideLineGap;
\r
3083 if (tinyLayout != oldTinyLayout) {
\r
3084 long style = GetWindowLong(hwndMain, GWL_STYLE);
\r
3086 style &= ~WS_SYSMENU;
\r
3087 InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize,
\r
3088 "&Minimize\tCtrl+F4");
\r
3090 style |= WS_SYSMENU;
\r
3091 RemoveMenu(hmenu, IDM_Minimize, MF_BYCOMMAND);
\r
3093 SetWindowLong(hwndMain, GWL_STYLE, style);
\r
3095 for (i=0; menuBarText[tinyLayout][i]; i++) {
\r
3096 ModifyMenu(hmenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP,
\r
3097 (UINT)GetSubMenu(hmenu, i), menuBarText[tinyLayout][i]);
\r
3099 DrawMenuBar(hwndMain);
\r
3102 boardWidth = BoardWidth(boardSize, BOARD_WIDTH);
\r
3103 boardHeight = BoardWidth(boardSize, BOARD_HEIGHT);
\r
3105 /* Get text area sizes */
\r
3106 hdc = GetDC(hwndMain);
\r
3107 if (appData.clockMode) {
\r
3108 sprintf(buf, "White: %s", TimeString(23*60*60*1000L));
\r
3110 sprintf(buf, "White");
\r
3112 oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);
\r
3113 GetTextExtentPoint(hdc, buf, strlen(buf), &clockSize);
\r
3114 SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);
\r
3115 str = "We only care about the height here";
\r
3116 GetTextExtentPoint(hdc, str, strlen(str), &messageSize);
\r
3117 SelectObject(hdc, oldFont);
\r
3118 ReleaseDC(hwndMain, hdc);
\r
3120 /* Compute where everything goes */
\r
3121 if(first.programLogo || second.programLogo) {
\r
3122 /* [HGM] logo: if either logo is on, reserve space for it */
\r
3123 logoHeight = 2*clockSize.cy;
\r
3124 leftLogoRect.left = OUTER_MARGIN;
\r
3125 leftLogoRect.right = leftLogoRect.left + 4*clockSize.cy;
\r
3126 leftLogoRect.top = OUTER_MARGIN;
\r
3127 leftLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3129 rightLogoRect.right = OUTER_MARGIN + boardWidth;
\r
3130 rightLogoRect.left = rightLogoRect.right - 4*clockSize.cy;
\r
3131 rightLogoRect.top = OUTER_MARGIN;
\r
3132 rightLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3135 blackRect.left = leftLogoRect.right;
\r
3136 blackRect.right = rightLogoRect.left;
\r
3137 blackRect.top = OUTER_MARGIN;
\r
3138 blackRect.bottom = blackRect.top + clockSize.cy;
\r
3140 whiteRect.left = blackRect.left ;
\r
3141 whiteRect.right = blackRect.right;
\r
3142 whiteRect.top = blackRect.bottom;
\r
3143 whiteRect.bottom = leftLogoRect.bottom;
\r
3145 whiteRect.left = OUTER_MARGIN;
\r
3146 whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2;
\r
3147 whiteRect.top = OUTER_MARGIN + logoHeight;
\r
3148 whiteRect.bottom = whiteRect.top + clockSize.cy;
\r
3150 blackRect.left = whiteRect.right + INNER_MARGIN;
\r
3151 blackRect.right = blackRect.left + boardWidth/2 - 1;
\r
3152 blackRect.top = whiteRect.top;
\r
3153 blackRect.bottom = whiteRect.bottom;
\r
3156 messageRect.left = OUTER_MARGIN + MESSAGE_LINE_LEFTMARGIN;
\r
3157 if (appData.showButtonBar) {
\r
3158 messageRect.right = OUTER_MARGIN + boardWidth // [HGM] logo: expressed independent of clock placement
\r
3159 - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN;
\r
3161 messageRect.right = OUTER_MARGIN + boardWidth;
\r
3163 messageRect.top = whiteRect.bottom + INNER_MARGIN;
\r
3164 messageRect.bottom = messageRect.top + messageSize.cy;
\r
3166 boardRect.left = OUTER_MARGIN;
\r
3167 boardRect.right = boardRect.left + boardWidth;
\r
3168 boardRect.top = messageRect.bottom + INNER_MARGIN;
\r
3169 boardRect.bottom = boardRect.top + boardHeight;
\r
3171 sizeInfo[boardSize].cliWidth = boardRect.right + OUTER_MARGIN;
\r
3172 sizeInfo[boardSize].cliHeight = boardRect.bottom + OUTER_MARGIN;
\r
3173 if(suppressVisibleEffects) return; // [HGM] when called for filling sizeInfo only
\r
3174 winWidth = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN;
\r
3175 winHeight = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) +
\r
3176 GetSystemMetrics(SM_CYCAPTION) + boardRect.bottom + OUTER_MARGIN;
\r
3177 GetWindowRect(hwndMain, &wrect);
\r
3178 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3179 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3180 /* compensate if menu bar wrapped */
\r
3181 GetClientRect(hwndMain, &crect);
\r
3182 offby = boardRect.bottom + OUTER_MARGIN - crect.bottom;
\r
3183 winHeight += offby;
\r
3185 case WMSZ_TOPLEFT:
\r
3186 SetWindowPos(hwndMain, NULL,
\r
3187 wrect.right - winWidth, wrect.bottom - winHeight,
\r
3188 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3191 case WMSZ_TOPRIGHT:
\r
3193 SetWindowPos(hwndMain, NULL,
\r
3194 wrect.left, wrect.bottom - winHeight,
\r
3195 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3198 case WMSZ_BOTTOMLEFT:
\r
3200 SetWindowPos(hwndMain, NULL,
\r
3201 wrect.right - winWidth, wrect.top,
\r
3202 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3205 case WMSZ_BOTTOMRIGHT:
\r
3209 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3210 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3215 for (i = 0; i < N_BUTTONS; i++) {
\r
3216 if (buttonDesc[i].hwnd != NULL) {
\r
3217 DestroyWindow(buttonDesc[i].hwnd);
\r
3218 buttonDesc[i].hwnd = NULL;
\r
3220 if (appData.showButtonBar) {
\r
3221 buttonDesc[i].hwnd =
\r
3222 CreateWindow("BUTTON", buttonDesc[i].label,
\r
3223 WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
\r
3224 boardRect.right - BUTTON_WIDTH*(N_BUTTONS-i),
\r
3225 messageRect.top, BUTTON_WIDTH, messageSize.cy, hwndMain,
\r
3226 (HMENU) buttonDesc[i].id,
\r
3227 (HINSTANCE) GetWindowLong(hwndMain, GWL_HINSTANCE), NULL);
\r
3229 SendMessage(buttonDesc[i].hwnd, WM_SETFONT,
\r
3230 (WPARAM)font[boardSize][MESSAGE_FONT]->hf,
\r
3231 MAKELPARAM(FALSE, 0));
\r
3233 if (buttonDesc[i].id == IDM_Pause)
\r
3234 hwndPause = buttonDesc[i].hwnd;
\r
3235 buttonDesc[i].wndproc = (WNDPROC)
\r
3236 SetWindowLong(buttonDesc[i].hwnd, GWL_WNDPROC, (LONG) ButtonProc);
\r
3239 if (gridPen != NULL) DeleteObject(gridPen);
\r
3240 if (highlightPen != NULL) DeleteObject(highlightPen);
\r
3241 if (premovePen != NULL) DeleteObject(premovePen);
\r
3242 if (lineGap != 0) {
\r
3243 logbrush.lbStyle = BS_SOLID;
\r
3244 logbrush.lbColor = RGB(0, 0, 0); /* grid pen color = black */
\r
3246 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3247 lineGap, &logbrush, 0, NULL);
\r
3248 logbrush.lbColor = highlightSquareColor;
\r
3250 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3251 lineGap, &logbrush, 0, NULL);
\r
3253 logbrush.lbColor = premoveHighlightColor;
\r
3255 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3256 lineGap, &logbrush, 0, NULL);
\r
3258 /* [HGM] Loop had to be split in part for vert. and hor. lines */
\r
3259 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
\r
3260 gridEndpoints[i*2].x = boardRect.left + lineGap / 2;
\r
3261 gridEndpoints[i*2].y = gridEndpoints[i*2 + 1].y =
\r
3262 boardRect.top + lineGap / 2 + (i * (squareSize + lineGap));
\r
3263 gridEndpoints[i*2 + 1].x = boardRect.left + lineGap / 2 +
\r
3264 BOARD_WIDTH * (squareSize + lineGap);
\r
3265 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3267 for (i = 0; i < BOARD_WIDTH + 1; i++) {
\r
3268 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].y = boardRect.top + lineGap / 2;
\r
3269 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].x =
\r
3270 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].x = boardRect.left +
\r
3271 lineGap / 2 + (i * (squareSize + lineGap));
\r
3272 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].y =
\r
3273 boardRect.top + BOARD_HEIGHT * (squareSize + lineGap);
\r
3274 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3278 /* [HGM] Licensing requirement */
\r
3280 if(gameInfo.variant == VariantGothic) GothicPopUp( GOTHIC, VariantGothic); else
\r
3283 if(gameInfo.variant == VariantFalcon) GothicPopUp( FALCON, VariantFalcon); else
\r
3285 GothicPopUp( "", VariantNormal);
\r
3288 /* if (boardSize == oldBoardSize) return; [HGM] variant might have changed */
\r
3289 oldBoardSize = boardSize;
\r
3290 oldTinyLayout = tinyLayout;
\r
3292 /* Load piece bitmaps for this board size */
\r
3293 for (i=0; i<=2; i++) {
\r
3294 for (piece = WhitePawn;
\r
3295 (int) piece < (int) BlackPawn;
\r
3296 piece = (ChessSquare) ((int) piece + 1)) {
\r
3297 if (pieceBitmap[i][piece] != NULL)
\r
3298 DeleteObject(pieceBitmap[i][piece]);
\r
3302 fontBitmapSquareSize = 0; /* [HGM] render: make sure pieces will be recreated, as we might need others now */
\r
3303 // Orthodox Chess pieces
\r
3304 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s");
\r
3305 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s");
\r
3306 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "s");
\r
3307 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "s");
\r
3308 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "s");
\r
3309 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "o");
\r
3310 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "o");
\r
3311 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "o");
\r
3312 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "o");
\r
3313 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "o");
\r
3314 pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "w");
\r
3315 pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "w");
\r
3316 pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "w");
\r
3317 pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w");
\r
3318 pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w");
\r
3319 if( !strcmp(appData.variant, "shogi") && (squareSize==72 || squareSize==49)) {
\r
3320 // in Shogi, Hijack the unused Queen for Lance
\r
3321 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3322 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3323 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3325 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s");
\r
3326 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o");
\r
3327 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w");
\r
3330 if(squareSize <= 72 && squareSize >= 33) {
\r
3331 /* A & C are available in most sizes now */
\r
3332 if(squareSize != 49 && squareSize != 72 && squareSize != 33) { // Vortex-like
\r
3333 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3334 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3335 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3336 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3337 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3338 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3339 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3340 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3341 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3342 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3343 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3344 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3345 } else { // Smirf-like
\r
3346 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "s");
\r
3347 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "o");
\r
3348 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "w");
\r
3350 if(gameInfo.variant == VariantGothic) { // Vortex-like
\r
3351 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3352 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3353 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3354 } else { // WinBoard standard
\r
3355 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s");
\r
3356 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o");
\r
3357 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "w");
\r
3362 if(squareSize==72 || squareSize==49 || squareSize==33) { /* experiment with some home-made bitmaps */
\r
3363 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "s");
\r
3364 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "o");
\r
3365 pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "w");
\r
3366 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "s");
\r
3367 pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "o");
\r
3368 pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3369 pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "s");
\r
3370 pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "o");
\r
3371 pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "w");
\r
3372 pieceBitmap[0][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "s");
\r
3373 pieceBitmap[1][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "o");
\r
3374 pieceBitmap[2][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "w");
\r
3375 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3376 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3377 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3378 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "s");
\r
3379 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "o");
\r
3380 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "w");
\r
3381 pieceBitmap[0][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "s");
\r
3382 pieceBitmap[1][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "o");
\r
3383 pieceBitmap[2][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "w");
\r
3384 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "s");
\r
3385 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "o");
\r
3386 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "w");
\r
3387 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3388 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3389 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3390 pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s");
\r
3391 pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o");
\r
3392 pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w");
\r
3394 if(gameInfo.variant == VariantShogi) { /* promoted Gold represemtations */
\r
3395 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s");
\r
3396 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "o");
\r
3397 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3398 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "s");
\r
3399 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "o");
\r
3400 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3401 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "s");
\r
3402 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "o");
\r
3403 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3404 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "s");
\r
3405 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "o");
\r
3406 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3408 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "s");
\r
3409 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "o");
\r
3410 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "w");
\r
3411 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "s");
\r
3412 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "o");
\r
3413 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "w");
\r
3414 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3415 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3416 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3417 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "s");
\r
3418 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "o");
\r
3419 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "w");
\r
3422 } else { /* other size, no special bitmaps available. Use smaller symbols */
\r
3423 if((int)boardSize < 2) minorSize = sizeInfo[0].squareSize;
\r
3424 else minorSize = sizeInfo[(int)boardSize - 2].squareSize;
\r
3425 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "s");
\r
3426 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "o");
\r
3427 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "w");
\r
3428 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "s");
\r
3429 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "o");
\r
3430 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "w");
\r
3431 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "s");
\r
3432 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "o");
\r
3433 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "w");
\r
3434 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "s");
\r
3435 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "o");
\r
3436 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "w");
\r
3440 if(gameInfo.variant == VariantShogi && squareSize == 58)
\r
3441 /* special Shogi support in this size */
\r
3442 { for (i=0; i<=2; i++) { /* replace all bitmaps */
\r
3443 for (piece = WhitePawn;
\r
3444 (int) piece < (int) BlackPawn;
\r
3445 piece = (ChessSquare) ((int) piece + 1)) {
\r
3446 if (pieceBitmap[i][piece] != NULL)
\r
3447 DeleteObject(pieceBitmap[i][piece]);
\r
3450 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3451 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3452 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3453 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3454 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3455 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3456 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r
3457 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");
\r
3458 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");
\r
3459 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");
\r
3460 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");
\r
3461 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");
\r
3462 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");
\r
3463 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");
\r
3464 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3465 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3466 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3467 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3468 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3469 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3470 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r
3471 pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");
\r
3472 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");
\r
3473 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");
\r
3474 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");
\r
3475 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");
\r
3476 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");
\r
3477 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");
\r
3478 pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "w");
\r
3479 pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "w");
\r
3480 pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3481 pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3482 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "w");
\r
3483 pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "w");
\r
3484 pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3485 pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3486 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "sp", squareSize, "w");
\r
3487 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "sn", squareSize, "w");
\r
3488 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3489 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3490 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "sl", squareSize, "w");
\r
3491 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3497 PieceBitmap(ChessSquare p, int kind)
\r
3499 if ((int) p >= (int) BlackPawn)
\r
3500 p = (ChessSquare) ((int) p - (int) BlackPawn + (int) WhitePawn);
\r
3502 return pieceBitmap[kind][(int) p];
\r
3505 /***************************************************************/
\r
3507 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
\r
3508 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
\r
3510 #define MIN3(a,b,c) (((a) < (b) && (a) < (c)) ? (a) : (((b) < (a) && (b) < (c)) ? (b) : (c)))
\r
3511 #define MAX3(a,b,c) (((a) > (b) && (a) > (c)) ? (a) : (((b) > (a) && (b) > (c)) ? (b) : (c)))
\r
3515 SquareToPos(int row, int column, int * x, int * y)
\r
3518 *x = boardRect.left + lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
\r
3519 *y = boardRect.top + lineGap + row * (squareSize + lineGap);
\r
3521 *x = boardRect.left + lineGap + column * (squareSize + lineGap);
\r
3522 *y = boardRect.top + lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
\r
3527 DrawCoordsOnDC(HDC hdc)
\r
3529 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
3530 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
3531 char str[2] = { NULLCHAR, NULLCHAR };
\r
3532 int oldMode, oldAlign, x, y, start, i;
\r
3536 if (!appData.showCoords)
\r
3539 start = flipView ? 1-(ONE!='1') : 23+(ONE!='1')-BOARD_HEIGHT;
\r
3541 oldBrush = SelectObject(hdc, GetStockObject(BLACK_BRUSH));
\r
3542 oldMode = SetBkMode(hdc, (appData.monoMode ? OPAQUE : TRANSPARENT));
\r
3543 oldAlign = GetTextAlign(hdc);
\r
3544 oldFont = SelectObject(hdc, font[boardSize][COORD_FONT]->hf);
\r
3546 y = boardRect.top + lineGap;
\r
3547 x = boardRect.left + lineGap + gameInfo.holdingsWidth*(squareSize + lineGap);
\r
3549 SetTextAlign(hdc, TA_LEFT|TA_TOP);
\r
3550 for (i = 0; i < BOARD_HEIGHT; i++) {
\r
3551 str[0] = files[start + i];
\r
3552 ExtTextOut(hdc, x + 2, y + 1, 0, NULL, str, 1, NULL);
\r
3553 y += squareSize + lineGap;
\r
3556 start = flipView ? 12-(BOARD_RGHT-BOARD_LEFT) : 12;
\r
3558 SetTextAlign(hdc, TA_RIGHT|TA_BOTTOM);
\r
3559 for (i = 0; i < BOARD_RGHT - BOARD_LEFT; i++) {
\r
3560 str[0] = ranks[start + i];
\r
3561 ExtTextOut(hdc, x + squareSize - 2, y - 1, 0, NULL, str, 1, NULL);
\r
3562 x += squareSize + lineGap;
\r
3565 SelectObject(hdc, oldBrush);
\r
3566 SetBkMode(hdc, oldMode);
\r
3567 SetTextAlign(hdc, oldAlign);
\r
3568 SelectObject(hdc, oldFont);
\r
3572 DrawGridOnDC(HDC hdc)
\r
3576 if (lineGap != 0) {
\r
3577 oldPen = SelectObject(hdc, gridPen);
\r
3578 PolyPolyline(hdc, gridEndpoints, gridVertexCounts, BOARD_WIDTH+BOARD_HEIGHT + 2);
\r
3579 SelectObject(hdc, oldPen);
\r
3583 #define HIGHLIGHT_PEN 0
\r
3584 #define PREMOVE_PEN 1
\r
3587 DrawHighlightOnDC(HDC hdc, BOOLEAN on, int x, int y, int pen)
\r
3590 HPEN oldPen, hPen;
\r
3591 if (lineGap == 0) return;
\r
3593 x1 = boardRect.left +
\r
3594 lineGap/2 + ((BOARD_WIDTH-1)-x) * (squareSize + lineGap);
\r
3595 y1 = boardRect.top +
\r
3596 lineGap/2 + y * (squareSize + lineGap);
\r
3598 x1 = boardRect.left +
\r
3599 lineGap/2 + x * (squareSize + lineGap);
\r
3600 y1 = boardRect.top +
\r
3601 lineGap/2 + ((BOARD_HEIGHT-1)-y) * (squareSize + lineGap);
\r
3603 hPen = pen ? premovePen : highlightPen;
\r
3604 oldPen = SelectObject(hdc, on ? hPen : gridPen);
\r
3605 MoveToEx(hdc, x1, y1, NULL);
\r
3606 LineTo(hdc, x1 + squareSize + lineGap, y1);
\r
3607 LineTo(hdc, x1 + squareSize + lineGap, y1 + squareSize + lineGap);
\r
3608 LineTo(hdc, x1, y1 + squareSize + lineGap);
\r
3609 LineTo(hdc, x1, y1);
\r
3610 SelectObject(hdc, oldPen);
\r
3614 DrawHighlightsOnDC(HDC hdc)
\r
3617 for (i=0; i<2; i++) {
\r
3618 if (highlightInfo.sq[i].x >= 0 && highlightInfo.sq[i].y >= 0)
\r
3619 DrawHighlightOnDC(hdc, TRUE,
\r
3620 highlightInfo.sq[i].x, highlightInfo.sq[i].y,
\r
3623 for (i=0; i<2; i++) {
\r
3624 if (premoveHighlightInfo.sq[i].x >= 0 &&
\r
3625 premoveHighlightInfo.sq[i].y >= 0) {
\r
3626 DrawHighlightOnDC(hdc, TRUE,
\r
3627 premoveHighlightInfo.sq[i].x,
\r
3628 premoveHighlightInfo.sq[i].y,
\r
3634 /* Note: sqcolor is used only in monoMode */
\r
3635 /* Note that this code is largely duplicated in woptions.c,
\r
3636 function DrawSampleSquare, so that needs to be updated too */
\r
3638 DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, HDC tmphdc)
\r
3640 HBITMAP oldBitmap;
\r
3644 if (appData.blindfold) return;
\r
3646 /* [AS] Use font-based pieces if needed */
\r
3647 if( fontBitmapSquareSize >= 0 && squareSize > 32 ) {
\r
3648 /* Create piece bitmaps, or do nothing if piece set is up to date */
\r
3649 CreatePiecesFromFont();
\r
3651 if( fontBitmapSquareSize == squareSize ) {
\r
3652 int index = TranslatePieceToFontPiece(piece);
\r
3654 SelectObject( tmphdc, hPieceMask[ index ] );
\r