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, Massachusetts.
\r
6 * Enhancements Copyright 1992-2001 Free Software Foundation, Inc.
\r
8 * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,
\r
9 * which was written and is copyrighted by Wayne Christopher.
\r
11 * The following terms apply to Digital Equipment Corporation's copyright
\r
12 * interest in XBoard:
\r
13 * ------------------------------------------------------------------------
\r
14 * All Rights Reserved
\r
16 * Permission to use, copy, modify, and distribute this software and its
\r
17 * documentation for any purpose and without fee is hereby granted,
\r
18 * provided that the above copyright notice appear in all copies and that
\r
19 * both that copyright notice and this permission notice appear in
\r
20 * supporting documentation, and that the name of Digital not be
\r
21 * used in advertising or publicity pertaining to distribution of the
\r
22 * software without specific, written prior permission.
\r
24 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
\r
25 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
\r
26 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
\r
27 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
\r
28 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
\r
29 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
\r
31 * ------------------------------------------------------------------------
\r
33 * The following terms apply to the enhanced version of XBoard distributed
\r
34 * by the Free Software Foundation:
\r
35 * ------------------------------------------------------------------------
\r
36 * This program is free software; you can redistribute it and/or modify
\r
37 * it under the terms of the GNU General Public License as published by
\r
38 * the Free Software Foundation; either version 2 of the License, or
\r
39 * (at your option) any later version.
\r
41 * This program is distributed in the hope that it will be useful,
\r
42 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
44 * GNU General Public License for more details.
\r
46 * You should have received a copy of the GNU General Public License
\r
47 * along with this program; if not, write to the Free Software
\r
48 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
\r
49 * ------------------------------------------------------------------------
\r
54 #include <windows.h>
\r
55 #include <winuser.h>
\r
56 #include <winsock.h>
\r
62 #include <sys/stat.h>
\r
65 #include <commdlg.h>
\r
67 #include <richedit.h>
\r
68 #include <mmsystem.h>
\r
76 #include "winboard.h"
\r
77 #include "frontend.h"
\r
78 #include "backend.h"
\r
80 #include "wclipbrd.h"
\r
81 #include "wgamelist.h"
\r
82 #include "wedittags.h"
\r
83 #include "woptions.h"
\r
84 #include "wsockerr.h"
\r
85 #include "defaults.h"
\r
89 //void InitEngineUCI( const char * iniDir, ChessProgramState * cps );
\r
92 void mysrandom(unsigned int seed);
\r
94 extern int whiteFlag, blackFlag;
\r
95 Boolean flipClock = FALSE;
\r
97 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);
\r
100 ChessSquare piece;
\r
101 POINT pos; /* window coordinates of current pos */
\r
102 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
103 POINT from; /* board coordinates of the piece's orig pos */
\r
104 POINT to; /* board coordinates of the piece's new pos */
\r
107 static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };
\r
110 POINT start; /* window coordinates of start pos */
\r
111 POINT pos; /* window coordinates of current pos */
\r
112 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
113 POINT from; /* board coordinates of the piece's orig pos */
\r
116 static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} };
\r
119 POINT sq[2]; /* board coordinates of from, to squares */
\r
122 static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} };
\r
123 static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };
\r
125 /* Window class names */
\r
126 char szAppName[] = "WinBoard";
\r
127 char szConsoleName[] = "WBConsole";
\r
129 /* Title bar text */
\r
130 char szTitle[] = "WinBoard";
\r
131 char szConsoleTitle[] = "ICS Interaction";
\r
134 char *settingsFileName;
\r
135 BOOLEAN saveSettingsOnExit;
\r
136 char installDir[MSG_SIZ];
\r
138 BoardSize boardSize;
\r
139 BOOLEAN chessProgram;
\r
140 static int boardX, boardY, consoleX, consoleY, consoleW, consoleH;
\r
141 static int squareSize, lineGap, minorSize;
\r
142 static int winWidth, winHeight;
\r
143 static RECT messageRect, whiteRect, blackRect;
\r
144 static char messageText[MESSAGE_TEXT_MAX];
\r
145 static int clockTimerEvent = 0;
\r
146 static int loadGameTimerEvent = 0;
\r
147 static int analysisTimerEvent = 0;
\r
148 static DelayedEventCallback delayedTimerCallback;
\r
149 static int delayedTimerEvent = 0;
\r
150 static int buttonCount = 2;
\r
151 char *icsTextMenuString;
\r
153 char *firstChessProgramNames;
\r
154 char *secondChessProgramNames;
\r
156 #define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */
\r
158 #define PALETTESIZE 256
\r
160 HINSTANCE hInst; /* current instance */
\r
161 HWND hwndMain = NULL; /* root window*/
\r
162 HWND hwndConsole = NULL;
\r
163 BOOLEAN alwaysOnTop = FALSE;
\r
165 COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
\r
166 blackPieceColor, highlightSquareColor, premoveHighlightColor;
\r
168 ColorClass currentColorClass;
\r
170 HWND hCommPort = NULL; /* currently open comm port */
\r
171 static HWND hwndPause; /* pause button */
\r
172 static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */
\r
173 static HBRUSH lightSquareBrush, darkSquareBrush,
\r
174 blackSquareBrush, /* [HGM] for band between board and holdings */
\r
175 whitePieceBrush, blackPieceBrush, iconBkgndBrush, outlineBrush;
\r
176 static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];
\r
177 static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];
\r
178 static HPEN gridPen = NULL;
\r
179 static HPEN highlightPen = NULL;
\r
180 static HPEN premovePen = NULL;
\r
181 static NPLOGPALETTE pLogPal;
\r
182 static BOOL paletteChanged = FALSE;
\r
183 static HICON iconWhite, iconBlack, iconCurrent;
\r
184 static int doingSizing = FALSE;
\r
185 static int lastSizing = 0;
\r
186 static int prevStderrPort;
\r
188 /* [AS] Support for background textures */
\r
189 #define BACK_TEXTURE_MODE_DISABLED 0
\r
190 #define BACK_TEXTURE_MODE_PLAIN 1
\r
191 #define BACK_TEXTURE_MODE_FULL_RANDOM 2
\r
193 static HBITMAP liteBackTexture = NULL;
\r
194 static HBITMAP darkBackTexture = NULL;
\r
195 static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
196 static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
197 static int backTextureSquareSize = 0;
\r
198 static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_SIZE][BOARD_SIZE];
\r
200 #if __GNUC__ && !defined(_winmajor)
\r
201 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */
\r
203 #define oldDialog (_winmajor < 4)
\r
206 char *defaultTextAttribs[] =
\r
208 COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,
\r
209 COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,
\r
219 int cliWidth, cliHeight;
\r
222 SizeInfo sizeInfo[] =
\r
224 { "tiny", 21, 0, 1, 1, 0, 0 },
\r
225 { "teeny", 25, 1, 1, 1, 0, 0 },
\r
226 { "dinky", 29, 1, 1, 1, 0, 0 },
\r
227 { "petite", 33, 1, 1, 1, 0, 0 },
\r
228 { "slim", 37, 2, 1, 0, 0, 0 },
\r
229 { "small", 40, 2, 1, 0, 0, 0 },
\r
230 { "mediocre", 45, 2, 1, 0, 0, 0 },
\r
231 { "middling", 49, 2, 0, 0, 0, 0 },
\r
232 { "average", 54, 2, 0, 0, 0, 0 },
\r
233 { "moderate", 58, 3, 0, 0, 0, 0 },
\r
234 { "medium", 64, 3, 0, 0, 0, 0 },
\r
235 { "bulky", 72, 3, 0, 0, 0, 0 },
\r
236 { "large", 80, 3, 0, 0, 0, 0 },
\r
237 { "big", 87, 3, 0, 0, 0, 0 },
\r
238 { "huge", 95, 3, 0, 0, 0, 0 },
\r
239 { "giant", 108, 3, 0, 0, 0, 0 },
\r
240 { "colossal", 116, 4, 0, 0, 0, 0 },
\r
241 { "titanic", 129, 4, 0, 0, 0, 0 },
\r
242 { NULL, 0, 0, 0, 0, 0, 0 }
\r
245 #define MF(x) {x, {0, }, {0, }, 0}
\r
246 MyFont fontRec[NUM_SIZES][NUM_FONTS] =
\r
248 { 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
249 { 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
250 { 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
251 { 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
252 { 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
253 { 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
254 { 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
255 { 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
256 { 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
257 { 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
258 { 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
259 { 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
260 { 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
261 { 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
262 { 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
263 { 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
264 { 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
265 { 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
268 MyFont *font[NUM_SIZES][NUM_FONTS];
\r
277 #define BUTTON_WIDTH (tinyLayout ? 16 : 32)
\r
278 #define N_BUTTONS 5
\r
280 MyButtonDesc buttonDesc[N_BUTTONS] =
\r
282 {"<<", IDM_ToStart, NULL, NULL},
\r
283 {"<", IDM_Backward, NULL, NULL},
\r
284 {"P", IDM_Pause, NULL, NULL},
\r
285 {">", IDM_Forward, NULL, NULL},
\r
286 {">>", IDM_ToEnd, NULL, NULL},
\r
289 int tinyLayout = 0, smallLayout = 0;
\r
290 #define MENU_BAR_ITEMS 6
\r
291 char *menuBarText[2][MENU_BAR_ITEMS+1] = {
\r
292 { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },
\r
293 { "&F", "&M", "&A", "&S", "&O", "&H", NULL },
\r
297 MySound sounds[(int)NSoundClasses];
\r
298 MyTextAttribs textAttribs[(int)NColorClasses];
\r
300 MyColorizeAttribs colorizeAttribs[] = {
\r
301 { (COLORREF)0, 0, "Shout Text" },
\r
302 { (COLORREF)0, 0, "SShout/CShout" },
\r
303 { (COLORREF)0, 0, "Channel 1 Text" },
\r
304 { (COLORREF)0, 0, "Channel Text" },
\r
305 { (COLORREF)0, 0, "Kibitz Text" },
\r
306 { (COLORREF)0, 0, "Tell Text" },
\r
307 { (COLORREF)0, 0, "Challenge Text" },
\r
308 { (COLORREF)0, 0, "Request Text" },
\r
309 { (COLORREF)0, 0, "Seek Text" },
\r
310 { (COLORREF)0, 0, "Normal Text" },
\r
311 { (COLORREF)0, 0, "None" }
\r
316 static char *commentTitle;
\r
317 static char *commentText;
\r
318 static int commentIndex;
\r
319 static Boolean editComment = FALSE;
\r
320 HWND commentDialog = NULL;
\r
321 BOOLEAN commentDialogUp = FALSE;
\r
322 static int commentX, commentY, commentH, commentW;
\r
324 static char *analysisTitle;
\r
325 static char *analysisText;
\r
326 HWND analysisDialog = NULL;
\r
327 BOOLEAN analysisDialogUp = FALSE;
\r
328 static int analysisX, analysisY, analysisH, analysisW;
\r
330 char errorTitle[MSG_SIZ];
\r
331 char errorMessage[2*MSG_SIZ];
\r
332 HWND errorDialog = NULL;
\r
333 BOOLEAN moveErrorMessageUp = FALSE;
\r
334 BOOLEAN consoleEcho = TRUE;
\r
335 CHARFORMAT consoleCF;
\r
336 COLORREF consoleBackgroundColor;
\r
338 char *programVersion;
\r
344 typedef int CPKind;
\r
353 SOCKET sock2; /* stderr socket for OpenRcmd */
\r
356 #define INPUT_SOURCE_BUF_SIZE 4096
\r
358 typedef struct _InputSource {
\r
365 char buf[INPUT_SOURCE_BUF_SIZE];
\r
369 InputCallback func;
\r
370 struct _InputSource *second; /* for stderr thread on CPRcmd */
\r
374 InputSource *consoleInputSource;
\r
379 VOID ConsoleOutput(char* data, int length, int forceVisible);
\r
380 VOID ConsoleCreate();
\r
382 ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
383 VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
\r
384 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
\r
385 VOID ParseCommSettings(char *arg, DCB *dcb);
\r
387 StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
388 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
\r
389 void ParseIcsTextMenu(char *icsTextMenuString);
\r
390 VOID PopUpMoveDialog(char firstchar);
\r
391 VOID PopUpNameDialog(char firstchar);
\r
392 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
\r
396 int GameListOptions();
\r
398 HWND moveHistoryDialog = NULL;
\r
399 BOOLEAN moveHistoryDialogUp = FALSE;
\r
401 WindowPlacement wpMoveHistory;
\r
403 HWND evalGraphDialog = NULL;
\r
404 BOOLEAN evalGraphDialogUp = FALSE;
\r
406 WindowPlacement wpEvalGraph;
\r
408 HWND engineOutputDialog = NULL;
\r
409 BOOLEAN engineOutputDialogUp = FALSE;
\r
411 WindowPlacement wpEngineOutput;
\r
413 VOID MoveHistoryPopUp();
\r
414 VOID MoveHistoryPopDown();
\r
415 VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
416 BOOL MoveHistoryIsUp();
\r
418 VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
419 VOID EvalGraphPopUp();
\r
420 VOID EvalGraphPopDown();
\r
421 BOOL EvalGraphIsUp();
\r
423 VOID EngineOutputPopUp();
\r
424 VOID EngineOutputPopDown();
\r
425 BOOL EngineOutputIsUp();
\r
426 VOID EngineOutputUpdate( FrontEndProgramStats * stats );
\r
428 VOID GothicPopUp(char *title, VariantClass variant);
\r
430 * Setting "frozen" should disable all user input other than deleting
\r
431 * the window. We do this while engines are initializing themselves.
\r
433 static int frozen = 0;
\r
434 static int oldMenuItemState[MENU_BAR_ITEMS];
\r
440 if (frozen) return;
\r
442 hmenu = GetMenu(hwndMain);
\r
443 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
444 oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
\r
446 DrawMenuBar(hwndMain);
\r
449 /* Undo a FreezeUI */
\r
455 if (!frozen) return;
\r
457 hmenu = GetMenu(hwndMain);
\r
458 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
459 EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
\r
461 DrawMenuBar(hwndMain);
\r
464 /*---------------------------------------------------------------------------*\
\r
468 \*---------------------------------------------------------------------------*/
\r
471 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
\r
472 LPSTR lpCmdLine, int nCmdShow)
\r
475 HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
\r
479 LoadLibrary("RICHED32.DLL");
\r
480 consoleCF.cbSize = sizeof(CHARFORMAT);
\r
482 if (!InitApplication(hInstance)) {
\r
485 if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
\r
489 hAccelMain = LoadAccelerators (hInstance, szAppName);
\r
490 hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
\r
491 hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
\r
493 /* Acquire and dispatch messages until a WM_QUIT message is received. */
\r
495 while (GetMessage(&msg, /* message structure */
\r
496 NULL, /* handle of window receiving the message */
\r
497 0, /* lowest message to examine */
\r
498 0)) /* highest message to examine */
\r
500 if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
\r
501 !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
\r
502 !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
\r
503 !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
\r
504 !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
\r
505 !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
\r
506 !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
\r
507 !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) &&
\r
508 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
\r
509 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
\r
510 TranslateMessage(&msg); /* Translates virtual key codes */
\r
511 DispatchMessage(&msg); /* Dispatches message to window */
\r
516 return (msg.wParam); /* Returns the value from PostQuitMessage */
\r
519 /*---------------------------------------------------------------------------*\
\r
521 * Initialization functions
\r
523 \*---------------------------------------------------------------------------*/
\r
526 InitApplication(HINSTANCE hInstance)
\r
530 /* Fill in window class structure with parameters that describe the */
\r
533 wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
\r
534 wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
\r
535 wc.cbClsExtra = 0; /* No per-class extra data. */
\r
536 wc.cbWndExtra = 0; /* No per-window extra data. */
\r
537 wc.hInstance = hInstance; /* Owner of this class */
\r
538 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
539 wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
\r
540 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
\r
541 wc.lpszMenuName = szAppName; /* Menu name from .RC */
\r
542 wc.lpszClassName = szAppName; /* Name to register as */
\r
544 /* Register the window class and return success/failure code. */
\r
545 if (!RegisterClass(&wc)) return FALSE;
\r
547 wc.style = CS_HREDRAW | CS_VREDRAW;
\r
548 wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
\r
550 wc.cbWndExtra = DLGWINDOWEXTRA;
\r
551 wc.hInstance = hInstance;
\r
552 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
553 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
\r
554 wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
\r
555 wc.lpszMenuName = NULL;
\r
556 wc.lpszClassName = szConsoleName;
\r
558 if (!RegisterClass(&wc)) return FALSE;
\r
563 /* Set by InitInstance, used by EnsureOnScreen */
\r
564 int screenHeight, screenWidth;
\r
567 EnsureOnScreen(int *x, int *y)
\r
569 int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
\r
570 /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
\r
571 if (*x > screenWidth - 32) *x = 0;
\r
572 if (*y > screenHeight - 32) *y = 0;
\r
573 if (*x < 10) *x = 10;
\r
574 if (*y < gap) *y = gap;
\r
578 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
\r
580 HWND hwnd; /* Main window handle. */
\r
582 WINDOWPLACEMENT wp;
\r
585 hInst = hInstance; /* Store instance handle in our global variable */
\r
587 if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
\r
588 *filepart = NULLCHAR;
\r
590 GetCurrentDirectory(MSG_SIZ, installDir);
\r
592 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise
\r
593 InitAppData(lpCmdLine); /* Get run-time parameters */
\r
594 if (appData.debugMode) {
\r
595 debugFP = fopen(appData.nameOfDebugFile, "w");
\r
596 setbuf(debugFP, NULL);
\r
601 // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()
\r
602 // InitEngineUCI( installDir, &second );
\r
604 /* Create a main window for this application instance. */
\r
605 hwnd = CreateWindow(szAppName, szTitle,
\r
606 (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
\r
607 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
\r
608 NULL, NULL, hInstance, NULL);
\r
611 /* If window could not be created, return "failure" */
\r
616 iconWhite = LoadIcon(hInstance, "icon_white");
\r
617 iconBlack = LoadIcon(hInstance, "icon_black");
\r
618 iconCurrent = iconWhite;
\r
619 InitDrawingColors();
\r
620 screenHeight = GetSystemMetrics(SM_CYSCREEN);
\r
621 screenWidth = GetSystemMetrics(SM_CXSCREEN);
\r
622 for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
\r
623 /* Compute window size for each board size, and use the largest
\r
624 size that fits on this screen as the default. */
\r
625 InitDrawingSizes((BoardSize)ibs, 0);
\r
626 if (boardSize == (BoardSize)-1 &&
\r
627 winHeight <= screenHeight
\r
628 - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10
\r
629 && winWidth <= screenWidth) {
\r
630 boardSize = (BoardSize)ibs;
\r
633 InitDrawingSizes(boardSize, 0);
\r
635 buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
\r
637 /* [AS] Load textures if specified */
\r
638 ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );
\r
640 if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {
\r
641 liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
642 liteBackTextureMode = appData.liteBackTextureMode;
\r
644 if (liteBackTexture == NULL && appData.debugMode) {
\r
645 fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );
\r
649 if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {
\r
650 darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
651 darkBackTextureMode = appData.darkBackTextureMode;
\r
653 if (darkBackTexture == NULL && appData.debugMode) {
\r
654 fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );
\r
658 mysrandom( (unsigned) time(NULL) );
\r
660 /* Make a console window if needed */
\r
661 if (appData.icsActive) {
\r
665 /* [AS] Restore layout */
\r
666 if( wpMoveHistory.visible ) {
\r
667 MoveHistoryPopUp();
\r
670 if( wpEvalGraph.visible ) {
\r
674 if( wpEngineOutput.visible ) {
\r
675 EngineOutputPopUp();
\r
680 /* Make the window visible; update its client area; and return "success" */
\r
681 EnsureOnScreen(&boardX, &boardY);
\r
682 wp.length = sizeof(WINDOWPLACEMENT);
\r
684 wp.showCmd = nCmdShow;
\r
685 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
\r
686 wp.rcNormalPosition.left = boardX;
\r
687 wp.rcNormalPosition.right = boardX + winWidth;
\r
688 wp.rcNormalPosition.top = boardY;
\r
689 wp.rcNormalPosition.bottom = boardY + winHeight;
\r
690 SetWindowPlacement(hwndMain, &wp);
\r
692 SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
693 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
696 /* [AS] Disable the FRC stuff if not playing the proper variant */
\r
697 if( gameInfo.variant != VariantFischeRandom ) {
\r
698 EnableMenuItem( GetMenu(hwndMain), IDM_NewGameFRC, MF_GRAYED );
\r
703 SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
704 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
706 ShowWindow(hwndConsole, nCmdShow);
\r
708 UpdateWindow(hwnd);
\r
716 ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
\r
717 ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
\r
718 ArgSettingsFilename
\r
726 String *pString; // ArgString
\r
727 int *pInt; // ArgInt
\r
728 float *pFloat; // ArgFloat
\r
729 Boolean *pBoolean; // ArgBoolean
\r
730 COLORREF *pColor; // ArgColor
\r
731 ColorClass cc; // ArgAttribs
\r
732 String *pFilename; // ArgFilename
\r
733 BoardSize *pBoardSize; // ArgBoardSize
\r
734 int whichFont; // ArgFont
\r
735 DCB *pDCB; // ArgCommSettings
\r
736 String *pFilename; // ArgSettingsFilename
\r
744 ArgDescriptor argDescriptors[] = {
\r
745 /* positional arguments */
\r
746 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
747 { "", ArgNone, NULL },
\r
748 /* keyword arguments */
\r
749 { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },
\r
750 { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },
\r
751 { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },
\r
752 { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },
\r
753 { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },
\r
754 { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },
\r
755 { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },
\r
756 { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },
\r
757 { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },
\r
758 { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },
\r
759 { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },
\r
760 { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },
\r
761 { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },
\r
762 { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },
\r
763 { "initString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
764 { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
765 { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },
\r
766 { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,
\r
768 { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,
\r
770 { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,
\r
772 { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },
\r
773 { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,
\r
775 { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },
\r
776 { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
777 { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
778 { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
779 { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
780 { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },
\r
781 { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },
\r
782 { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
783 { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
784 { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
785 { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
786 { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
787 { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
788 { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
789 { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
790 { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
791 { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
792 /*!!bitmapDirectory?*/
\r
793 { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
794 { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
795 { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
796 { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
797 { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },
\r
798 { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },
\r
799 { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },
\r
800 { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },
\r
801 { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },
\r
802 { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },
\r
803 { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },
\r
804 { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },
\r
805 { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
806 { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
807 { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
808 { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
809 { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
810 { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
811 { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
812 { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
813 { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
814 { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
815 { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
816 { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
817 { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },
\r
818 { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },
\r
819 { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
820 { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
821 { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },
\r
822 { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },
\r
823 { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },
\r
824 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
825 { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
826 { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
827 { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
828 { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },
\r
829 { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },
\r
830 { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },
\r
831 { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },
\r
832 { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
833 { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
834 { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
835 { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
836 { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
837 { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
838 { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
839 { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
840 { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },
\r
841 { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },
\r
842 { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
843 { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
844 { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
845 { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
846 { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },
\r
847 { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },
\r
848 { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
849 { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
850 { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },
\r
851 { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },
\r
852 { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
853 { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
854 { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },
\r
855 { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },
\r
856 { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
857 { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
858 { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
859 { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
860 { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
861 { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
862 { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },
\r
863 { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },
\r
864 { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
865 { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
866 { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },
\r
867 { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },
\r
868 { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
869 { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
870 { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },
\r
871 { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },
\r
872 { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
873 { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
874 { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },
\r
875 { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },
\r
876 { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
877 { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
878 { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },
\r
879 { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },
\r
880 { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
881 { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
882 { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },
\r
883 { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
884 { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
885 { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
886 { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors,
\r
887 FALSE }, /* only so that old WinBoard.ini files from betas can be read */
\r
888 { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },
\r
889 { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },
\r
890 { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },
\r
891 { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },
\r
892 { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },
\r
893 { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },
\r
894 { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE }, /* [AS] */
\r
895 { "boardSize", ArgBoardSize, (LPVOID) &boardSize,
\r
896 TRUE }, /* must come after all fonts */
\r
897 { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },
\r
898 { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,
\r
899 FALSE }, /* historical; kept only so old winboard.ini files will parse */
\r
900 { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },
\r
901 { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },
\r
902 { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
903 { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
904 { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },
\r
905 { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },
\r
906 { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
907 { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
908 { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },
\r
909 { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },
\r
910 { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
911 { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
912 { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },
\r
913 { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },
\r
914 { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
915 { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
916 { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },
\r
917 { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },
\r
918 { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
919 { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
920 { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },
\r
921 { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },
\r
922 { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
923 { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
924 { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },
\r
925 { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
926 { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
927 { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
929 { "cmailGameName", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
930 { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
932 { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },
\r
933 { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
934 { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
935 { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
936 { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },
\r
937 { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
938 { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
939 { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
940 { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },
\r
941 { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },
\r
942 { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
943 { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
944 { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },
\r
945 { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },
\r
946 { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
947 { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
948 { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },
\r
949 { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },
\r
950 { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
951 { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
952 { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },
\r
953 { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },
\r
954 { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
955 { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
956 { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },
\r
957 { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },
\r
958 { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
959 { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
960 { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },
\r
961 { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },
\r
962 { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },
\r
963 { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
964 { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
965 { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },
\r
966 { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},
\r
967 { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},
\r
968 { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
969 { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
970 { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},
\r
971 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
972 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
973 { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },
\r
974 { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
975 { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
976 { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },
\r
977 { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },
\r
978 { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
979 { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
980 { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },
\r
981 { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },
\r
982 { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },
\r
983 { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
984 { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
985 { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },
\r
986 { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },
\r
987 { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
988 { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
989 { "highlightLastMove", ArgBoolean,
\r
990 (LPVOID) &appData.highlightLastMove, TRUE },
\r
991 { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },
\r
992 { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
993 { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
994 { "highlightDragging", ArgBoolean,
\r
995 (LPVOID) &appData.highlightDragging, TRUE },
\r
996 { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },
\r
997 { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
998 { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
999 { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },
\r
1000 { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },
\r
1001 { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1002 { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1003 { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },
\r
1004 { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },
\r
1005 { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },
\r
1006 { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },
\r
1007 { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },
\r
1008 { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },
\r
1009 { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },
\r
1010 { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },
\r
1011 { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },
\r
1012 { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },
\r
1013 { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },
\r
1014 { "soundShout", ArgFilename,
\r
1015 (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },
\r
1016 { "soundSShout", ArgFilename,
\r
1017 (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },
\r
1018 { "soundChannel1", ArgFilename,
\r
1019 (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },
\r
1020 { "soundChannel", ArgFilename,
\r
1021 (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },
\r
1022 { "soundKibitz", ArgFilename,
\r
1023 (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },
\r
1024 { "soundTell", ArgFilename,
\r
1025 (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },
\r
1026 { "soundChallenge", ArgFilename,
\r
1027 (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },
\r
1028 { "soundRequest", ArgFilename,
\r
1029 (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },
\r
1030 { "soundSeek", ArgFilename,
\r
1031 (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },
\r
1032 { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },
\r
1033 { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },
\r
1034 { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },
\r
1035 { "soundIcsLoss", ArgFilename,
\r
1036 (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },
\r
1037 { "soundIcsDraw", ArgFilename,
\r
1038 (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },
\r
1039 { "soundIcsUnfinished", ArgFilename,
\r
1040 (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},
\r
1041 { "soundIcsAlarm", ArgFilename,
\r
1042 (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },
\r
1043 { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },
\r
1044 { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },
\r
1045 { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1046 { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1047 { "reuseChessPrograms", ArgBoolean,
\r
1048 (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */
\r
1049 { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },
\r
1050 { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },
\r
1051 { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1052 { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1053 { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },
\r
1054 { "x", ArgInt, (LPVOID) &boardX, TRUE },
\r
1055 { "y", ArgInt, (LPVOID) &boardY, TRUE },
\r
1056 { "icsX", ArgInt, (LPVOID) &consoleX, TRUE },
\r
1057 { "icsY", ArgInt, (LPVOID) &consoleY, TRUE },
\r
1058 { "icsW", ArgInt, (LPVOID) &consoleW, TRUE },
\r
1059 { "icsH", ArgInt, (LPVOID) &consoleH, TRUE },
\r
1060 { "analysisX", ArgInt, (LPVOID) &analysisX, TRUE },
\r
1061 { "analysisY", ArgInt, (LPVOID) &analysisY, TRUE },
\r
1062 { "analysisW", ArgInt, (LPVOID) &analysisW, TRUE },
\r
1063 { "analysisH", ArgInt, (LPVOID) &analysisH, TRUE },
\r
1064 { "commentX", ArgInt, (LPVOID) &commentX, TRUE },
\r
1065 { "commentY", ArgInt, (LPVOID) &commentY, TRUE },
\r
1066 { "commentW", ArgInt, (LPVOID) &commentW, TRUE },
\r
1067 { "commentH", ArgInt, (LPVOID) &commentH, TRUE },
\r
1068 { "tagsX", ArgInt, (LPVOID) &editTagsX, TRUE },
\r
1069 { "tagsY", ArgInt, (LPVOID) &editTagsY, TRUE },
\r
1070 { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },
\r
1071 { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },
\r
1072 { "gameListX", ArgInt, (LPVOID) &gameListX, TRUE },
\r
1073 { "gameListY", ArgInt, (LPVOID) &gameListY, TRUE },
\r
1074 { "gameListW", ArgInt, (LPVOID) &gameListW, TRUE },
\r
1075 { "gameListH", ArgInt, (LPVOID) &gameListH, TRUE },
\r
1076 { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1077 { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1078 { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },
\r
1079 { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },
\r
1080 { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },
\r
1081 { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1082 { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1083 { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },
\r
1084 { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },
\r
1085 { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,
\r
1087 { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,
\r
1089 { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1090 { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1091 { "variant", ArgString, (LPVOID) &appData.variant, FALSE },
\r
1092 { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion, FALSE },
\r
1093 { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,FALSE },
\r
1094 { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },
\r
1095 { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },
\r
1096 { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1097 { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1098 /* [AS] New features */
\r
1099 { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE },
\r
1100 { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE },
\r
1101 { "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE },
\r
1102 { "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE },
\r
1103 { "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE },
\r
1104 { "darkBackTextureFile", ArgString, (LPVOID) &appData.darkBackTextureFile, TRUE },
\r
1105 { "liteBackTextureMode", ArgInt, (LPVOID) &appData.liteBackTextureMode, TRUE },
\r
1106 { "darkBackTextureMode", ArgInt, (LPVOID) &appData.darkBackTextureMode, TRUE },
\r
1107 { "renderPiecesWithFont", ArgString, (LPVOID) &appData.renderPiecesWithFont, TRUE },
\r
1108 { "fontPieceToCharTable", ArgString, (LPVOID) &appData.fontToPieceTable, TRUE },
\r
1109 { "fontPieceBackColorWhite", ArgColor, (LPVOID) &appData.fontBackColorWhite, TRUE },
\r
1110 { "fontPieceForeColorWhite", ArgColor, (LPVOID) &appData.fontForeColorWhite, TRUE },
\r
1111 { "fontPieceBackColorBlack", ArgColor, (LPVOID) &appData.fontBackColorBlack, TRUE },
\r
1112 { "fontPieceForeColorBlack", ArgColor, (LPVOID) &appData.fontForeColorBlack, TRUE },
\r
1113 { "fontPieceSize", ArgInt, (LPVOID) &appData.fontPieceSize, TRUE },
\r
1114 { "overrideLineGap", ArgInt, (LPVOID) &appData.overrideLineGap, TRUE },
\r
1115 { "adjudicateLossThreshold", ArgInt, (LPVOID) &appData.adjudicateLossThreshold, TRUE },
\r
1116 { "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE },
\r
1117 { "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE },
\r
1118 { "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1119 { "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1120 { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },
\r
1121 { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE },
\r
1122 { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE },
\r
1123 { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE },
\r
1124 { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE },
\r
1125 { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE },
\r
1126 { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE },
\r
1127 { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE },
\r
1128 { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE },
\r
1129 { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE },
\r
1130 { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE },
\r
1131 { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE },
\r
1132 { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE },
\r
1133 { "firstIsUCI", ArgBoolean, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1134 { "fUCI", ArgTrue, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1135 { "secondIsUCI", ArgBoolean, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1136 { "sUCI", ArgTrue, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1137 { "firstHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1138 { "fNoOwnBookUCI", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1139 { "secondHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1140 { "sNoOwnBookUCI", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1141 { "polyglotDir", ArgFilename, (LPVOID) &appData.polyglotDir, TRUE },
\r
1142 { "usePolyglotBook", ArgBoolean, (LPVOID) &appData.usePolyglotBook, TRUE },
\r
1143 { "polyglotBook", ArgFilename, (LPVOID) &appData.polyglotBook, TRUE },
\r
1144 { "defaultHashSize", ArgInt, (LPVOID) &appData.defaultHashSize, TRUE },
\r
1145 { "defaultCacheSizeEGTB", ArgInt, (LPVOID) &appData.defaultCacheSizeEGTB, TRUE },
\r
1146 { "defaultPathEGTB", ArgFilename, (LPVOID) &appData.defaultPathEGTB, TRUE },
\r
1148 /* [AS] Layout stuff */
\r
1149 { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },
\r
1150 { "moveHistoryX", ArgInt, (LPVOID) &wpMoveHistory.x, TRUE },
\r
1151 { "moveHistoryY", ArgInt, (LPVOID) &wpMoveHistory.y, TRUE },
\r
1152 { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },
\r
1153 { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },
\r
1155 { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },
\r
1156 { "evalGraphX", ArgInt, (LPVOID) &wpEvalGraph.x, TRUE },
\r
1157 { "evalGraphY", ArgInt, (LPVOID) &wpEvalGraph.y, TRUE },
\r
1158 { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },
\r
1159 { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },
\r
1161 { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },
\r
1162 { "engineOutputX", ArgInt, (LPVOID) &wpEngineOutput.x, TRUE },
\r
1163 { "engineOutputY", ArgInt, (LPVOID) &wpEngineOutput.y, TRUE },
\r
1164 { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },
\r
1165 { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },
\r
1167 /* [HGM] board-size, adjudication and misc. options */
\r
1168 { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE },
\r
1169 { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE },
\r
1170 { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE },
\r
1171 { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE },
\r
1172 { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE },
\r
1173 { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE },
\r
1174 { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE },
\r
1175 { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE },
\r
1176 { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE },
\r
1177 { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE },
\r
1178 { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE },
\r
1179 { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE },
\r
1180 { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE },
\r
1181 { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE },
\r
1182 { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE },
\r
1183 { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE },
\r
1184 { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE },
\r
1185 { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE },
\r
1186 { "userName", ArgString, (LPVOID) &appData.userName, FALSE },
\r
1187 { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE },
\r
1188 { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE },
\r
1189 { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE },
\r
1190 { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE },
\r
1193 { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },
\r
1194 { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },
\r
1195 { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1196 { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1197 { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },
\r
1198 { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },
\r
1199 { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1200 { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1201 { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },
\r
1202 { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },
\r
1203 { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },
\r
1204 { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE },
\r
1205 { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,
\r
1207 { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE },
\r
1208 { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE },
\r
1209 { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE },
\r
1210 { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1211 { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1212 { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE },
\r
1213 { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,
\r
1215 { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1216 { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1217 { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1218 { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE },
\r
1219 { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE },
\r
1220 { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1221 { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1222 { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1223 { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1224 { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE },
\r
1225 { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE },
\r
1226 { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1227 { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1228 { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },
\r
1229 { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },
\r
1230 { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },
\r
1231 /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */
\r
1232 { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },
\r
1234 /* [HGM] options for broadcasting and time odds */
\r
1235 { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },
\r
1236 { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },
\r
1237 { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },
\r
1238 { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },
\r
1239 { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },
\r
1240 { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },
\r
1241 { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },
\r
1242 { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },
\r
1243 { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },
\r
1244 { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },
\r
1245 { NULL, ArgNone, NULL, FALSE }
\r
1249 /* Kludge for indirection files on command line */
\r
1250 char* lastIndirectionFilename;
\r
1251 ArgDescriptor argDescriptorIndirection =
\r
1252 { "", ArgSettingsFilename, (LPVOID) NULL, FALSE };
\r
1256 ExitArgError(char *msg, char *badArg)
\r
1258 char buf[MSG_SIZ];
\r
1260 sprintf(buf, "%s %s", msg, badArg);
\r
1261 DisplayFatalError(buf, 0, 2);
\r
1265 /* Command line font name parser. NULL name means do nothing.
\r
1266 Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"
\r
1267 For backward compatibility, syntax without the colon is also
\r
1268 accepted, but font names with digits in them won't work in that case.
\r
1271 ParseFontName(char *name, MyFontParams *mfp)
\r
1274 if (name == NULL) return;
\r
1276 q = strchr(p, ':');
\r
1278 if (q - p >= sizeof(mfp->faceName))
\r
1279 ExitArgError("Font name too long:", name);
\r
1280 memcpy(mfp->faceName, p, q - p);
\r
1281 mfp->faceName[q - p] = NULLCHAR;
\r
1284 q = mfp->faceName;
\r
1285 while (*p && !isdigit(*p)) {
\r
1287 if (q - mfp->faceName >= sizeof(mfp->faceName))
\r
1288 ExitArgError("Font name too long:", name);
\r
1290 while (q > mfp->faceName && q[-1] == ' ') q--;
\r
1293 if (!*p) ExitArgError("Font point size missing:", name);
\r
1294 mfp->pointSize = (float) atof(p);
\r
1295 mfp->bold = (strchr(p, 'b') != NULL);
\r
1296 mfp->italic = (strchr(p, 'i') != NULL);
\r
1297 mfp->underline = (strchr(p, 'u') != NULL);
\r
1298 mfp->strikeout = (strchr(p, 's') != NULL);
\r
1301 /* Color name parser.
\r
1302 X version accepts X color names, but this one
\r
1303 handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */
\r
1305 ParseColorName(char *name)
\r
1307 int red, green, blue, count;
\r
1308 char buf[MSG_SIZ];
\r
1310 count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);
\r
1312 count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d",
\r
1313 &red, &green, &blue);
\r
1316 sprintf(buf, "Can't parse color name %s", name);
\r
1317 DisplayError(buf, 0);
\r
1318 return RGB(0, 0, 0);
\r
1320 return PALETTERGB(red, green, blue);
\r
1324 void ParseAttribs(COLORREF *color, int *effects, char* argValue)
\r
1326 char *e = argValue;
\r
1330 if (*e == 'b') eff |= CFE_BOLD;
\r
1331 else if (*e == 'i') eff |= CFE_ITALIC;
\r
1332 else if (*e == 'u') eff |= CFE_UNDERLINE;
\r
1333 else if (*e == 's') eff |= CFE_STRIKEOUT;
\r
1334 else if (*e == '#' || isdigit(*e)) break;
\r
1338 *color = ParseColorName(e);
\r
1343 ParseBoardSize(char *name)
\r
1345 BoardSize bs = SizeTiny;
\r
1346 while (sizeInfo[bs].name != NULL) {
\r
1347 if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;
\r
1350 ExitArgError("Unrecognized board size value", name);
\r
1351 return bs; /* not reached */
\r
1356 StringGet(void *getClosure)
\r
1358 char **p = (char **) getClosure;
\r
1363 FileGet(void *getClosure)
\r
1366 FILE* f = (FILE*) getClosure;
\r
1375 /* Parse settings file named "name". If file found, return the
\r
1376 full name in fullname and return TRUE; else return FALSE */
\r
1378 ParseSettingsFile(char *name, char fullname[MSG_SIZ])
\r
1383 if (SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy)) {
\r
1384 f = fopen(fullname, "r");
\r
1386 ParseArgs(FileGet, f);
\r
1395 ParseArgs(GetFunc get, void *cl)
\r
1397 char argName[ARG_MAX];
\r
1398 char argValue[ARG_MAX];
\r
1399 ArgDescriptor *ad;
\r
1408 while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);
\r
1409 if (ch == NULLCHAR) break;
\r
1411 /* Comment to end of line */
\r
1413 while (ch != '\n' && ch != NULLCHAR) ch = get(cl);
\r
1415 } else if (ch == '/' || ch == '-') {
\r
1418 while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&
\r
1419 ch != '\n' && ch != '\t') {
\r
1425 for (ad = argDescriptors; ad->argName != NULL; ad++)
\r
1426 if (strcmp(ad->argName, argName + 1) == 0) break;
\r
1428 if (ad->argName == NULL)
\r
1429 ExitArgError("Unrecognized argument", argName);
\r
1431 } else if (ch == '@') {
\r
1432 /* Indirection file */
\r
1433 ad = &argDescriptorIndirection;
\r
1436 /* Positional argument */
\r
1437 ad = &argDescriptors[posarg++];
\r
1438 strcpy(argName, ad->argName);
\r
1441 if (ad->argType == ArgTrue) {
\r
1442 *(Boolean *) ad->argLoc = TRUE;
\r
1445 if (ad->argType == ArgFalse) {
\r
1446 *(Boolean *) ad->argLoc = FALSE;
\r
1450 while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
\r
1451 if (ch == NULLCHAR || ch == '\n') {
\r
1452 ExitArgError("No value provided for argument", argName);
\r
1456 // Quoting with { }. No characters have to (or can) be escaped.
\r
1457 // Thus the string cannot contain a '}' character.
\r
1477 } else if (ch == '\'' || ch == '"') {
\r
1478 // Quoting with ' ' or " ", with \ as escape character.
\r
1479 // Inconvenient for long strings that may contain Windows filenames.
\r
1496 if (ch == start) {
\r
1505 if (ad->argType == ArgFilename
\r
1506 || ad->argType == ArgSettingsFilename) {
\r
1512 ExitArgError("Incomplete \\ escape in value for", argName);
\r
1536 for (i = 0; i < 3; i++) {
\r
1537 if (ch >= '0' && ch <= '7') {
\r
1538 octval = octval*8 + (ch - '0');
\r
1545 *q++ = (char) octval;
\r
1556 while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {
\r
1563 switch (ad->argType) {
\r
1565 *(int *) ad->argLoc = atoi(argValue);
\r
1569 *(float *) ad->argLoc = (float) atof(argValue);
\r
1574 *(char **) ad->argLoc = strdup(argValue);
\r
1577 case ArgSettingsFilename:
\r
1579 char fullname[MSG_SIZ];
\r
1580 if (ParseSettingsFile(argValue, fullname)) {
\r
1581 if (ad->argLoc != NULL) {
\r
1582 *(char **) ad->argLoc = strdup(fullname);
\r
1585 if (ad->argLoc != NULL) {
\r
1587 ExitArgError("Failed to open indirection file", argValue);
\r
1594 switch (argValue[0]) {
\r
1597 *(Boolean *) ad->argLoc = TRUE;
\r
1601 *(Boolean *) ad->argLoc = FALSE;
\r
1604 ExitArgError("Unrecognized boolean argument value", argValue);
\r
1610 *(COLORREF *)ad->argLoc = ParseColorName(argValue);
\r
1613 case ArgAttribs: {
\r
1614 ColorClass cc = (ColorClass)ad->argLoc;
\r
1615 ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);
\r
1619 case ArgBoardSize:
\r
1620 *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);
\r
1624 ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);
\r
1627 case ArgCommSettings:
\r
1628 ParseCommSettings(argValue, &dcb);
\r
1632 ExitArgError("Unrecognized argument", argValue);
\r
1639 LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
\r
1641 HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
\r
1642 lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);
\r
1645 lf->lfEscapement = 0;
\r
1646 lf->lfOrientation = 0;
\r
1647 lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;
\r
1648 lf->lfItalic = mfp->italic;
\r
1649 lf->lfUnderline = mfp->underline;
\r
1650 lf->lfStrikeOut = mfp->strikeout;
\r
1651 lf->lfCharSet = DEFAULT_CHARSET;
\r
1652 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
1653 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
1654 lf->lfQuality = DEFAULT_QUALITY;
\r
1655 lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
\r
1656 strcpy(lf->lfFaceName, mfp->faceName);
\r
1660 CreateFontInMF(MyFont *mf)
\r
1662 LFfromMFP(&mf->lf, &mf->mfp);
\r
1663 if (mf->hf) DeleteObject(mf->hf);
\r
1664 mf->hf = CreateFontIndirect(&mf->lf);
\r
1668 SetDefaultTextAttribs()
\r
1671 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1672 ParseAttribs(&textAttribs[cc].color,
\r
1673 &textAttribs[cc].effects,
\r
1674 defaultTextAttribs[cc]);
\r
1679 SetDefaultSounds()
\r
1683 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1684 textAttribs[cc].sound.name = strdup("");
\r
1685 textAttribs[cc].sound.data = NULL;
\r
1687 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1688 sounds[sc].name = strdup("");
\r
1689 sounds[sc].data = NULL;
\r
1691 sounds[(int)SoundBell].name = strdup(SOUND_BELL);
\r
1699 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1700 MyLoadSound(&textAttribs[cc].sound);
\r
1702 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1703 MyLoadSound(&sounds[sc]);
\r
1708 InitAppData(LPSTR lpCmdLine)
\r
1711 char buf[ARG_MAX], currDir[MSG_SIZ];
\r
1714 programName = szAppName;
\r
1716 /* Initialize to defaults */
\r
1717 lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);
\r
1718 darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);
\r
1719 whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);
\r
1720 blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);
\r
1721 highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);
\r
1722 premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);
\r
1723 consoleBackgroundColor = ParseColorName(COLOR_BKGD);
\r
1724 SetDefaultTextAttribs();
\r
1725 SetDefaultSounds();
\r
1726 appData.movesPerSession = MOVES_PER_SESSION;
\r
1727 appData.initString = INIT_STRING;
\r
1728 appData.secondInitString = INIT_STRING;
\r
1729 appData.firstComputerString = COMPUTER_STRING;
\r
1730 appData.secondComputerString = COMPUTER_STRING;
\r
1731 appData.firstChessProgram = FIRST_CHESS_PROGRAM;
\r
1732 appData.secondChessProgram = SECOND_CHESS_PROGRAM;
\r
1733 appData.firstPlaysBlack = FALSE;
\r
1734 appData.noChessProgram = FALSE;
\r
1735 chessProgram = FALSE;
\r
1736 appData.firstHost = FIRST_HOST;
\r
1737 appData.secondHost = SECOND_HOST;
\r
1738 appData.firstDirectory = FIRST_DIRECTORY;
\r
1739 appData.secondDirectory = SECOND_DIRECTORY;
\r
1740 appData.bitmapDirectory = "";
\r
1741 appData.remoteShell = REMOTE_SHELL;
\r
1742 appData.remoteUser = "";
\r
1743 appData.timeDelay = TIME_DELAY;
\r
1744 appData.timeControl = TIME_CONTROL;
\r
1745 appData.timeIncrement = TIME_INCREMENT;
\r
1746 appData.icsActive = FALSE;
\r
1747 appData.icsHost = "";
\r
1748 appData.icsPort = ICS_PORT;
\r
1749 appData.icsCommPort = ICS_COMM_PORT;
\r
1750 appData.icsLogon = ICS_LOGON;
\r
1751 appData.icsHelper = "";
\r
1752 appData.useTelnet = FALSE;
\r
1753 appData.telnetProgram = TELNET_PROGRAM;
\r
1754 appData.gateway = "";
\r
1755 appData.loadGameFile = "";
\r
1756 appData.loadGameIndex = 0;
\r
1757 appData.saveGameFile = "";
\r
1758 appData.autoSaveGames = FALSE;
\r
1759 appData.loadPositionFile = "";
\r
1760 appData.loadPositionIndex = 1;
\r
1761 appData.savePositionFile = "";
\r
1762 appData.matchMode = FALSE;
\r
1763 appData.matchGames = 0;
\r
1764 appData.monoMode = FALSE;
\r
1765 appData.debugMode = FALSE;
\r
1766 appData.clockMode = TRUE;
\r
1767 boardSize = (BoardSize) -1; /* determine by screen size */
\r
1768 appData.Iconic = FALSE; /*unused*/
\r
1769 appData.searchTime = "";
\r
1770 appData.searchDepth = 0;
\r
1771 appData.showCoords = FALSE;
\r
1772 appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/
\r
1773 appData.autoCallFlag = FALSE;
\r
1774 appData.flipView = FALSE;
\r
1775 appData.autoFlipView = TRUE;
\r
1776 appData.cmailGameName = "";
\r
1777 appData.alwaysPromoteToQueen = FALSE;
\r
1778 appData.oldSaveStyle = FALSE;
\r
1779 appData.quietPlay = FALSE;
\r
1780 appData.showThinking = FALSE;
\r
1781 appData.ponderNextMove = TRUE;
\r
1782 appData.periodicUpdates = TRUE;
\r
1783 appData.popupExitMessage = TRUE;
\r
1784 appData.popupMoveErrors = FALSE;
\r
1785 appData.autoObserve = FALSE;
\r
1786 appData.autoComment = FALSE;
\r
1787 appData.animate = TRUE;
\r
1788 appData.animSpeed = 10;
\r
1789 appData.animateDragging = TRUE;
\r
1790 appData.highlightLastMove = TRUE;
\r
1791 appData.getMoveList = TRUE;
\r
1792 appData.testLegality = TRUE;
\r
1793 appData.premove = TRUE;
\r
1794 appData.premoveWhite = FALSE;
\r
1795 appData.premoveWhiteText = "";
\r
1796 appData.premoveBlack = FALSE;
\r
1797 appData.premoveBlackText = "";
\r
1798 appData.icsAlarm = TRUE;
\r
1799 appData.icsAlarmTime = 5000;
\r
1800 appData.autoRaiseBoard = TRUE;
\r
1801 appData.localLineEditing = TRUE;
\r
1802 appData.colorize = TRUE;
\r
1803 appData.reuseFirst = TRUE;
\r
1804 appData.reuseSecond = TRUE;
\r
1805 appData.blindfold = FALSE;
\r
1806 dcb.DCBlength = sizeof(DCB);
\r
1807 dcb.BaudRate = 9600;
\r
1808 dcb.fBinary = TRUE;
\r
1809 dcb.fParity = FALSE;
\r
1810 dcb.fOutxCtsFlow = FALSE;
\r
1811 dcb.fOutxDsrFlow = FALSE;
\r
1812 dcb.fDtrControl = DTR_CONTROL_ENABLE;
\r
1813 dcb.fDsrSensitivity = FALSE;
\r
1814 dcb.fTXContinueOnXoff = TRUE;
\r
1815 dcb.fOutX = FALSE;
\r
1817 dcb.fNull = FALSE;
\r
1818 dcb.fRtsControl = RTS_CONTROL_ENABLE;
\r
1819 dcb.fAbortOnError = FALSE;
\r
1820 dcb.wReserved = 0;
\r
1822 dcb.Parity = SPACEPARITY;
\r
1823 dcb.StopBits = ONESTOPBIT;
\r
1824 settingsFileName = SETTINGS_FILE;
\r
1825 saveSettingsOnExit = TRUE;
\r
1826 boardX = CW_USEDEFAULT;
\r
1827 boardY = CW_USEDEFAULT;
\r
1828 consoleX = CW_USEDEFAULT;
\r
1829 consoleY = CW_USEDEFAULT;
\r
1830 consoleW = CW_USEDEFAULT;
\r
1831 consoleH = CW_USEDEFAULT;
\r
1832 analysisX = CW_USEDEFAULT;
\r
1833 analysisY = CW_USEDEFAULT;
\r
1834 analysisW = CW_USEDEFAULT;
\r
1835 analysisH = CW_USEDEFAULT;
\r
1836 commentX = CW_USEDEFAULT;
\r
1837 commentY = CW_USEDEFAULT;
\r
1838 commentW = CW_USEDEFAULT;
\r
1839 commentH = CW_USEDEFAULT;
\r
1840 editTagsX = CW_USEDEFAULT;
\r
1841 editTagsY = CW_USEDEFAULT;
\r
1842 editTagsW = CW_USEDEFAULT;
\r
1843 editTagsH = CW_USEDEFAULT;
\r
1844 gameListX = CW_USEDEFAULT;
\r
1845 gameListY = CW_USEDEFAULT;
\r
1846 gameListW = CW_USEDEFAULT;
\r
1847 gameListH = CW_USEDEFAULT;
\r
1848 icsTextMenuString = ICS_TEXT_MENU_DEFAULT;
\r
1849 icsNames = ICS_NAMES;
\r
1850 firstChessProgramNames = FCP_NAMES;
\r
1851 secondChessProgramNames = SCP_NAMES;
\r
1852 appData.initialMode = "";
\r
1853 appData.variant = "normal";
\r
1854 appData.firstProtocolVersion = PROTOVER;
\r
1855 appData.secondProtocolVersion = PROTOVER;
\r
1856 appData.showButtonBar = TRUE;
\r
1858 /* [AS] New properties (see comments in header file) */
\r
1859 appData.firstScoreIsAbsolute = FALSE;
\r
1860 appData.secondScoreIsAbsolute = FALSE;
\r
1861 appData.saveExtendedInfoInPGN = FALSE;
\r
1862 appData.hideThinkingFromHuman = FALSE;
\r
1863 appData.liteBackTextureFile = "";
\r
1864 appData.liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
1865 appData.darkBackTextureFile = "";
\r
1866 appData.darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
1867 appData.renderPiecesWithFont = "";
\r
1868 appData.fontToPieceTable = "";
\r
1869 appData.fontBackColorWhite = 0;
\r
1870 appData.fontForeColorWhite = 0;
\r
1871 appData.fontBackColorBlack = 0;
\r
1872 appData.fontForeColorBlack = 0;
\r
1873 appData.fontPieceSize = 80;
\r
1874 appData.overrideLineGap = 1;
\r
1875 appData.adjudicateLossThreshold = 0;
\r
1876 appData.delayBeforeQuit = 0;
\r
1877 appData.delayAfterQuit = 0;
\r
1878 appData.nameOfDebugFile = "winboard.debug";
\r
1879 appData.pgnEventHeader = "Computer Chess Game";
\r
1880 appData.defaultFrcPosition = -1;
\r
1881 appData.gameListTags = GLT_DEFAULT_TAGS;
\r
1882 appData.saveOutOfBookInfo = TRUE;
\r
1883 appData.showEvalInMoveHistory = TRUE;
\r
1884 appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );
\r
1885 appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );
\r
1886 appData.highlightMoveWithArrow = FALSE;
\r
1887 appData.highlightArrowColor = ParseColorName( "#FFFF80" );
\r
1888 appData.useStickyWindows = TRUE;
\r
1889 appData.adjudicateDrawMoves = 0;
\r
1890 appData.autoDisplayComment = TRUE;
\r
1891 appData.autoDisplayTags = TRUE;
\r
1892 appData.firstIsUCI = FALSE;
\r
1893 appData.secondIsUCI = FALSE;
\r
1894 appData.firstHasOwnBookUCI = TRUE;
\r
1895 appData.secondHasOwnBookUCI = TRUE;
\r
1896 appData.polyglotDir = "";
\r
1897 appData.usePolyglotBook = FALSE;
\r
1898 appData.polyglotBook = "";
\r
1899 appData.defaultHashSize = 64;
\r
1900 appData.defaultCacheSizeEGTB = 4;
\r
1901 appData.defaultPathEGTB = "c:\\egtb";
\r
1903 InitWindowPlacement( &wpMoveHistory );
\r
1904 InitWindowPlacement( &wpEvalGraph );
\r
1905 InitWindowPlacement( &wpEngineOutput );
\r
1907 /* [HGM] User-selectable board size, adjudication control, miscellaneous */
\r
1908 appData.NrFiles = -1;
\r
1909 appData.NrRanks = -1;
\r
1910 appData.holdingsSize = -1;
\r
1911 appData.testClaims = FALSE;
\r
1912 appData.checkMates = FALSE;
\r
1913 appData.materialDraws= FALSE;
\r
1914 appData.trivialDraws = FALSE;
\r
1915 appData.ruleMoves = 51;
\r
1916 appData.drawRepeats = 6;
\r
1917 appData.matchPause = 10000;
\r
1918 appData.alphaRank = FALSE;
\r
1919 appData.allWhite = FALSE;
\r
1920 appData.upsideDown = FALSE;
\r
1921 appData.serverPause = 15;
\r
1922 appData.serverMovesName = NULL;
\r
1923 appData.suppressLoadMoves = FALSE;
\r
1924 appData.firstTimeOdds = 1;
\r
1925 appData.secondTimeOdds = 1;
\r
1926 appData.firstAccumulateTC = 1; // combine previous and current sessions
\r
1927 appData.secondAccumulateTC = 1;
\r
1928 appData.firstNPS = -1; // [HGM] nps: use wall-clock time
\r
1929 appData.secondNPS = -1;
\r
1930 appData.engineComments = 1;
\r
1931 appData.smpCores = 1; // [HGM] SMP: max nr of cores
\r
1932 appData.egtFormats = "";
\r
1935 appData.zippyTalk = ZIPPY_TALK;
\r
1936 appData.zippyPlay = ZIPPY_PLAY;
\r
1937 appData.zippyLines = ZIPPY_LINES;
\r
1938 appData.zippyPinhead = ZIPPY_PINHEAD;
\r
1939 appData.zippyPassword = ZIPPY_PASSWORD;
\r
1940 appData.zippyPassword2 = ZIPPY_PASSWORD2;
\r
1941 appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;
\r
1942 appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;
\r
1943 appData.zippyUseI = ZIPPY_USE_I;
\r
1944 appData.zippyBughouse = ZIPPY_BUGHOUSE;
\r
1945 appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;
\r
1946 appData.zippyGameEnd = ZIPPY_GAME_END;
\r
1947 appData.zippyGameStart = ZIPPY_GAME_START;
\r
1948 appData.zippyAdjourn = ZIPPY_ADJOURN;
\r
1949 appData.zippyAbort = ZIPPY_ABORT;
\r
1950 appData.zippyVariants = ZIPPY_VARIANTS;
\r
1951 appData.zippyMaxGames = ZIPPY_MAX_GAMES;
\r
1952 appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;
\r
1955 /* Point font array elements to structures and
\r
1956 parse default font names */
\r
1957 for (i=0; i<NUM_FONTS; i++) {
\r
1958 for (j=0; j<NUM_SIZES; j++) {
\r
1959 font[j][i] = &fontRec[j][i];
\r
1960 ParseFontName(font[j][i]->def, &font[j][i]->mfp);
\r
1964 /* Parse default settings file if any */
\r
1965 if (ParseSettingsFile(settingsFileName, buf)) {
\r
1966 settingsFileName = strdup(buf);
\r
1969 /* Parse command line */
\r
1970 ParseArgs(StringGet, &lpCmdLine);
\r
1972 /* [HGM] make sure board size is acceptable */
\r
1973 if(appData.NrFiles > BOARD_SIZE ||
\r
1974 appData.NrRanks > BOARD_SIZE )
\r
1975 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
1977 /* [HGM] After parsing the options from the .ini file, and overruling them
\r
1978 * with options from the command line, we now make an even higher priority
\r
1979 * overrule by WB options attached to the engine command line. This so that
\r
1980 * tournament managers can use WB options (such as /timeOdds) that follow
\r
1983 if(appData.firstChessProgram != NULL) {
\r
1984 char *p = StrStr(appData.firstChessProgram, "WBopt");
\r
1985 static char *f = "first";
\r
1986 char buf[MSG_SIZ], *q = buf;
\r
1987 if(p != NULL) { // engine command line contains WinBoard options
\r
1988 sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"
\r
1989 ParseArgs(StringGet, &q);
\r
1990 p[-1] = 0; // cut them offengine command line
\r
1993 // now do same for second chess program
\r
1994 if(appData.secondChessProgram != NULL) {
\r
1995 char *p = StrStr(appData.secondChessProgram, "WBopt");
\r
1996 static char *s = "second";
\r
1997 char buf[MSG_SIZ], *q = buf;
\r
1998 if(p != NULL) { // engine command line contains WinBoard options
\r
1999 sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"
\r
2000 ParseArgs(StringGet, &q);
\r
2001 p[-1] = 0; // cut them offengine command line
\r
2006 /* Propagate options that affect others */
\r
2007 if (appData.matchMode || appData.matchGames) chessProgram = TRUE;
\r
2008 if (appData.icsActive || appData.noChessProgram) {
\r
2009 chessProgram = FALSE; /* not local chess program mode */
\r
2012 /* Open startup dialog if needed */
\r
2013 if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||
\r
2014 (appData.icsActive && *appData.icsHost == NULLCHAR) ||
\r
2015 (chessProgram && (*appData.firstChessProgram == NULLCHAR ||
\r
2016 *appData.secondChessProgram == NULLCHAR))) {
\r
2019 lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);
\r
2020 DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);
\r
2021 FreeProcInstance(lpProc);
\r
2024 /* Make sure save files land in the right (?) directory */
\r
2025 if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {
\r
2026 appData.saveGameFile = strdup(buf);
\r
2028 if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {
\r
2029 appData.savePositionFile = strdup(buf);
\r
2032 /* Finish initialization for fonts and sounds */
\r
2033 for (i=0; i<NUM_FONTS; i++) {
\r
2034 for (j=0; j<NUM_SIZES; j++) {
\r
2035 CreateFontInMF(font[j][i]);
\r
2038 /* xboard, and older WinBoards, controlled the move sound with the
\r
2039 appData.ringBellAfterMoves option. In the current WinBoard, we
\r
2040 always turn the option on (so that the backend will call us),
\r
2041 then let the user turn the sound off by setting it to silence if
\r
2042 desired. To accommodate old winboard.ini files saved by old
\r
2043 versions of WinBoard, we also turn off the sound if the option
\r
2044 was initially set to false. */
\r
2045 if (!appData.ringBellAfterMoves) {
\r
2046 sounds[(int)SoundMove].name = strdup("");
\r
2047 appData.ringBellAfterMoves = TRUE;
\r
2049 GetCurrentDirectory(MSG_SIZ, currDir);
\r
2050 SetCurrentDirectory(installDir);
\r
2052 SetCurrentDirectory(currDir);
\r
2054 p = icsTextMenuString;
\r
2055 if (p[0] == '@') {
\r
2056 FILE* f = fopen(p + 1, "r");
\r
2058 DisplayFatalError(p + 1, errno, 2);
\r
2061 i = fread(buf, 1, sizeof(buf)-1, f);
\r
2063 buf[i] = NULLCHAR;
\r
2066 ParseIcsTextMenu(strdup(p));
\r
2073 HMENU hmenu = GetMenu(hwndMain);
\r
2075 (void) EnableMenuItem(hmenu, IDM_CommPort,
\r
2076 MF_BYCOMMAND|((appData.icsActive &&
\r
2077 *appData.icsCommPort != NULLCHAR) ?
\r
2078 MF_ENABLED : MF_GRAYED));
\r
2079 (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,
\r
2080 MF_BYCOMMAND|(saveSettingsOnExit ?
\r
2081 MF_CHECKED : MF_UNCHECKED));
\r
2086 SaveSettings(char* name)
\r
2089 ArgDescriptor *ad;
\r
2090 WINDOWPLACEMENT wp;
\r
2091 char dir[MSG_SIZ];
\r
2093 if (!hwndMain) return;
\r
2095 GetCurrentDirectory(MSG_SIZ, dir);
\r
2096 SetCurrentDirectory(installDir);
\r
2097 f = fopen(name, "w");
\r
2098 SetCurrentDirectory(dir);
\r
2100 DisplayError(name, errno);
\r
2103 fprintf(f, ";\n");
\r
2104 fprintf(f, "; %s %s.%s Save Settings file\n", PRODUCT, VERSION, PATCHLEVEL);
\r
2105 fprintf(f, ";\n");
\r
2106 fprintf(f, "; You can edit the values of options that are already set in this file,\n");
\r
2107 fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");
\r
2108 fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");
\r
2109 fprintf(f, ";\n");
\r
2111 wp.length = sizeof(WINDOWPLACEMENT);
\r
2112 GetWindowPlacement(hwndMain, &wp);
\r
2113 boardX = wp.rcNormalPosition.left;
\r
2114 boardY = wp.rcNormalPosition.top;
\r
2116 if (hwndConsole) {
\r
2117 GetWindowPlacement(hwndConsole, &wp);
\r
2118 consoleX = wp.rcNormalPosition.left;
\r
2119 consoleY = wp.rcNormalPosition.top;
\r
2120 consoleW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2121 consoleH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2124 if (analysisDialog) {
\r
2125 GetWindowPlacement(analysisDialog, &wp);
\r
2126 analysisX = wp.rcNormalPosition.left;
\r
2127 analysisY = wp.rcNormalPosition.top;
\r
2128 analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2129 analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2132 if (commentDialog) {
\r
2133 GetWindowPlacement(commentDialog, &wp);
\r
2134 commentX = wp.rcNormalPosition.left;
\r
2135 commentY = wp.rcNormalPosition.top;
\r
2136 commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2137 commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2140 if (editTagsDialog) {
\r
2141 GetWindowPlacement(editTagsDialog, &wp);
\r
2142 editTagsX = wp.rcNormalPosition.left;
\r
2143 editTagsY = wp.rcNormalPosition.top;
\r
2144 editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2145 editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2148 if (gameListDialog) {
\r
2149 GetWindowPlacement(gameListDialog, &wp);
\r
2150 gameListX = wp.rcNormalPosition.left;
\r
2151 gameListY = wp.rcNormalPosition.top;
\r
2152 gameListW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2153 gameListH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2156 /* [AS] Move history */
\r
2157 wpMoveHistory.visible = MoveHistoryIsUp();
\r
2159 if( moveHistoryDialog ) {
\r
2160 GetWindowPlacement(moveHistoryDialog, &wp);
\r
2161 wpMoveHistory.x = wp.rcNormalPosition.left;
\r
2162 wpMoveHistory.y = wp.rcNormalPosition.top;
\r
2163 wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2164 wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2167 /* [AS] Eval graph */
\r
2168 wpEvalGraph.visible = EvalGraphIsUp();
\r
2170 if( evalGraphDialog ) {
\r
2171 GetWindowPlacement(evalGraphDialog, &wp);
\r
2172 wpEvalGraph.x = wp.rcNormalPosition.left;
\r
2173 wpEvalGraph.y = wp.rcNormalPosition.top;
\r
2174 wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2175 wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2178 /* [AS] Engine output */
\r
2179 wpEngineOutput.visible = EngineOutputIsUp();
\r
2181 if( engineOutputDialog ) {
\r
2182 GetWindowPlacement(engineOutputDialog, &wp);
\r
2183 wpEngineOutput.x = wp.rcNormalPosition.left;
\r
2184 wpEngineOutput.y = wp.rcNormalPosition.top;
\r
2185 wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2186 wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2189 for (ad = argDescriptors; ad->argName != NULL; ad++) {
\r
2190 if (!ad->save) continue;
\r
2191 switch (ad->argType) {
\r
2194 char *p = *(char **)ad->argLoc;
\r
2195 if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {
\r
2196 /* Quote multiline values or \-containing values
\r
2197 with { } if possible */
\r
2198 fprintf(f, "/%s={%s}\n", ad->argName, p);
\r
2200 /* Else quote with " " */
\r
2201 fprintf(f, "/%s=\"", ad->argName);
\r
2203 if (*p == '\n') fprintf(f, "\n");
\r
2204 else if (*p == '\r') fprintf(f, "\\r");
\r
2205 else if (*p == '\t') fprintf(f, "\\t");
\r
2206 else if (*p == '\b') fprintf(f, "\\b");
\r
2207 else if (*p == '\f') fprintf(f, "\\f");
\r
2208 else if (*p < ' ') fprintf(f, "\\%03o", *p);
\r
2209 else if (*p == '\"') fprintf(f, "\\\"");
\r
2210 else if (*p == '\\') fprintf(f, "\\\\");
\r
2214 fprintf(f, "\"\n");
\r
2219 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);
\r
2222 fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);
\r
2225 fprintf(f, "/%s=%s\n", ad->argName,
\r
2226 (*(Boolean *)ad->argLoc) ? "true" : "false");
\r
2229 if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2232 if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2236 COLORREF color = *(COLORREF *)ad->argLoc;
\r
2237 fprintf(f, "/%s=#%02x%02x%02x\n", ad->argName,
\r
2238 color&0xff, (color>>8)&0xff, (color>>16)&0xff);
\r
2243 MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];
\r
2244 fprintf(f, "/%s=\"%s%s%s%s%s#%02x%02x%02x\"\n", ad->argName,
\r
2245 (ta->effects & CFE_BOLD) ? "b" : "",
\r
2246 (ta->effects & CFE_ITALIC) ? "i" : "",
\r
2247 (ta->effects & CFE_UNDERLINE) ? "u" : "",
\r
2248 (ta->effects & CFE_STRIKEOUT) ? "s" : "",
\r
2249 (ta->effects) ? " " : "",
\r
2250 ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);
\r
2254 if (strchr(*(char **)ad->argLoc, '\"')) {
\r
2255 fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);
\r
2257 fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);
\r
2260 case ArgBoardSize:
\r
2261 fprintf(f, "/%s=%s\n", ad->argName,
\r
2262 sizeInfo[*(BoardSize *)ad->argLoc].name);
\r
2267 for (bs=0; bs<NUM_SIZES; bs++) {
\r
2268 MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;
\r
2269 fprintf(f, "/size=%s ", sizeInfo[bs].name);
\r
2270 fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n",
\r
2271 ad->argName, mfp->faceName, mfp->pointSize,
\r
2272 mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",
\r
2273 mfp->bold ? "b" : "",
\r
2274 mfp->italic ? "i" : "",
\r
2275 mfp->underline ? "u" : "",
\r
2276 mfp->strikeout ? "s" : "");
\r
2280 case ArgCommSettings:
\r
2281 PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);
\r
2289 /*---------------------------------------------------------------------------*\
\r
2291 * GDI board drawing routines
\r
2293 \*---------------------------------------------------------------------------*/
\r
2295 /* [AS] Draw square using background texture */
\r
2296 static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )
\r
2301 return; /* Should never happen! */
\r
2304 SetGraphicsMode( dst, GM_ADVANCED );
\r
2311 /* X reflection */
\r
2316 x.eDx = (FLOAT) dw + dx - 1;
\r
2319 SetWorldTransform( dst, &x );
\r
2322 /* Y reflection */
\r
2328 x.eDy = (FLOAT) dh + dy - 1;
\r
2330 SetWorldTransform( dst, &x );
\r
2338 x.eDx = (FLOAT) dx;
\r
2339 x.eDy = (FLOAT) dy;
\r
2342 SetWorldTransform( dst, &x );
\r
2346 BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );
\r
2354 SetWorldTransform( dst, &x );
\r
2356 ModifyWorldTransform( dst, 0, MWT_IDENTITY );
\r
2359 /* [AS] [HGM] Make room for more piece types, so all pieces can be different */
\r
2361 PM_WP = (int) WhitePawn,
\r
2362 PM_WN = (int) WhiteKnight,
\r
2363 PM_WB = (int) WhiteBishop,
\r
2364 PM_WR = (int) WhiteRook,
\r
2365 PM_WQ = (int) WhiteQueen,
\r
2366 PM_WF = (int) WhiteFerz,
\r
2367 PM_WW = (int) WhiteWazir,
\r
2368 PM_WE = (int) WhiteAlfil,
\r
2369 PM_WM = (int) WhiteMan,
\r
2370 PM_WO = (int) WhiteCannon,
\r
2371 PM_WU = (int) WhiteUnicorn,
\r
2372 PM_WH = (int) WhiteNightrider,
\r
2373 PM_WA = (int) WhiteAngel,
\r
2374 PM_WC = (int) WhiteMarshall,
\r
2375 PM_WAB = (int) WhiteCardinal,
\r
2376 PM_WD = (int) WhiteDragon,
\r
2377 PM_WL = (int) WhiteLance,
\r
2378 PM_WS = (int) WhiteCobra,
\r
2379 PM_WV = (int) WhiteFalcon,
\r
2380 PM_WSG = (int) WhiteSilver,
\r
2381 PM_WG = (int) WhiteGrasshopper,
\r
2382 PM_WK = (int) WhiteKing,
\r
2383 PM_BP = (int) BlackPawn,
\r
2384 PM_BN = (int) BlackKnight,
\r
2385 PM_BB = (int) BlackBishop,
\r
2386 PM_BR = (int) BlackRook,
\r
2387 PM_BQ = (int) BlackQueen,
\r
2388 PM_BF = (int) BlackFerz,
\r
2389 PM_BW = (int) BlackWazir,
\r
2390 PM_BE = (int) BlackAlfil,
\r
2391 PM_BM = (int) BlackMan,
\r
2392 PM_BO = (int) BlackCannon,
\r
2393 PM_BU = (int) BlackUnicorn,
\r
2394 PM_BH = (int) BlackNightrider,
\r
2395 PM_BA = (int) BlackAngel,
\r
2396 PM_BC = (int) BlackMarshall,
\r
2397 PM_BG = (int) BlackGrasshopper,
\r
2398 PM_BAB = (int) BlackCardinal,
\r
2399 PM_BD = (int) BlackDragon,
\r
2400 PM_BL = (int) BlackLance,
\r
2401 PM_BS = (int) BlackCobra,
\r
2402 PM_BV = (int) BlackFalcon,
\r
2403 PM_BSG = (int) BlackSilver,
\r
2404 PM_BK = (int) BlackKing
\r
2407 static HFONT hPieceFont = NULL;
\r
2408 static HBITMAP hPieceMask[(int) EmptySquare];
\r
2409 static HBITMAP hPieceFace[(int) EmptySquare];
\r
2410 static int fontBitmapSquareSize = 0;
\r
2411 static char pieceToFontChar[(int) EmptySquare] =
\r
2412 { 'p', 'n', 'b', 'r', 'q',
\r
2413 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',
\r
2414 'k', 'o', 'm', 'v', 't', 'w',
\r
2415 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',
\r
2418 extern BOOL SetCharTable( char *table, const char * map );
\r
2419 /* [HGM] moved to backend.c */
\r
2421 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )
\r
2424 BYTE r1 = GetRValue( color );
\r
2425 BYTE g1 = GetGValue( color );
\r
2426 BYTE b1 = GetBValue( color );
\r
2432 /* Create a uniform background first */
\r
2433 hbrush = CreateSolidBrush( color );
\r
2434 SetRect( &rc, 0, 0, squareSize, squareSize );
\r
2435 FillRect( hdc, &rc, hbrush );
\r
2436 DeleteObject( hbrush );
\r
2439 /* Vertical gradient, good for pawn, knight and rook, less for queen and king */
\r
2440 int steps = squareSize / 2;
\r
2443 for( i=0; i<steps; i++ ) {
\r
2444 BYTE r = r1 - (r1-r2) * i / steps;
\r
2445 BYTE g = g1 - (g1-g2) * i / steps;
\r
2446 BYTE b = b1 - (b1-b2) * i / steps;
\r
2448 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2449 SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );
\r
2450 FillRect( hdc, &rc, hbrush );
\r
2451 DeleteObject(hbrush);
\r
2454 else if( mode == 2 ) {
\r
2455 /* Diagonal gradient, good more or less for every piece */
\r
2456 POINT triangle[3];
\r
2457 HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );
\r
2458 HBRUSH hbrush_old;
\r
2459 int steps = squareSize;
\r
2462 triangle[0].x = squareSize - steps;
\r
2463 triangle[0].y = squareSize;
\r
2464 triangle[1].x = squareSize;
\r
2465 triangle[1].y = squareSize;
\r
2466 triangle[2].x = squareSize;
\r
2467 triangle[2].y = squareSize - steps;
\r
2469 for( i=0; i<steps; i++ ) {
\r
2470 BYTE r = r1 - (r1-r2) * i / steps;
\r
2471 BYTE g = g1 - (g1-g2) * i / steps;
\r
2472 BYTE b = b1 - (b1-b2) * i / steps;
\r
2474 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2475 hbrush_old = SelectObject( hdc, hbrush );
\r
2476 Polygon( hdc, triangle, 3 );
\r
2477 SelectObject( hdc, hbrush_old );
\r
2478 DeleteObject(hbrush);
\r
2483 SelectObject( hdc, hpen );
\r
2488 [AS] The method I use to create the bitmaps it a bit tricky, but it
\r
2489 seems to work ok. The main problem here is to find the "inside" of a chess
\r
2490 piece: follow the steps as explained below.
\r
2492 static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
\r
2496 COLORREF chroma = RGB(0xFF,0x00,0xFF);
\r
2500 int backColor = whitePieceColor;
\r
2501 int foreColor = blackPieceColor;
\r
2503 if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {
\r
2504 backColor = appData.fontBackColorWhite;
\r
2505 foreColor = appData.fontForeColorWhite;
\r
2507 else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {
\r
2508 backColor = appData.fontBackColorBlack;
\r
2509 foreColor = appData.fontForeColorBlack;
\r
2513 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2515 hbm_old = SelectObject( hdc, hbm );
\r
2519 rc.right = squareSize;
\r
2520 rc.bottom = squareSize;
\r
2522 /* Step 1: background is now black */
\r
2523 FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );
\r
2525 GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );
\r
2527 pt.x = (squareSize - sz.cx) / 2;
\r
2528 pt.y = (squareSize - sz.cy) / 2;
\r
2530 SetBkMode( hdc, TRANSPARENT );
\r
2531 SetTextColor( hdc, chroma );
\r
2532 /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */
\r
2533 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[index], 1 );
\r
2535 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
\r
2536 /* Step 3: the area outside the piece is filled with white */
\r
2537 // FloodFill( hdc, 0, 0, chroma );
\r
2538 ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );
\r
2539 ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big
\r
2540 ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );
\r
2541 ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );
\r
2542 SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
\r
2544 Step 4: this is the tricky part, the area inside the piece is filled with black,
\r
2545 but if the start point is not inside the piece we're lost!
\r
2546 There should be a better way to do this... if we could create a region or path
\r
2547 from the fill operation we would be fine for example.
\r
2549 // FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );
\r
2550 ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );
\r
2552 { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */
\r
2553 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2554 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2556 SelectObject( dc2, bm2 );
\r
2557 BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy
\r
2558 BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2559 BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2560 BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2561 BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2564 DeleteObject( bm2 );
\r
2567 SetTextColor( hdc, 0 );
\r
2569 Step 5: some fonts have "disconnected" areas that are skipped by the fill:
\r
2570 draw the piece again in black for safety.
\r
2572 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[index], 1 );
\r
2574 SelectObject( hdc, hbm_old );
\r
2576 if( hPieceMask[index] != NULL ) {
\r
2577 DeleteObject( hPieceMask[index] );
\r
2580 hPieceMask[index] = hbm;
\r
2583 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2585 SelectObject( hdc, hbm );
\r
2588 HDC dc1 = CreateCompatibleDC( hdc_window );
\r
2589 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2590 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2592 SelectObject( dc1, hPieceMask[index] );
\r
2593 SelectObject( dc2, bm2 );
\r
2594 FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );
\r
2595 BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );
\r
2598 Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves
\r
2599 the piece background and deletes (makes transparent) the rest.
\r
2600 Thanks to that mask, we are free to paint the background with the greates
\r
2601 freedom, as we'll be able to mask off the unwanted parts when finished.
\r
2602 We use this, to make gradients and give the pieces a "roundish" look.
\r
2604 SetPieceBackground( hdc, backColor, 2 );
\r
2605 BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );
\r
2609 DeleteObject( bm2 );
\r
2612 SetTextColor( hdc, foreColor );
\r
2613 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[index], 1 );
\r
2615 SelectObject( hdc, hbm_old );
\r
2617 if( hPieceFace[index] != NULL ) {
\r
2618 DeleteObject( hPieceFace[index] );
\r
2621 hPieceFace[index] = hbm;
\r
2624 static int TranslatePieceToFontPiece( int piece )
\r
2654 case BlackMarshall:
\r
2658 case BlackNightrider:
\r
2664 case BlackUnicorn:
\r
2668 case BlackGrasshopper:
\r
2680 case BlackCardinal:
\r
2687 case WhiteMarshall:
\r
2691 case WhiteNightrider:
\r
2697 case WhiteUnicorn:
\r
2701 case WhiteGrasshopper:
\r
2713 case WhiteCardinal:
\r
2722 void CreatePiecesFromFont()
\r
2725 HDC hdc_window = NULL;
\r
2731 if( fontBitmapSquareSize < 0 ) {
\r
2732 /* Something went seriously wrong in the past: do not try to recreate fonts! */
\r
2736 if( appData.renderPiecesWithFont == NULL || appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {
\r
2737 fontBitmapSquareSize = -1;
\r
2741 if( fontBitmapSquareSize != squareSize ) {
\r
2742 hdc_window = GetDC( hwndMain );
\r
2743 hdc = CreateCompatibleDC( hdc_window );
\r
2745 if( hPieceFont != NULL ) {
\r
2746 DeleteObject( hPieceFont );
\r
2749 for( i=0; i<=(int)BlackKing; i++ ) {
\r
2750 hPieceMask[i] = NULL;
\r
2751 hPieceFace[i] = NULL;
\r
2757 if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {
\r
2758 fontHeight = appData.fontPieceSize;
\r
2761 fontHeight = (fontHeight * squareSize) / 100;
\r
2763 lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
\r
2765 lf.lfEscapement = 0;
\r
2766 lf.lfOrientation = 0;
\r
2767 lf.lfWeight = FW_NORMAL;
\r
2769 lf.lfUnderline = 0;
\r
2770 lf.lfStrikeOut = 0;
\r
2771 lf.lfCharSet = DEFAULT_CHARSET;
\r
2772 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
2773 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
2774 lf.lfQuality = PROOF_QUALITY;
\r
2775 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
\r
2776 strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );
\r
2777 lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';
\r
2779 hPieceFont = CreateFontIndirect( &lf );
\r
2781 if( hPieceFont == NULL ) {
\r
2782 fontBitmapSquareSize = -2;
\r
2785 /* Setup font-to-piece character table */
\r
2786 if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {
\r
2787 /* No (or wrong) global settings, try to detect the font */
\r
2788 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {
\r
2790 SetCharTable(pieceToFontChar, "phbrqkojntwl");
\r
2792 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {
\r
2793 /* DiagramTT* family */
\r
2794 SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");
\r
2796 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {
\r
2797 /* Fairy symbols */
\r
2798 SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
\r
2800 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {
\r
2801 /* Good Companion (Some characters get warped as literal :-( */
\r
2802 char s[] = "1cmWG0ñueOS¯®oYI23wgQU";
\r
2803 s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;
\r
2804 SetCharTable(pieceToFontChar, s);
\r
2807 /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */
\r
2808 SetCharTable(pieceToFontChar, "pnbrqkomvtwl");
\r
2812 /* Create bitmaps */
\r
2813 hfont_old = SelectObject( hdc, hPieceFont );
\r
2815 CreatePieceMaskFromFont( hdc_window, hdc, PM_WP );
\r
2816 CreatePieceMaskFromFont( hdc_window, hdc, PM_WN );
\r
2817 CreatePieceMaskFromFont( hdc_window, hdc, PM_WB );
\r
2818 CreatePieceMaskFromFont( hdc_window, hdc, PM_WR );
\r
2819 CreatePieceMaskFromFont( hdc_window, hdc, PM_WQ );
\r
2820 CreatePieceMaskFromFont( hdc_window, hdc, PM_WK );
\r
2821 CreatePieceMaskFromFont( hdc_window, hdc, PM_BP );
\r
2822 CreatePieceMaskFromFont( hdc_window, hdc, PM_BN );
\r
2823 CreatePieceMaskFromFont( hdc_window, hdc, PM_BB );
\r
2824 CreatePieceMaskFromFont( hdc_window, hdc, PM_BR );
\r
2825 CreatePieceMaskFromFont( hdc_window, hdc, PM_BQ );
\r
2826 CreatePieceMaskFromFont( hdc_window, hdc, PM_BK );
\r
2828 CreatePieceMaskFromFont( hdc_window, hdc, PM_WA );
\r
2829 CreatePieceMaskFromFont( hdc_window, hdc, PM_WC );
\r
2830 CreatePieceMaskFromFont( hdc_window, hdc, PM_WF );
\r
2831 CreatePieceMaskFromFont( hdc_window, hdc, PM_WH );
\r
2832 CreatePieceMaskFromFont( hdc_window, hdc, PM_WE );
\r
2833 CreatePieceMaskFromFont( hdc_window, hdc, PM_WW );
\r
2834 CreatePieceMaskFromFont( hdc_window, hdc, PM_WU );
\r
2835 CreatePieceMaskFromFont( hdc_window, hdc, PM_WO );
\r
2836 CreatePieceMaskFromFont( hdc_window, hdc, PM_WG );
\r
2837 CreatePieceMaskFromFont( hdc_window, hdc, PM_WM );
\r
2838 CreatePieceMaskFromFont( hdc_window, hdc, PM_WSG );
\r
2839 CreatePieceMaskFromFont( hdc_window, hdc, PM_WV );
\r
2840 CreatePieceMaskFromFont( hdc_window, hdc, PM_WAB );
\r
2841 CreatePieceMaskFromFont( hdc_window, hdc, PM_WD );
\r
2842 CreatePieceMaskFromFont( hdc_window, hdc, PM_WL );
\r
2843 CreatePieceMaskFromFont( hdc_window, hdc, PM_WS );
\r
2844 CreatePieceMaskFromFont( hdc_window, hdc, PM_BA );
\r
2845 CreatePieceMaskFromFont( hdc_window, hdc, PM_BC );
\r
2846 CreatePieceMaskFromFont( hdc_window, hdc, PM_BF );
\r
2847 CreatePieceMaskFromFont( hdc_window, hdc, PM_BH );
\r
2848 CreatePieceMaskFromFont( hdc_window, hdc, PM_BE );
\r
2849 CreatePieceMaskFromFont( hdc_window, hdc, PM_BW );
\r
2850 CreatePieceMaskFromFont( hdc_window, hdc, PM_BU );
\r
2851 CreatePieceMaskFromFont( hdc_window, hdc, PM_BO );
\r
2852 CreatePieceMaskFromFont( hdc_window, hdc, PM_BG );
\r
2853 CreatePieceMaskFromFont( hdc_window, hdc, PM_BM );
\r
2854 CreatePieceMaskFromFont( hdc_window, hdc, PM_BSG );
\r
2855 CreatePieceMaskFromFont( hdc_window, hdc, PM_BV );
\r
2856 CreatePieceMaskFromFont( hdc_window, hdc, PM_BAB );
\r
2857 CreatePieceMaskFromFont( hdc_window, hdc, PM_BD );
\r
2858 CreatePieceMaskFromFont( hdc_window, hdc, PM_BL );
\r
2859 CreatePieceMaskFromFont( hdc_window, hdc, PM_BS );
\r
2861 for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */
\r
2862 if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */
\r
2863 CreatePieceMaskFromFont( hdc_window, hdc, i );
\r
2865 SelectObject( hdc, hfont_old );
\r
2867 fontBitmapSquareSize = squareSize;
\r
2871 if( hdc != NULL ) {
\r
2875 if( hdc_window != NULL ) {
\r
2876 ReleaseDC( hwndMain, hdc_window );
\r
2881 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)
\r
2885 sprintf(name, "%s%d%s", piece, squareSize, suffix);
\r
2886 if (gameInfo.event &&
\r
2887 strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&
\r
2888 strcmp(name, "k80s") == 0) {
\r
2889 strcpy(name, "tim");
\r
2891 return LoadBitmap(hinst, name);
\r
2895 /* Insert a color into the program's logical palette
\r
2896 structure. This code assumes the given color is
\r
2897 the result of the RGB or PALETTERGB macro, and it
\r
2898 knows how those macros work (which is documented).
\r
2901 InsertInPalette(COLORREF color)
\r
2903 LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);
\r
2905 if (pLogPal->palNumEntries++ >= PALETTESIZE) {
\r
2906 DisplayFatalError("Too many colors", 0, 1);
\r
2907 pLogPal->palNumEntries--;
\r
2911 pe->peFlags = (char) 0;
\r
2912 pe->peRed = (char) (0xFF & color);
\r
2913 pe->peGreen = (char) (0xFF & (color >> 8));
\r
2914 pe->peBlue = (char) (0xFF & (color >> 16));
\r
2920 InitDrawingColors()
\r
2922 if (pLogPal == NULL) {
\r
2923 /* Allocate enough memory for a logical palette with
\r
2924 * PALETTESIZE entries and set the size and version fields
\r
2925 * of the logical palette structure.
\r
2927 pLogPal = (NPLOGPALETTE)
\r
2928 LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +
\r
2929 (sizeof(PALETTEENTRY) * (PALETTESIZE))));
\r
2930 pLogPal->palVersion = 0x300;
\r
2932 pLogPal->palNumEntries = 0;
\r
2934 InsertInPalette(lightSquareColor);
\r
2935 InsertInPalette(darkSquareColor);
\r
2936 InsertInPalette(whitePieceColor);
\r
2937 InsertInPalette(blackPieceColor);
\r
2938 InsertInPalette(highlightSquareColor);
\r
2939 InsertInPalette(premoveHighlightColor);
\r
2941 /* create a logical color palette according the information
\r
2942 * in the LOGPALETTE structure.
\r
2944 hPal = CreatePalette((LPLOGPALETTE) pLogPal);
\r
2946 lightSquareBrush = CreateSolidBrush(lightSquareColor);
\r
2947 blackSquareBrush = CreateSolidBrush(blackPieceColor);
\r
2948 darkSquareBrush = CreateSolidBrush(darkSquareColor);
\r
2949 whitePieceBrush = CreateSolidBrush(whitePieceColor);
\r
2950 blackPieceBrush = CreateSolidBrush(blackPieceColor);
\r
2951 iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
\r
2953 /* [AS] Force rendering of the font-based pieces */
\r
2954 if( fontBitmapSquareSize > 0 ) {
\r
2955 fontBitmapSquareSize = 0;
\r
2961 BoardWidth(int boardSize, int n)
\r
2962 { /* [HGM] argument n added to allow different width and height */
\r
2963 int lineGap = sizeInfo[boardSize].lineGap;
\r
2965 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
2966 lineGap = appData.overrideLineGap;
\r
2969 return (n + 1) * lineGap +
\r
2970 n * sizeInfo[boardSize].squareSize;
\r
2973 /* Respond to board resize by dragging edge */
\r
2975 ResizeBoard(int newSizeX, int newSizeY, int flags)
\r
2977 BoardSize newSize = NUM_SIZES - 1;
\r
2978 static int recurse = 0;
\r
2979 if (IsIconic(hwndMain)) return;
\r
2980 if (recurse > 0) return;
\r
2982 while (newSize > 0) {
\r
2983 InitDrawingSizes(newSize, 0);
\r
2984 if(newSizeX >= sizeInfo[newSize].cliWidth ||
\r
2985 newSizeY >= sizeInfo[newSize].cliHeight) break;
\r
2988 boardSize = newSize;
\r
2989 InitDrawingSizes(boardSize, flags);
\r
2996 InitDrawingSizes(BoardSize boardSize, int flags)
\r
2998 int i, boardWidth, boardHeight; /* [HGM] height treated separately */
\r
2999 ChessSquare piece;
\r
3000 static int oldBoardSize = -1, oldTinyLayout = 0;
\r
3002 SIZE clockSize, messageSize;
\r
3004 char buf[MSG_SIZ];
\r
3006 HMENU hmenu = GetMenu(hwndMain);
\r
3007 RECT crect, wrect;
\r
3009 LOGBRUSH logbrush;
\r
3011 /* [HGM] call with -1 uses old size (for if nr of files, ranks changes) */
\r
3012 if(boardSize == (BoardSize)(-2) ) boardSize = oldBoardSize;
\r
3014 tinyLayout = sizeInfo[boardSize].tinyLayout;
\r
3015 smallLayout = sizeInfo[boardSize].smallLayout;
\r
3016 squareSize = sizeInfo[boardSize].squareSize;
\r
3017 lineGap = sizeInfo[boardSize].lineGap;
\r
3018 minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted */
\r
3020 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3021 lineGap = appData.overrideLineGap;
\r
3024 if (tinyLayout != oldTinyLayout) {
\r
3025 long style = GetWindowLong(hwndMain, GWL_STYLE);
\r
3027 style &= ~WS_SYSMENU;
\r
3028 InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize,
\r
3029 "&Minimize\tCtrl+F4");
\r
3031 style |= WS_SYSMENU;
\r
3032 RemoveMenu(hmenu, IDM_Minimize, MF_BYCOMMAND);
\r
3034 SetWindowLong(hwndMain, GWL_STYLE, style);
\r
3036 for (i=0; menuBarText[tinyLayout][i]; i++) {
\r
3037 ModifyMenu(hmenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP,
\r
3038 (UINT)GetSubMenu(hmenu, i), menuBarText[tinyLayout][i]);
\r
3040 DrawMenuBar(hwndMain);
\r
3043 boardWidth = BoardWidth(boardSize, BOARD_WIDTH);
\r
3044 boardHeight = BoardWidth(boardSize, BOARD_HEIGHT);
\r
3046 /* Get text area sizes */
\r
3047 hdc = GetDC(hwndMain);
\r
3048 if (appData.clockMode) {
\r
3049 sprintf(buf, "White: %s", TimeString(23*60*60*1000L));
\r
3051 sprintf(buf, "White");
\r
3053 oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);
\r
3054 GetTextExtentPoint(hdc, buf, strlen(buf), &clockSize);
\r
3055 SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);
\r
3056 str = "We only care about the height here";
\r
3057 GetTextExtentPoint(hdc, str, strlen(str), &messageSize);
\r
3058 SelectObject(hdc, oldFont);
\r
3059 ReleaseDC(hwndMain, hdc);
\r
3061 /* Compute where everything goes */
\r
3062 whiteRect.left = OUTER_MARGIN;
\r
3063 whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2;
\r
3064 whiteRect.top = OUTER_MARGIN;
\r
3065 whiteRect.bottom = whiteRect.top + clockSize.cy;
\r
3067 blackRect.left = whiteRect.right + INNER_MARGIN;
\r
3068 blackRect.right = blackRect.left + boardWidth/2 - 1;
\r
3069 blackRect.top = whiteRect.top;
\r
3070 blackRect.bottom = whiteRect.bottom;
\r
3072 messageRect.left = whiteRect.left + MESSAGE_LINE_LEFTMARGIN;
\r
3073 if (appData.showButtonBar) {
\r
3074 messageRect.right = blackRect.right
\r
3075 - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN;
\r
3077 messageRect.right = blackRect.right;
\r
3079 messageRect.top = whiteRect.bottom + INNER_MARGIN;
\r
3080 messageRect.bottom = messageRect.top + messageSize.cy;
\r
3082 boardRect.left = whiteRect.left;
\r
3083 boardRect.right = boardRect.left + boardWidth;
\r
3084 boardRect.top = messageRect.bottom + INNER_MARGIN;
\r
3085 boardRect.bottom = boardRect.top + boardHeight;
\r
3087 sizeInfo[boardSize].cliWidth = boardRect.right + OUTER_MARGIN;
\r
3088 sizeInfo[boardSize].cliHeight = boardRect.bottom + OUTER_MARGIN;
\r
3089 winWidth = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN;
\r
3090 winHeight = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) +
\r
3091 GetSystemMetrics(SM_CYCAPTION) + boardRect.bottom + OUTER_MARGIN;
\r
3092 GetWindowRect(hwndMain, &wrect);
\r
3093 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3094 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3095 /* compensate if menu bar wrapped */
\r
3096 GetClientRect(hwndMain, &crect);
\r
3097 offby = boardRect.bottom + OUTER_MARGIN - crect.bottom;
\r
3098 winHeight += offby;
\r
3100 case WMSZ_TOPLEFT:
\r
3101 SetWindowPos(hwndMain, NULL,
\r
3102 wrect.right - winWidth, wrect.bottom - winHeight,
\r
3103 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3106 case WMSZ_TOPRIGHT:
\r
3108 SetWindowPos(hwndMain, NULL,
\r
3109 wrect.left, wrect.bottom - winHeight,
\r
3110 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3113 case WMSZ_BOTTOMLEFT:
\r
3115 SetWindowPos(hwndMain, NULL,
\r
3116 wrect.right - winWidth, wrect.top,
\r
3117 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3120 case WMSZ_BOTTOMRIGHT:
\r
3124 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3125 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3130 for (i = 0; i < N_BUTTONS; i++) {
\r
3131 if (buttonDesc[i].hwnd != NULL) {
\r
3132 DestroyWindow(buttonDesc[i].hwnd);
\r
3133 buttonDesc[i].hwnd = NULL;
\r
3135 if (appData.showButtonBar) {
\r
3136 buttonDesc[i].hwnd =
\r
3137 CreateWindow("BUTTON", buttonDesc[i].label,
\r
3138 WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
\r
3139 boardRect.right - BUTTON_WIDTH*(N_BUTTONS-i),
\r
3140 messageRect.top, BUTTON_WIDTH, messageSize.cy, hwndMain,
\r
3141 (HMENU) buttonDesc[i].id,
\r
3142 (HINSTANCE) GetWindowLong(hwndMain, GWL_HINSTANCE), NULL);
\r
3144 SendMessage(buttonDesc[i].hwnd, WM_SETFONT,
\r
3145 (WPARAM)font[boardSize][MESSAGE_FONT]->hf,
\r
3146 MAKELPARAM(FALSE, 0));
\r
3148 if (buttonDesc[i].id == IDM_Pause)
\r
3149 hwndPause = buttonDesc[i].hwnd;
\r
3150 buttonDesc[i].wndproc = (WNDPROC)
\r
3151 SetWindowLong(buttonDesc[i].hwnd, GWL_WNDPROC, (LONG) ButtonProc);
\r
3154 if (gridPen != NULL) DeleteObject(gridPen);
\r
3155 if (highlightPen != NULL) DeleteObject(highlightPen);
\r
3156 if (premovePen != NULL) DeleteObject(premovePen);
\r
3157 if (lineGap != 0) {
\r
3158 logbrush.lbStyle = BS_SOLID;
\r
3159 logbrush.lbColor = RGB(0, 0, 0); /* grid pen color = black */
\r
3161 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3162 lineGap, &logbrush, 0, NULL);
\r
3163 logbrush.lbColor = highlightSquareColor;
\r
3165 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3166 lineGap, &logbrush, 0, NULL);
\r
3168 logbrush.lbColor = premoveHighlightColor;
\r
3170 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3171 lineGap, &logbrush, 0, NULL);
\r
3173 /* [HGM] Loop had to be split in part for vert. and hor. lines */
\r
3174 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
\r
3175 gridEndpoints[i*2].x = boardRect.left + lineGap / 2;
\r
3176 gridEndpoints[i*2].y = gridEndpoints[i*2 + 1].y =
\r
3177 boardRect.top + lineGap / 2 + (i * (squareSize + lineGap));
\r
3178 gridEndpoints[i*2 + 1].x = boardRect.left + lineGap / 2 +
\r
3179 BOARD_WIDTH * (squareSize + lineGap);
\r
3180 lineGap / 2 + (i * (squareSize + lineGap));
\r
3181 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3183 for (i = 0; i < BOARD_WIDTH + 1; i++) {
\r
3184 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].y = boardRect.top + lineGap / 2;
\r
3185 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].x =
\r
3186 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].x = boardRect.left +
\r
3187 lineGap / 2 + (i * (squareSize + lineGap));
\r
3188 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].y =
\r
3189 boardRect.top + BOARD_HEIGHT * (squareSize + lineGap);
\r
3190 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3194 /* [HGM] Licensing requirement */
\r
3196 if(gameInfo.variant == VariantGothic) GothicPopUp( GOTHIC, VariantGothic); else
\r
3199 if(gameInfo.variant == VariantFalcon) GothicPopUp( FALCON, VariantFalcon); else
\r
3201 GothicPopUp( "", VariantNormal);
\r
3204 /* if (boardSize == oldBoardSize) return; [HGM] variant might have changed */
\r
3205 oldBoardSize = boardSize;
\r
3206 oldTinyLayout = tinyLayout;
\r
3208 /* Load piece bitmaps for this board size */
\r
3209 for (i=0; i<=2; i++) {
\r
3210 for (piece = WhitePawn;
\r
3211 (int) piece < (int) BlackPawn;
\r
3212 piece = (ChessSquare) ((int) piece + 1)) {
\r
3213 if (pieceBitmap[i][piece] != NULL)
\r
3214 DeleteObject(pieceBitmap[i][piece]);
\r
3218 fontBitmapSquareSize = 0; /* [HGM] render: make sure pieces will be recreated, as we might need others now */
\r
3219 // Orthodox Chess pieces
\r
3220 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s");
\r
3221 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s");
\r
3222 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "s");
\r
3223 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "s");
\r
3224 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "s");
\r
3225 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "o");
\r
3226 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "o");
\r
3227 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "o");
\r
3228 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "o");
\r
3229 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "o");
\r
3230 pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "w");
\r
3231 pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "w");
\r
3232 pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "w");
\r
3233 pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w");
\r
3234 pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w");
\r
3235 if( !strcmp(appData.variant, "shogi") && (squareSize==72 || squareSize==49)) {
\r
3236 // in Shogi, Hijack the unused Queen for Lance
\r
3237 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3238 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3239 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3241 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s");
\r
3242 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o");
\r
3243 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w");
\r
3246 if(squareSize <= 72 && squareSize >= 33) {
\r
3247 /* A & C are available in most sizes now */
\r
3248 if(squareSize != 49 && squareSize != 72 && squareSize != 33) { // Vortex-like
\r
3249 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3250 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3251 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3252 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3253 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3254 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3255 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3256 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3257 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3258 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3259 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3260 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3261 } else { // Smirf-like
\r
3262 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "s");
\r
3263 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "o");
\r
3264 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "w");
\r
3266 if(gameInfo.variant == VariantGothic) { // Vortex-like
\r
3267 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3268 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3269 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3270 } else { // WinBoard standard
\r
3271 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s");
\r
3272 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o");
\r
3273 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "w");
\r
3278 if(squareSize==72 || squareSize==49 || squareSize==33) { /* experiment with some home-made bitmaps */
\r
3279 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "s");
\r
3280 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "o");
\r
3281 pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "w");
\r
3282 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "s");
\r
3283 pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "o");
\r
3284 pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3285 pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "s");
\r
3286 pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "o");
\r
3287 pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "w");
\r
3288 pieceBitmap[0][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "s");
\r
3289 pieceBitmap[1][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "o");
\r
3290 pieceBitmap[2][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "w");
\r
3291 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3292 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3293 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3294 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "s");
\r
3295 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "o");
\r
3296 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "w");
\r
3297 pieceBitmap[0][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "s");
\r
3298 pieceBitmap[1][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "o");
\r
3299 pieceBitmap[2][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "w");
\r
3300 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "s");
\r
3301 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "o");
\r
3302 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "w");
\r
3303 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3304 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3305 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3306 pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s");
\r
3307 pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o");
\r
3308 pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w");
\r
3310 if(gameInfo.variant == VariantShogi) { /* promoted Gold represemtations */
\r
3311 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s");
\r
3312 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "o");
\r
3313 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3314 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "s");
\r
3315 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "o");
\r
3316 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3317 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "s");
\r
3318 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "o");
\r
3319 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3320 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "s");
\r
3321 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "o");
\r
3322 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3324 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "s");
\r
3325 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "o");
\r
3326 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "w");
\r
3327 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "s");
\r
3328 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "o");
\r
3329 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "w");
\r
3330 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3331 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3332 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3333 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "s");
\r
3334 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "o");
\r
3335 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "w");
\r
3338 } else { /* other size, no special bitmaps available. Use smaller symbols */
\r
3339 if((int)boardSize < 2) minorSize = sizeInfo[0].squareSize;
\r
3340 else minorSize = sizeInfo[(int)boardSize - 2].squareSize;
\r
3341 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "s");
\r
3342 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "o");
\r
3343 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "w");
\r
3344 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "s");
\r
3345 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "o");
\r
3346 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "w");
\r
3347 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "s");
\r
3348 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "o");
\r
3349 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "w");
\r
3350 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "s");
\r
3351 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "o");
\r
3352 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "w");
\r
3356 if(gameInfo.variant == VariantShogi && squareSize == 58)
\r
3357 /* special Shogi support in this size */
\r
3358 { for (i=0; i<=2; i++) { /* replace all bitmaps */
\r
3359 for (piece = WhitePawn;
\r
3360 (int) piece < (int) BlackPawn;
\r
3361 piece = (ChessSquare) ((int) piece + 1)) {
\r
3362 if (pieceBitmap[i][piece] != NULL)
\r
3363 DeleteObject(pieceBitmap[i][piece]);
\r
3366 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3367 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3368 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3369 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3370 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3371 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3372 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r
3373 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");
\r
3374 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");
\r
3375 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");
\r
3376 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");
\r
3377 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");
\r
3378 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");
\r
3379 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");
\r
3380 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3381 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3382 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3383 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3384 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3385 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3386 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r
3387 pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");
\r
3388 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");
\r
3389 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");
\r
3390 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");
\r
3391 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");
\r
3392 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");
\r
3393 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");
\r
3394 pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "w");
\r
3395 pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "w");
\r
3396 pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3397 pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3398 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "w");
\r
3399 pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "w");
\r
3400 pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3401 pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3402 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "sp", squareSize, "w");
\r
3403 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "sn", squareSize, "w");
\r
3404 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3405 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3406 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "sl", squareSize, "w");
\r
3407 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3413 PieceBitmap(ChessSquare p, int kind)
\r
3415 if ((int) p >= (int) BlackPawn)
\r
3416 p = (ChessSquare) ((int) p - (int) BlackPawn + (int) WhitePawn);
\r
3418 return pieceBitmap[kind][(int) p];
\r
3421 /***************************************************************/
\r
3423 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
\r
3424 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
\r
3426 #define MIN3(a,b,c) (((a) < (b) && (a) < (c)) ? (a) : (((b) < (a) && (b) < (c)) ? (b) : (c)))
\r
3427 #define MAX3(a,b,c) (((a) > (b) && (a) > (c)) ? (a) : (((b) > (a) && (b) > (c)) ? (b) : (c)))
\r
3431 SquareToPos(int row, int column, int * x, int * y)
\r
3434 *x = boardRect.left + lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
\r
3435 *y = boardRect.top + lineGap + row * (squareSize + lineGap);
\r
3437 *x = boardRect.left + lineGap + column * (squareSize + lineGap);
\r
3438 *y = boardRect.top + lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
\r
3443 DrawCoordsOnDC(HDC hdc)
\r
3445 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
3446 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
3447 char str[2] = { NULLCHAR, NULLCHAR };
\r
3448 int oldMode, oldAlign, x, y, start, i;
\r
3452 if (!appData.showCoords)
\r
3455 start = flipView ? 1-(ONE!='1') : 23+(ONE!='1')-BOARD_HEIGHT;
\r
3457 oldBrush = SelectObject(hdc, GetStockObject(BLACK_BRUSH));
\r
3458 oldMode = SetBkMode(hdc, (appData.monoMode ? OPAQUE : TRANSPARENT));
\r
3459 oldAlign = GetTextAlign(hdc);
\r
3460 oldFont = SelectObject(hdc, font[boardSize][COORD_FONT]->hf);
\r
3462 y = boardRect.top + lineGap;
\r
3463 x = boardRect.left + lineGap + gameInfo.holdingsWidth*(squareSize + lineGap);
\r
3465 SetTextAlign(hdc, TA_LEFT|TA_TOP);
\r
3466 for (i = 0; i < BOARD_HEIGHT; i++) {
\r
3467 str[0] = files[start + i];
\r
3468 ExtTextOut(hdc, x + 2, y + 1, 0, NULL, str, 1, NULL);
\r
3469 y += squareSize + lineGap;
\r
3472 start = flipView ? 12-(BOARD_RGHT-BOARD_LEFT) : 12;
\r
3474 SetTextAlign(hdc, TA_RIGHT|TA_BOTTOM);
\r
3475 for (i = 0; i < BOARD_RGHT - BOARD_LEFT; i++) {
\r
3476 str[0] = ranks[start + i];
\r
3477 ExtTextOut(hdc, x + squareSize - 2, y - 1, 0, NULL, str, 1, NULL);
\r
3478 x += squareSize + lineGap;
\r
3481 SelectObject(hdc, oldBrush);
\r
3482 SetBkMode(hdc, oldMode);
\r
3483 SetTextAlign(hdc, oldAlign);
\r
3484 SelectObject(hdc, oldFont);
\r
3488 DrawGridOnDC(HDC hdc)
\r
3492 if (lineGap != 0) {
\r
3493 oldPen = SelectObject(hdc, gridPen);
\r
3494 PolyPolyline(hdc, gridEndpoints, gridVertexCounts, BOARD_WIDTH+BOARD_HEIGHT + 2);
\r
3495 SelectObject(hdc, oldPen);
\r
3499 #define HIGHLIGHT_PEN 0
\r
3500 #define PREMOVE_PEN 1
\r
3503 DrawHighlightOnDC(HDC hdc, BOOLEAN on, int x, int y, int pen)
\r
3506 HPEN oldPen, hPen;
\r
3507 if (lineGap == 0) return;
\r
3509 x1 = boardRect.left +
\r
3510 lineGap/2 + ((BOARD_WIDTH-1)-x) * (squareSize + lineGap);
\r
3511 y1 = boardRect.top +
\r
3512 lineGap/2 + y * (squareSize + lineGap);
\r
3514 x1 = boardRect.left +
\r
3515 lineGap/2 + x * (squareSize + lineGap);
\r
3516 y1 = boardRect.top +
\r
3517 lineGap/2 + ((BOARD_HEIGHT-1)-y) * (squareSize + lineGap);
\r
3519 hPen = pen ? premovePen : highlightPen;
\r
3520 oldPen = SelectObject(hdc, on ? hPen : gridPen);
\r
3521 MoveToEx(hdc, x1, y1, NULL);
\r
3522 LineTo(hdc, x1 + squareSize + lineGap, y1);
\r
3523 LineTo(hdc, x1 + squareSize + lineGap, y1 + squareSize + lineGap);
\r
3524 LineTo(hdc, x1, y1 + squareSize + lineGap);
\r
3525 LineTo(hdc, x1, y1);
\r
3526 SelectObject(hdc, oldPen);
\r
3530 DrawHighlightsOnDC(HDC hdc)
\r
3533 for (i=0; i<2; i++) {
\r
3534 if (highlightInfo.sq[i].x >= 0 && highlightInfo.sq[i].y >= 0)
\r
3535 DrawHighlightOnDC(hdc, TRUE,
\r
3536 highlightInfo.sq[i].x, highlightInfo.sq[i].y,
\r
3539 for (i=0; i<2; i++) {
\r
3540 if (premoveHighlightInfo.sq[i].x >= 0 &&
\r
3541 premoveHighlightInfo.sq[i].y >= 0) {
\r
3542 DrawHighlightOnDC(hdc, TRUE,
\r
3543 premoveHighlightInfo.sq[i].x,
\r
3544 premoveHighlightInfo.sq[i].y,
\r
3550 /* Note: sqcolor is used only in monoMode */
\r
3551 /* Note that this code is largely duplicated in woptions.c,
\r
3552 function DrawSampleSquare, so that needs to be updated too */
\r
3554 DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, HDC tmphdc)
\r
3556 HBITMAP oldBitmap;
\r
3560 if (appData.blindfold) return;
\r
3562 /* [AS] Use font-based pieces if needed */
\r
3563 if( fontBitmapSquareSize >= 0 && squareSize > 32 ) {
\r
3564 /* Create piece bitmaps, or do nothing if piece set is up to date */
\r
3565 CreatePiecesFromFont();
\r
3567 if( fontBitmapSquareSize == squareSize ) {
\r
3568 int index = TranslatePieceToFontPiece( piece );
\r
3570 SelectObject( tmphdc, hPieceMask[ index ] );
\r
3574 squareSize, squareSize,
\r
3579 SelectObject( tmphdc, hPieceFace[ index ] );
\r
3583 squareSize, squareSize,
\r
3592 if (appData.monoMode) {
\r
3593 SelectObject(tmphdc, PieceBitmap(piece,
\r
3594 color == sqcolor ? OUTLINE_PIECE : SOLID_PIECE));
\r
3595 BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0,
\r
3596 sqcolor ? SRCCOPY : NOTSRCCOPY);
\r
3598 tmpSize = squareSize;
\r
3600 (piece >= (int)WhiteNightrider && piece <= WhiteGrasshopper ||
\r
3601 piece >= (int)BlackNightrider && piece <= BlackGrasshopper) ) {
\r
3602 /* [HGM] no bitmap available for promoted pieces in Crazyhouse */
\r
3603 /* Bitmaps of smaller size are substituted, but we have to align them */
\r
3604 x += (squareSize - minorSize)>>1;
\r
3605 y += squareSize - minorSize - 2;
\r
3606 tmpSize = minorSize;
\r
3608 if (color || appData.allWhite ) {
\r
3609 oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, WHITE_PIECE));
\r
3611 oldBrush = SelectObject(hdc, whitePieceBrush);
\r
3612 else oldBrush = SelectObject(hdc, blackPieceBrush);
\r
3613 if(appData.upsideDown && color==flipView)
\r
3614 StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, 0x00B8074A);
\r
3616 BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);
\r
3618 /* Use black piece color for outline of white pieces */
\r
3619 /* Not sure this looks really good (though xboard does it).
\r
3620 Maybe better to have another selectable color, default black */
\r
3621 SelectObject(hdc, blackPieceBrush); /* could have own brush */
\r
3622 SelectObject(tmphdc, PieceBitmap(piece, OUTLINE_PIECE));
\r
3623 BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);
\r
3625 /* Use black for outline of white pieces */
\r
3626 SelectObject(tmphdc, PieceBitmap(piece, OUTLINE_PIECE));
\r
3627 if(appData.upsideDown && color==flipView)
\r
3628 StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, SRCAND);
\r
3630 BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, SRCAND);
\r
3634 /* Use white piece color for details of black pieces */
\r
3635 /* Requires filled-in solid bitmaps (BLACK_PIECE class); the
\r
3636 WHITE_PIECE ones aren't always the right shape. */
\r
3637 /* Not sure this looks really good (though xboard does it).
\r
3638 Maybe better to have another selectable color, default medium gray? */
\r
3639 oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, BLACK_PIECE));
\r
3640 oldBrush = SelectObject(hdc, whitePieceBrush); /* could have own brush */
\r
3641 BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);
\r
3642 SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE));
\r
3643 SelectObject(hdc, blackPieceBrush);
\r
3644 BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);
\r
3646 /* Use square color for details of black pieces */
\r
3647 oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE));
\r
3648 oldBrush = SelectObject(hdc, blackPieceBrush);
\r
3649 if(appData.upsideDown && !flipView)
\r
3650 StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, 0x00B8074A);
\r
3652 BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);
\r
3655 SelectObject(hdc, oldBrush);
\r
3656 SelectObject(tmphdc, oldBitmap);
\r