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, leftLogoRect, rightLogoRect; // [HGM] logo
\r
144 static int logoHeight = 0;
\r
145 static char messageText[MESSAGE_TEXT_MAX];
\r
146 static int clockTimerEvent = 0;
\r
147 static int loadGameTimerEvent = 0;
\r
148 static int analysisTimerEvent = 0;
\r
149 static DelayedEventCallback delayedTimerCallback;
\r
150 static int delayedTimerEvent = 0;
\r
151 static int buttonCount = 2;
\r
152 char *icsTextMenuString;
\r
154 char *firstChessProgramNames;
\r
155 char *secondChessProgramNames;
\r
157 #define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */
\r
159 #define PALETTESIZE 256
\r
161 HINSTANCE hInst; /* current instance */
\r
162 HWND hwndMain = NULL; /* root window*/
\r
163 HWND hwndConsole = NULL;
\r
164 BOOLEAN alwaysOnTop = FALSE;
\r
166 COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
\r
167 blackPieceColor, highlightSquareColor, premoveHighlightColor;
\r
169 ColorClass currentColorClass;
\r
171 HWND hCommPort = NULL; /* currently open comm port */
\r
172 static HWND hwndPause; /* pause button */
\r
173 static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */
\r
174 static HBRUSH lightSquareBrush, darkSquareBrush,
\r
175 blackSquareBrush, /* [HGM] for band between board and holdings */
\r
176 whitePieceBrush, blackPieceBrush, iconBkgndBrush, outlineBrush;
\r
177 static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];
\r
178 static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];
\r
179 static HPEN gridPen = NULL;
\r
180 static HPEN highlightPen = NULL;
\r
181 static HPEN premovePen = NULL;
\r
182 static NPLOGPALETTE pLogPal;
\r
183 static BOOL paletteChanged = FALSE;
\r
184 static HICON iconWhite, iconBlack, iconCurrent;
\r
185 static int doingSizing = FALSE;
\r
186 static int lastSizing = 0;
\r
187 static int prevStderrPort;
\r
189 /* [AS] Support for background textures */
\r
190 #define BACK_TEXTURE_MODE_DISABLED 0
\r
191 #define BACK_TEXTURE_MODE_PLAIN 1
\r
192 #define BACK_TEXTURE_MODE_FULL_RANDOM 2
\r
194 static HBITMAP liteBackTexture = NULL;
\r
195 static HBITMAP darkBackTexture = NULL;
\r
196 static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
197 static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
198 static int backTextureSquareSize = 0;
\r
199 static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_SIZE][BOARD_SIZE];
\r
201 #if __GNUC__ && !defined(_winmajor)
\r
202 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */
\r
204 #define oldDialog (_winmajor < 4)
\r
207 char *defaultTextAttribs[] =
\r
209 COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,
\r
210 COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,
\r
220 int cliWidth, cliHeight;
\r
223 SizeInfo sizeInfo[] =
\r
225 { "tiny", 21, 0, 1, 1, 0, 0 },
\r
226 { "teeny", 25, 1, 1, 1, 0, 0 },
\r
227 { "dinky", 29, 1, 1, 1, 0, 0 },
\r
228 { "petite", 33, 1, 1, 1, 0, 0 },
\r
229 { "slim", 37, 2, 1, 0, 0, 0 },
\r
230 { "small", 40, 2, 1, 0, 0, 0 },
\r
231 { "mediocre", 45, 2, 1, 0, 0, 0 },
\r
232 { "middling", 49, 2, 0, 0, 0, 0 },
\r
233 { "average", 54, 2, 0, 0, 0, 0 },
\r
234 { "moderate", 58, 3, 0, 0, 0, 0 },
\r
235 { "medium", 64, 3, 0, 0, 0, 0 },
\r
236 { "bulky", 72, 3, 0, 0, 0, 0 },
\r
237 { "large", 80, 3, 0, 0, 0, 0 },
\r
238 { "big", 87, 3, 0, 0, 0, 0 },
\r
239 { "huge", 95, 3, 0, 0, 0, 0 },
\r
240 { "giant", 108, 3, 0, 0, 0, 0 },
\r
241 { "colossal", 116, 4, 0, 0, 0, 0 },
\r
242 { "titanic", 129, 4, 0, 0, 0, 0 },
\r
243 { NULL, 0, 0, 0, 0, 0, 0 }
\r
246 #define MF(x) {x, {0, }, {0, }, 0}
\r
247 MyFont fontRec[NUM_SIZES][NUM_FONTS] =
\r
249 { 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
250 { 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
251 { 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
252 { 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
253 { 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
254 { 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
255 { 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
256 { 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
257 { 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
258 { 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
259 { 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
260 { 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
261 { 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
262 { 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
263 { 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
264 { 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
265 { 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
266 { 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
269 MyFont *font[NUM_SIZES][NUM_FONTS];
\r
278 #define BUTTON_WIDTH (tinyLayout ? 16 : 32)
\r
279 #define N_BUTTONS 5
\r
281 MyButtonDesc buttonDesc[N_BUTTONS] =
\r
283 {"<<", IDM_ToStart, NULL, NULL},
\r
284 {"<", IDM_Backward, NULL, NULL},
\r
285 {"P", IDM_Pause, NULL, NULL},
\r
286 {">", IDM_Forward, NULL, NULL},
\r
287 {">>", IDM_ToEnd, NULL, NULL},
\r
290 int tinyLayout = 0, smallLayout = 0;
\r
291 #define MENU_BAR_ITEMS 6
\r
292 char *menuBarText[2][MENU_BAR_ITEMS+1] = {
\r
293 { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },
\r
294 { "&F", "&M", "&A", "&S", "&O", "&H", NULL },
\r
298 MySound sounds[(int)NSoundClasses];
\r
299 MyTextAttribs textAttribs[(int)NColorClasses];
\r
301 MyColorizeAttribs colorizeAttribs[] = {
\r
302 { (COLORREF)0, 0, "Shout Text" },
\r
303 { (COLORREF)0, 0, "SShout/CShout" },
\r
304 { (COLORREF)0, 0, "Channel 1 Text" },
\r
305 { (COLORREF)0, 0, "Channel Text" },
\r
306 { (COLORREF)0, 0, "Kibitz Text" },
\r
307 { (COLORREF)0, 0, "Tell Text" },
\r
308 { (COLORREF)0, 0, "Challenge Text" },
\r
309 { (COLORREF)0, 0, "Request Text" },
\r
310 { (COLORREF)0, 0, "Seek Text" },
\r
311 { (COLORREF)0, 0, "Normal Text" },
\r
312 { (COLORREF)0, 0, "None" }
\r
317 static char *commentTitle;
\r
318 static char *commentText;
\r
319 static int commentIndex;
\r
320 static Boolean editComment = FALSE;
\r
321 HWND commentDialog = NULL;
\r
322 BOOLEAN commentDialogUp = FALSE;
\r
323 static int commentX, commentY, commentH, commentW;
\r
325 static char *analysisTitle;
\r
326 static char *analysisText;
\r
327 HWND analysisDialog = NULL;
\r
328 BOOLEAN analysisDialogUp = FALSE;
\r
329 static int analysisX, analysisY, analysisH, analysisW;
\r
331 char errorTitle[MSG_SIZ];
\r
332 char errorMessage[2*MSG_SIZ];
\r
333 HWND errorDialog = NULL;
\r
334 BOOLEAN moveErrorMessageUp = FALSE;
\r
335 BOOLEAN consoleEcho = TRUE;
\r
336 CHARFORMAT consoleCF;
\r
337 COLORREF consoleBackgroundColor;
\r
339 char *programVersion;
\r
345 typedef int CPKind;
\r
354 SOCKET sock2; /* stderr socket for OpenRcmd */
\r
357 #define INPUT_SOURCE_BUF_SIZE 4096
\r
359 typedef struct _InputSource {
\r
366 char buf[INPUT_SOURCE_BUF_SIZE];
\r
370 InputCallback func;
\r
371 struct _InputSource *second; /* for stderr thread on CPRcmd */
\r
375 InputSource *consoleInputSource;
\r
380 VOID ConsoleOutput(char* data, int length, int forceVisible);
\r
381 VOID ConsoleCreate();
\r
383 ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
384 VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
\r
385 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
\r
386 VOID ParseCommSettings(char *arg, DCB *dcb);
\r
388 StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
389 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
\r
390 void ParseIcsTextMenu(char *icsTextMenuString);
\r
391 VOID PopUpMoveDialog(char firstchar);
\r
392 VOID PopUpNameDialog(char firstchar);
\r
393 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
\r
397 int GameListOptions();
\r
399 HWND moveHistoryDialog = NULL;
\r
400 BOOLEAN moveHistoryDialogUp = FALSE;
\r
402 WindowPlacement wpMoveHistory;
\r
404 HWND evalGraphDialog = NULL;
\r
405 BOOLEAN evalGraphDialogUp = FALSE;
\r
407 WindowPlacement wpEvalGraph;
\r
409 HWND engineOutputDialog = NULL;
\r
410 BOOLEAN engineOutputDialogUp = FALSE;
\r
412 WindowPlacement wpEngineOutput;
\r
414 VOID MoveHistoryPopUp();
\r
415 VOID MoveHistoryPopDown();
\r
416 VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
417 BOOL MoveHistoryIsUp();
\r
419 VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
420 VOID EvalGraphPopUp();
\r
421 VOID EvalGraphPopDown();
\r
422 BOOL EvalGraphIsUp();
\r
424 VOID EngineOutputPopUp();
\r
425 VOID EngineOutputPopDown();
\r
426 BOOL EngineOutputIsUp();
\r
427 VOID EngineOutputUpdate( FrontEndProgramStats * stats );
\r
429 VOID GothicPopUp(char *title, VariantClass variant);
\r
431 * Setting "frozen" should disable all user input other than deleting
\r
432 * the window. We do this while engines are initializing themselves.
\r
434 static int frozen = 0;
\r
435 static int oldMenuItemState[MENU_BAR_ITEMS];
\r
441 if (frozen) return;
\r
443 hmenu = GetMenu(hwndMain);
\r
444 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
445 oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
\r
447 DrawMenuBar(hwndMain);
\r
450 /* Undo a FreezeUI */
\r
456 if (!frozen) return;
\r
458 hmenu = GetMenu(hwndMain);
\r
459 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
460 EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
\r
462 DrawMenuBar(hwndMain);
\r
465 /*---------------------------------------------------------------------------*\
\r
469 \*---------------------------------------------------------------------------*/
\r
472 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
\r
473 LPSTR lpCmdLine, int nCmdShow)
\r
476 HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
\r
480 LoadLibrary("RICHED32.DLL");
\r
481 consoleCF.cbSize = sizeof(CHARFORMAT);
\r
483 if (!InitApplication(hInstance)) {
\r
486 if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
\r
490 hAccelMain = LoadAccelerators (hInstance, szAppName);
\r
491 hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
\r
492 hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
\r
494 /* Acquire and dispatch messages until a WM_QUIT message is received. */
\r
496 while (GetMessage(&msg, /* message structure */
\r
497 NULL, /* handle of window receiving the message */
\r
498 0, /* lowest message to examine */
\r
499 0)) /* highest message to examine */
\r
501 if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
\r
502 !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
\r
503 !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
\r
504 !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
\r
505 !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
\r
506 !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
\r
507 !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
\r
508 !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) &&
\r
509 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
\r
510 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
\r
511 TranslateMessage(&msg); /* Translates virtual key codes */
\r
512 DispatchMessage(&msg); /* Dispatches message to window */
\r
517 return (msg.wParam); /* Returns the value from PostQuitMessage */
\r
520 /*---------------------------------------------------------------------------*\
\r
522 * Initialization functions
\r
524 \*---------------------------------------------------------------------------*/
\r
527 InitApplication(HINSTANCE hInstance)
\r
531 /* Fill in window class structure with parameters that describe the */
\r
534 wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
\r
535 wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
\r
536 wc.cbClsExtra = 0; /* No per-class extra data. */
\r
537 wc.cbWndExtra = 0; /* No per-window extra data. */
\r
538 wc.hInstance = hInstance; /* Owner of this class */
\r
539 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
540 wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
\r
541 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
\r
542 wc.lpszMenuName = szAppName; /* Menu name from .RC */
\r
543 wc.lpszClassName = szAppName; /* Name to register as */
\r
545 /* Register the window class and return success/failure code. */
\r
546 if (!RegisterClass(&wc)) return FALSE;
\r
548 wc.style = CS_HREDRAW | CS_VREDRAW;
\r
549 wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
\r
551 wc.cbWndExtra = DLGWINDOWEXTRA;
\r
552 wc.hInstance = hInstance;
\r
553 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
554 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
\r
555 wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
\r
556 wc.lpszMenuName = NULL;
\r
557 wc.lpszClassName = szConsoleName;
\r
559 if (!RegisterClass(&wc)) return FALSE;
\r
564 /* Set by InitInstance, used by EnsureOnScreen */
\r
565 int screenHeight, screenWidth;
\r
568 EnsureOnScreen(int *x, int *y)
\r
570 int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
\r
571 /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
\r
572 if (*x > screenWidth - 32) *x = 0;
\r
573 if (*y > screenHeight - 32) *y = 0;
\r
574 if (*x < 10) *x = 10;
\r
575 if (*y < gap) *y = gap;
\r
579 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
\r
581 HWND hwnd; /* Main window handle. */
\r
583 WINDOWPLACEMENT wp;
\r
586 hInst = hInstance; /* Store instance handle in our global variable */
\r
588 if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
\r
589 *filepart = NULLCHAR;
\r
591 GetCurrentDirectory(MSG_SIZ, installDir);
\r
593 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise
\r
594 InitAppData(lpCmdLine); /* Get run-time parameters */
\r
595 if (appData.debugMode) {
\r
596 debugFP = fopen(appData.nameOfDebugFile, "w");
\r
597 setbuf(debugFP, NULL);
\r
602 // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()
\r
603 // InitEngineUCI( installDir, &second );
\r
605 /* Create a main window for this application instance. */
\r
606 hwnd = CreateWindow(szAppName, szTitle,
\r
607 (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
\r
608 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
\r
609 NULL, NULL, hInstance, NULL);
\r
612 /* If window could not be created, return "failure" */
\r
617 /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */
\r
618 if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {
\r
619 first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
621 if (first.programLogo == NULL && appData.debugMode) {
\r
622 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );
\r
624 } else if(appData.autoLogo) {
\r
625 if(appData.firstDirectory && appData.firstDirectory[0]) {
\r
627 sprintf(buf, "%s/logo.bmp", appData.firstDirectory);
\r
628 first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
632 if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {
\r
633 second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
635 if (second.programLogo == NULL && appData.debugMode) {
\r
636 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );
\r
638 } else if(appData.autoLogo) {
\r
639 if(appData.secondDirectory && appData.secondDirectory[0]) {
\r
641 sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);
\r
642 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
646 iconWhite = LoadIcon(hInstance, "icon_white");
\r
647 iconBlack = LoadIcon(hInstance, "icon_black");
\r
648 iconCurrent = iconWhite;
\r
649 InitDrawingColors();
\r
650 screenHeight = GetSystemMetrics(SM_CYSCREEN);
\r
651 screenWidth = GetSystemMetrics(SM_CXSCREEN);
\r
652 for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
\r
653 /* Compute window size for each board size, and use the largest
\r
654 size that fits on this screen as the default. */
\r
655 InitDrawingSizes((BoardSize)ibs, 0);
\r
656 if (boardSize == (BoardSize)-1 &&
\r
657 winHeight <= screenHeight
\r
658 - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10
\r
659 && winWidth <= screenWidth) {
\r
660 boardSize = (BoardSize)ibs;
\r
664 InitDrawingSizes(boardSize, 0);
\r
666 buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
\r
668 /* [AS] Load textures if specified */
\r
669 ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );
\r
671 if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {
\r
672 liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
673 liteBackTextureMode = appData.liteBackTextureMode;
\r
675 if (liteBackTexture == NULL && appData.debugMode) {
\r
676 fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );
\r
680 if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {
\r
681 darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
682 darkBackTextureMode = appData.darkBackTextureMode;
\r
684 if (darkBackTexture == NULL && appData.debugMode) {
\r
685 fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );
\r
689 mysrandom( (unsigned) time(NULL) );
\r
691 /* [AS] Restore layout */
\r
692 if( wpMoveHistory.visible ) {
\r
693 MoveHistoryPopUp();
\r
696 if( wpEvalGraph.visible ) {
\r
700 if( wpEngineOutput.visible ) {
\r
701 EngineOutputPopUp();
\r
706 /* Make the window visible; update its client area; and return "success" */
\r
707 EnsureOnScreen(&boardX, &boardY);
\r
708 wp.length = sizeof(WINDOWPLACEMENT);
\r
710 wp.showCmd = nCmdShow;
\r
711 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
\r
712 wp.rcNormalPosition.left = boardX;
\r
713 wp.rcNormalPosition.right = boardX + winWidth;
\r
714 wp.rcNormalPosition.top = boardY;
\r
715 wp.rcNormalPosition.bottom = boardY + winHeight;
\r
716 SetWindowPlacement(hwndMain, &wp);
\r
718 SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
719 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
722 /* [AS] Disable the FRC stuff if not playing the proper variant */
\r
723 if( gameInfo.variant != VariantFischeRandom ) {
\r
724 EnableMenuItem( GetMenu(hwndMain), IDM_NewGameFRC, MF_GRAYED );
\r
729 SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
730 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
732 ShowWindow(hwndConsole, nCmdShow);
\r
734 UpdateWindow(hwnd);
\r
742 ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
\r
743 ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
\r
744 ArgSettingsFilename
\r
752 String *pString; // ArgString
\r
753 int *pInt; // ArgInt
\r
754 float *pFloat; // ArgFloat
\r
755 Boolean *pBoolean; // ArgBoolean
\r
756 COLORREF *pColor; // ArgColor
\r
757 ColorClass cc; // ArgAttribs
\r
758 String *pFilename; // ArgFilename
\r
759 BoardSize *pBoardSize; // ArgBoardSize
\r
760 int whichFont; // ArgFont
\r
761 DCB *pDCB; // ArgCommSettings
\r
762 String *pFilename; // ArgSettingsFilename
\r
770 ArgDescriptor argDescriptors[] = {
\r
771 /* positional arguments */
\r
772 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
773 { "", ArgNone, NULL },
\r
774 /* keyword arguments */
\r
775 { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },
\r
776 { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },
\r
777 { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },
\r
778 { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },
\r
779 { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },
\r
780 { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },
\r
781 { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },
\r
782 { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },
\r
783 { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },
\r
784 { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },
\r
785 { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },
\r
786 { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },
\r
787 { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },
\r
788 { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },
\r
789 { "initString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
790 { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
791 { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },
\r
792 { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,
\r
794 { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,
\r
796 { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,
\r
798 { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },
\r
799 { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,
\r
801 { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },
\r
802 { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
803 { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
804 { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
805 { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
806 { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },
\r
807 { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },
\r
808 { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
809 { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
810 { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
811 { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
812 { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
813 { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
814 { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
815 { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
816 { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
817 { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
818 /*!!bitmapDirectory?*/
\r
819 { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
820 { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
821 { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
822 { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
823 { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },
\r
824 { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },
\r
825 { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },
\r
826 { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },
\r
827 { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },
\r
828 { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },
\r
829 { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },
\r
830 { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },
\r
831 { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
832 { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
833 { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
834 { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
835 { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
836 { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
837 { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
838 { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
839 { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
840 { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
841 { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
842 { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
843 { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },
\r
844 { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },
\r
845 { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
846 { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
847 { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },
\r
848 { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },
\r
849 { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },
\r
850 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
851 { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
852 { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
853 { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
854 { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },
\r
855 { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },
\r
856 { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },
\r
857 { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },
\r
858 { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
859 { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
860 { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
861 { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
862 { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
863 { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
864 { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
865 { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
866 { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },
\r
867 { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },
\r
868 { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
869 { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
870 { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
871 { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
872 { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },
\r
873 { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },
\r
874 { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
875 { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
876 { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },
\r
877 { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },
\r
878 { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
879 { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
880 { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },
\r
881 { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },
\r
882 { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
883 { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
884 { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
885 { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
886 { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
887 { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
888 { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },
\r
889 { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },
\r
890 { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
891 { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
892 { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },
\r
893 { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },
\r
894 { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
895 { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
896 { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },
\r
897 { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },
\r
898 { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
899 { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
900 { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },
\r
901 { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },
\r
902 { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
903 { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
904 { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },
\r
905 { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },
\r
906 { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
907 { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
908 { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },
\r
909 { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
910 { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
911 { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
912 { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors,
\r
913 FALSE }, /* only so that old WinBoard.ini files from betas can be read */
\r
914 { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },
\r
915 { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },
\r
916 { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },
\r
917 { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },
\r
918 { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },
\r
919 { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },
\r
920 { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE }, /* [AS] */
\r
921 { "boardSize", ArgBoardSize, (LPVOID) &boardSize,
\r
922 TRUE }, /* must come after all fonts */
\r
923 { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },
\r
924 { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,
\r
925 FALSE }, /* historical; kept only so old winboard.ini files will parse */
\r
926 { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },
\r
927 { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },
\r
928 { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
929 { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
930 { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },
\r
931 { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },
\r
932 { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
933 { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
934 { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },
\r
935 { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },
\r
936 { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
937 { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
938 { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },
\r
939 { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },
\r
940 { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
941 { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
942 { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },
\r
943 { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },
\r
944 { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
945 { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
946 { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },
\r
947 { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },
\r
948 { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
949 { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
950 { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },
\r
951 { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
952 { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
953 { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
955 { "cmailGameName", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
956 { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
958 { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },
\r
959 { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
960 { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
961 { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
962 { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },
\r
963 { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
964 { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
965 { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
966 { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },
\r
967 { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },
\r
968 { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
969 { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
970 { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },
\r
971 { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },
\r
972 { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
973 { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
974 { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },
\r
975 { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },
\r
976 { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
977 { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
978 { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },
\r
979 { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },
\r
980 { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
981 { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
982 { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },
\r
983 { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },
\r
984 { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
985 { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
986 { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },
\r
987 { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },
\r
988 { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },
\r
989 { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
990 { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
991 { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },
\r
992 { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},
\r
993 { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},
\r
994 { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
995 { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
996 { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},
\r
997 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
998 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
999 { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },
\r
1000 { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1001 { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1002 { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },
\r
1003 { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },
\r
1004 { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1005 { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1006 { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },
\r
1007 { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },
\r
1008 { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },
\r
1009 { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1010 { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1011 { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },
\r
1012 { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },
\r
1013 { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1014 { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1015 { "highlightLastMove", ArgBoolean,
\r
1016 (LPVOID) &appData.highlightLastMove, TRUE },
\r
1017 { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1018 { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1019 { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1020 { "highlightDragging", ArgBoolean,
\r
1021 (LPVOID) &appData.highlightDragging, TRUE },
\r
1022 { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },
\r
1023 { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1024 { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1025 { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },
\r
1026 { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },
\r
1027 { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1028 { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1029 { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },
\r
1030 { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },
\r
1031 { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },
\r
1032 { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },
\r
1033 { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },
\r
1034 { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },
\r
1035 { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },
\r
1036 { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },
\r
1037 { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },
\r
1038 { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },
\r
1039 { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },
\r
1040 { "soundShout", ArgFilename,
\r
1041 (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },
\r
1042 { "soundSShout", ArgFilename,
\r
1043 (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },
\r
1044 { "soundChannel1", ArgFilename,
\r
1045 (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },
\r
1046 { "soundChannel", ArgFilename,
\r
1047 (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },
\r
1048 { "soundKibitz", ArgFilename,
\r
1049 (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },
\r
1050 { "soundTell", ArgFilename,
\r
1051 (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },
\r
1052 { "soundChallenge", ArgFilename,
\r
1053 (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },
\r
1054 { "soundRequest", ArgFilename,
\r
1055 (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },
\r
1056 { "soundSeek", ArgFilename,
\r
1057 (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },
\r
1058 { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },
\r
1059 { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },
\r
1060 { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },
\r
1061 { "soundIcsLoss", ArgFilename,
\r
1062 (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },
\r
1063 { "soundIcsDraw", ArgFilename,
\r
1064 (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },
\r
1065 { "soundIcsUnfinished", ArgFilename,
\r
1066 (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},
\r
1067 { "soundIcsAlarm", ArgFilename,
\r
1068 (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },
\r
1069 { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },
\r
1070 { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },
\r
1071 { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1072 { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1073 { "reuseChessPrograms", ArgBoolean,
\r
1074 (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */
\r
1075 { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },
\r
1076 { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },
\r
1077 { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1078 { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1079 { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },
\r
1080 { "x", ArgInt, (LPVOID) &boardX, TRUE },
\r
1081 { "y", ArgInt, (LPVOID) &boardY, TRUE },
\r
1082 { "icsX", ArgInt, (LPVOID) &consoleX, TRUE },
\r
1083 { "icsY", ArgInt, (LPVOID) &consoleY, TRUE },
\r
1084 { "icsW", ArgInt, (LPVOID) &consoleW, TRUE },
\r
1085 { "icsH", ArgInt, (LPVOID) &consoleH, TRUE },
\r
1086 { "analysisX", ArgInt, (LPVOID) &analysisX, TRUE },
\r
1087 { "analysisY", ArgInt, (LPVOID) &analysisY, TRUE },
\r
1088 { "analysisW", ArgInt, (LPVOID) &analysisW, TRUE },
\r
1089 { "analysisH", ArgInt, (LPVOID) &analysisH, TRUE },
\r
1090 { "commentX", ArgInt, (LPVOID) &commentX, TRUE },
\r
1091 { "commentY", ArgInt, (LPVOID) &commentY, TRUE },
\r
1092 { "commentW", ArgInt, (LPVOID) &commentW, TRUE },
\r
1093 { "commentH", ArgInt, (LPVOID) &commentH, TRUE },
\r
1094 { "tagsX", ArgInt, (LPVOID) &editTagsX, TRUE },
\r
1095 { "tagsY", ArgInt, (LPVOID) &editTagsY, TRUE },
\r
1096 { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },
\r
1097 { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },
\r
1098 { "gameListX", ArgInt, (LPVOID) &gameListX, TRUE },
\r
1099 { "gameListY", ArgInt, (LPVOID) &gameListY, TRUE },
\r
1100 { "gameListW", ArgInt, (LPVOID) &gameListW, TRUE },
\r
1101 { "gameListH", ArgInt, (LPVOID) &gameListH, TRUE },
\r
1102 { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1103 { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1104 { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },
\r
1105 { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },
\r
1106 { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },
\r
1107 { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1108 { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1109 { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },
\r
1110 { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },
\r
1111 { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,
\r
1113 { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,
\r
1115 { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1116 { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1117 { "variant", ArgString, (LPVOID) &appData.variant, FALSE },
\r
1118 { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion, FALSE },
\r
1119 { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,FALSE },
\r
1120 { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },
\r
1121 { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },
\r
1122 { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1123 { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1124 /* [AS] New features */
\r
1125 { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE },
\r
1126 { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE },
\r
1127 { "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE },
\r
1128 { "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE },
\r
1129 { "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE },
\r
1130 { "darkBackTextureFile", ArgString, (LPVOID) &appData.darkBackTextureFile, TRUE },
\r
1131 { "liteBackTextureMode", ArgInt, (LPVOID) &appData.liteBackTextureMode, TRUE },
\r
1132 { "darkBackTextureMode", ArgInt, (LPVOID) &appData.darkBackTextureMode, TRUE },
\r
1133 { "renderPiecesWithFont", ArgString, (LPVOID) &appData.renderPiecesWithFont, TRUE },
\r
1134 { "fontPieceToCharTable", ArgString, (LPVOID) &appData.fontToPieceTable, TRUE },
\r
1135 { "fontPieceBackColorWhite", ArgColor, (LPVOID) &appData.fontBackColorWhite, TRUE },
\r
1136 { "fontPieceForeColorWhite", ArgColor, (LPVOID) &appData.fontForeColorWhite, TRUE },
\r
1137 { "fontPieceBackColorBlack", ArgColor, (LPVOID) &appData.fontBackColorBlack, TRUE },
\r
1138 { "fontPieceForeColorBlack", ArgColor, (LPVOID) &appData.fontForeColorBlack, TRUE },
\r
1139 { "fontPieceSize", ArgInt, (LPVOID) &appData.fontPieceSize, TRUE },
\r
1140 { "overrideLineGap", ArgInt, (LPVOID) &appData.overrideLineGap, TRUE },
\r
1141 { "adjudicateLossThreshold", ArgInt, (LPVOID) &appData.adjudicateLossThreshold, TRUE },
\r
1142 { "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE },
\r
1143 { "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE },
\r
1144 { "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1145 { "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1146 { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },
\r
1147 { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE },
\r
1148 { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE },
\r
1149 { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE },
\r
1150 { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE },
\r
1151 { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE },
\r
1152 { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE },
\r
1153 { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE },
\r
1154 { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE },
\r
1155 { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE },
\r
1156 { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE },
\r
1157 { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE },
\r
1158 { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE },
\r
1159 { "firstIsUCI", ArgBoolean, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1160 { "fUCI", ArgTrue, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1161 { "secondIsUCI", ArgBoolean, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1162 { "sUCI", ArgTrue, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1163 { "firstHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1164 { "fNoOwnBookUCI", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1165 { "secondHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1166 { "sNoOwnBookUCI", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1167 { "polyglotDir", ArgFilename, (LPVOID) &appData.polyglotDir, TRUE },
\r
1168 { "usePolyglotBook", ArgBoolean, (LPVOID) &appData.usePolyglotBook, TRUE },
\r
1169 { "polyglotBook", ArgFilename, (LPVOID) &appData.polyglotBook, TRUE },
\r
1170 { "defaultHashSize", ArgInt, (LPVOID) &appData.defaultHashSize, TRUE },
\r
1171 { "defaultCacheSizeEGTB", ArgInt, (LPVOID) &appData.defaultCacheSizeEGTB, TRUE },
\r
1172 { "defaultPathEGTB", ArgFilename, (LPVOID) &appData.defaultPathEGTB, TRUE },
\r
1174 /* [AS] Layout stuff */
\r
1175 { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },
\r
1176 { "moveHistoryX", ArgInt, (LPVOID) &wpMoveHistory.x, TRUE },
\r
1177 { "moveHistoryY", ArgInt, (LPVOID) &wpMoveHistory.y, TRUE },
\r
1178 { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },
\r
1179 { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },
\r
1181 { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },
\r
1182 { "evalGraphX", ArgInt, (LPVOID) &wpEvalGraph.x, TRUE },
\r
1183 { "evalGraphY", ArgInt, (LPVOID) &wpEvalGraph.y, TRUE },
\r
1184 { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },
\r
1185 { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },
\r
1187 { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },
\r
1188 { "engineOutputX", ArgInt, (LPVOID) &wpEngineOutput.x, TRUE },
\r
1189 { "engineOutputY", ArgInt, (LPVOID) &wpEngineOutput.y, TRUE },
\r
1190 { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },
\r
1191 { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },
\r
1193 /* [HGM] board-size, adjudication and misc. options */
\r
1194 { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE },
\r
1195 { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE },
\r
1196 { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE },
\r
1197 { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE },
\r
1198 { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE },
\r
1199 { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE },
\r
1200 { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE },
\r
1201 { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE },
\r
1202 { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE },
\r
1203 { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE },
\r
1204 { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE },
\r
1205 { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE },
\r
1206 { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE },
\r
1207 { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE },
\r
1208 { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE },
\r
1209 { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE },
\r
1210 { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE },
\r
1211 { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE },
\r
1212 { "userName", ArgString, (LPVOID) &appData.userName, FALSE },
\r
1213 { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE },
\r
1214 { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE },
\r
1215 { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE },
\r
1216 { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE },
\r
1217 { "niceEngines", ArgInt, (LPVOID) &appData.niceEngines, TRUE },
\r
1218 { "firstLogo", ArgFilename, (LPVOID) &appData.firstLogo, FALSE },
\r
1219 { "secondLogo", ArgFilename, (LPVOID) &appData.secondLogo, FALSE },
\r
1220 { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE },
\r
1223 { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },
\r
1224 { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },
\r
1225 { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1226 { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1227 { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },
\r
1228 { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },
\r
1229 { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1230 { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1231 { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },
\r
1232 { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },
\r
1233 { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },
\r
1234 { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE },
\r
1235 { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,
\r
1237 { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE },
\r
1238 { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE },
\r
1239 { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE },
\r
1240 { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1241 { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1242 { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE },
\r
1243 { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,
\r
1245 { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1246 { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1247 { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1248 { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE },
\r
1249 { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE },
\r
1250 { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1251 { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1252 { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1253 { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1254 { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE },
\r
1255 { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE },
\r
1256 { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1257 { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1258 { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },
\r
1259 { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },
\r
1260 { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },
\r
1261 /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */
\r
1262 { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },
\r
1264 /* [HGM] options for broadcasting and time odds */
\r
1265 { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },
\r
1266 { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },
\r
1267 { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },
\r
1268 { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },
\r
1269 { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },
\r
1270 { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },
\r
1271 { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },
\r
1272 { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },
\r
1273 { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },
\r
1274 { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },
\r
1275 { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE },
\r
1276 { NULL, ArgNone, NULL, FALSE }
\r
1280 /* Kludge for indirection files on command line */
\r
1281 char* lastIndirectionFilename;
\r
1282 ArgDescriptor argDescriptorIndirection =
\r
1283 { "", ArgSettingsFilename, (LPVOID) NULL, FALSE };
\r
1287 ExitArgError(char *msg, char *badArg)
\r
1289 char buf[MSG_SIZ];
\r
1291 sprintf(buf, "%s %s", msg, badArg);
\r
1292 DisplayFatalError(buf, 0, 2);
\r
1296 /* Command line font name parser. NULL name means do nothing.
\r
1297 Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"
\r
1298 For backward compatibility, syntax without the colon is also
\r
1299 accepted, but font names with digits in them won't work in that case.
\r
1302 ParseFontName(char *name, MyFontParams *mfp)
\r
1305 if (name == NULL) return;
\r
1307 q = strchr(p, ':');
\r
1309 if (q - p >= sizeof(mfp->faceName))
\r
1310 ExitArgError("Font name too long:", name);
\r
1311 memcpy(mfp->faceName, p, q - p);
\r
1312 mfp->faceName[q - p] = NULLCHAR;
\r
1315 q = mfp->faceName;
\r
1316 while (*p && !isdigit(*p)) {
\r
1318 if (q - mfp->faceName >= sizeof(mfp->faceName))
\r
1319 ExitArgError("Font name too long:", name);
\r
1321 while (q > mfp->faceName && q[-1] == ' ') q--;
\r
1324 if (!*p) ExitArgError("Font point size missing:", name);
\r
1325 mfp->pointSize = (float) atof(p);
\r
1326 mfp->bold = (strchr(p, 'b') != NULL);
\r
1327 mfp->italic = (strchr(p, 'i') != NULL);
\r
1328 mfp->underline = (strchr(p, 'u') != NULL);
\r
1329 mfp->strikeout = (strchr(p, 's') != NULL);
\r
1332 /* Color name parser.
\r
1333 X version accepts X color names, but this one
\r
1334 handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */
\r
1336 ParseColorName(char *name)
\r
1338 int red, green, blue, count;
\r
1339 char buf[MSG_SIZ];
\r
1341 count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);
\r
1343 count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d",
\r
1344 &red, &green, &blue);
\r
1347 sprintf(buf, "Can't parse color name %s", name);
\r
1348 DisplayError(buf, 0);
\r
1349 return RGB(0, 0, 0);
\r
1351 return PALETTERGB(red, green, blue);
\r
1355 void ParseAttribs(COLORREF *color, int *effects, char* argValue)
\r
1357 char *e = argValue;
\r
1361 if (*e == 'b') eff |= CFE_BOLD;
\r
1362 else if (*e == 'i') eff |= CFE_ITALIC;
\r
1363 else if (*e == 'u') eff |= CFE_UNDERLINE;
\r
1364 else if (*e == 's') eff |= CFE_STRIKEOUT;
\r
1365 else if (*e == '#' || isdigit(*e)) break;
\r
1369 *color = ParseColorName(e);
\r
1374 ParseBoardSize(char *name)
\r
1376 BoardSize bs = SizeTiny;
\r
1377 while (sizeInfo[bs].name != NULL) {
\r
1378 if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;
\r
1381 ExitArgError("Unrecognized board size value", name);
\r
1382 return bs; /* not reached */
\r
1387 StringGet(void *getClosure)
\r
1389 char **p = (char **) getClosure;
\r
1394 FileGet(void *getClosure)
\r
1397 FILE* f = (FILE*) getClosure;
\r
1406 /* Parse settings file named "name". If file found, return the
\r
1407 full name in fullname and return TRUE; else return FALSE */
\r
1409 ParseSettingsFile(char *name, char fullname[MSG_SIZ])
\r
1414 if (SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy)) {
\r
1415 f = fopen(fullname, "r");
\r
1417 ParseArgs(FileGet, f);
\r
1426 ParseArgs(GetFunc get, void *cl)
\r
1428 char argName[ARG_MAX];
\r
1429 char argValue[ARG_MAX];
\r
1430 ArgDescriptor *ad;
\r
1439 while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);
\r
1440 if (ch == NULLCHAR) break;
\r
1442 /* Comment to end of line */
\r
1444 while (ch != '\n' && ch != NULLCHAR) ch = get(cl);
\r
1446 } else if (ch == '/' || ch == '-') {
\r
1449 while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&
\r
1450 ch != '\n' && ch != '\t') {
\r
1456 for (ad = argDescriptors; ad->argName != NULL; ad++)
\r
1457 if (strcmp(ad->argName, argName + 1) == 0) break;
\r
1459 if (ad->argName == NULL)
\r
1460 ExitArgError("Unrecognized argument", argName);
\r
1462 } else if (ch == '@') {
\r
1463 /* Indirection file */
\r
1464 ad = &argDescriptorIndirection;
\r
1467 /* Positional argument */
\r
1468 ad = &argDescriptors[posarg++];
\r
1469 strcpy(argName, ad->argName);
\r
1472 if (ad->argType == ArgTrue) {
\r
1473 *(Boolean *) ad->argLoc = TRUE;
\r
1476 if (ad->argType == ArgFalse) {
\r
1477 *(Boolean *) ad->argLoc = FALSE;
\r
1481 while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
\r
1482 if (ch == NULLCHAR || ch == '\n') {
\r
1483 ExitArgError("No value provided for argument", argName);
\r
1487 // Quoting with { }. No characters have to (or can) be escaped.
\r
1488 // Thus the string cannot contain a '}' character.
\r
1508 } else if (ch == '\'' || ch == '"') {
\r
1509 // Quoting with ' ' or " ", with \ as escape character.
\r
1510 // Inconvenient for long strings that may contain Windows filenames.
\r
1527 if (ch == start) {
\r
1536 if (ad->argType == ArgFilename
\r
1537 || ad->argType == ArgSettingsFilename) {
\r
1543 ExitArgError("Incomplete \\ escape in value for", argName);
\r
1567 for (i = 0; i < 3; i++) {
\r
1568 if (ch >= '0' && ch <= '7') {
\r
1569 octval = octval*8 + (ch - '0');
\r
1576 *q++ = (char) octval;
\r
1587 while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {
\r
1594 switch (ad->argType) {
\r
1596 *(int *) ad->argLoc = atoi(argValue);
\r
1600 *(float *) ad->argLoc = (float) atof(argValue);
\r
1605 *(char **) ad->argLoc = strdup(argValue);
\r
1608 case ArgSettingsFilename:
\r
1610 char fullname[MSG_SIZ];
\r
1611 if (ParseSettingsFile(argValue, fullname)) {
\r
1612 if (ad->argLoc != NULL) {
\r
1613 *(char **) ad->argLoc = strdup(fullname);
\r
1616 if (ad->argLoc != NULL) {
\r
1618 ExitArgError("Failed to open indirection file", argValue);
\r
1625 switch (argValue[0]) {
\r
1628 *(Boolean *) ad->argLoc = TRUE;
\r
1632 *(Boolean *) ad->argLoc = FALSE;
\r
1635 ExitArgError("Unrecognized boolean argument value", argValue);
\r
1641 *(COLORREF *)ad->argLoc = ParseColorName(argValue);
\r
1644 case ArgAttribs: {
\r
1645 ColorClass cc = (ColorClass)ad->argLoc;
\r
1646 ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);
\r
1650 case ArgBoardSize:
\r
1651 *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);
\r
1655 ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);
\r
1658 case ArgCommSettings:
\r
1659 ParseCommSettings(argValue, &dcb);
\r
1663 ExitArgError("Unrecognized argument", argValue);
\r
1670 LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
\r
1672 HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
\r
1673 lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);
\r
1676 lf->lfEscapement = 0;
\r
1677 lf->lfOrientation = 0;
\r
1678 lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;
\r
1679 lf->lfItalic = mfp->italic;
\r
1680 lf->lfUnderline = mfp->underline;
\r
1681 lf->lfStrikeOut = mfp->strikeout;
\r
1682 lf->lfCharSet = DEFAULT_CHARSET;
\r
1683 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
1684 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
1685 lf->lfQuality = DEFAULT_QUALITY;
\r
1686 lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
\r
1687 strcpy(lf->lfFaceName, mfp->faceName);
\r
1691 CreateFontInMF(MyFont *mf)
\r
1693 LFfromMFP(&mf->lf, &mf->mfp);
\r
1694 if (mf->hf) DeleteObject(mf->hf);
\r
1695 mf->hf = CreateFontIndirect(&mf->lf);
\r
1699 SetDefaultTextAttribs()
\r
1702 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1703 ParseAttribs(&textAttribs[cc].color,
\r
1704 &textAttribs[cc].effects,
\r
1705 defaultTextAttribs[cc]);
\r
1710 SetDefaultSounds()
\r
1714 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1715 textAttribs[cc].sound.name = strdup("");
\r
1716 textAttribs[cc].sound.data = NULL;
\r
1718 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1719 sounds[sc].name = strdup("");
\r
1720 sounds[sc].data = NULL;
\r
1722 sounds[(int)SoundBell].name = strdup(SOUND_BELL);
\r
1730 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1731 MyLoadSound(&textAttribs[cc].sound);
\r
1733 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1734 MyLoadSound(&sounds[sc]);
\r
1739 InitAppData(LPSTR lpCmdLine)
\r
1742 char buf[ARG_MAX], currDir[MSG_SIZ];
\r
1745 programName = szAppName;
\r
1747 /* Initialize to defaults */
\r
1748 lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);
\r
1749 darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);
\r
1750 whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);
\r
1751 blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);
\r
1752 highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);
\r
1753 premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);
\r
1754 consoleBackgroundColor = ParseColorName(COLOR_BKGD);
\r
1755 SetDefaultTextAttribs();
\r
1756 SetDefaultSounds();
\r
1757 appData.movesPerSession = MOVES_PER_SESSION;
\r
1758 appData.initString = INIT_STRING;
\r
1759 appData.secondInitString = INIT_STRING;
\r
1760 appData.firstComputerString = COMPUTER_STRING;
\r
1761 appData.secondComputerString = COMPUTER_STRING;
\r
1762 appData.firstChessProgram = FIRST_CHESS_PROGRAM;
\r
1763 appData.secondChessProgram = SECOND_CHESS_PROGRAM;
\r
1764 appData.firstPlaysBlack = FALSE;
\r
1765 appData.noChessProgram = FALSE;
\r
1766 chessProgram = FALSE;
\r
1767 appData.firstHost = FIRST_HOST;
\r
1768 appData.secondHost = SECOND_HOST;
\r
1769 appData.firstDirectory = FIRST_DIRECTORY;
\r
1770 appData.secondDirectory = SECOND_DIRECTORY;
\r
1771 appData.bitmapDirectory = "";
\r
1772 appData.remoteShell = REMOTE_SHELL;
\r
1773 appData.remoteUser = "";
\r
1774 appData.timeDelay = TIME_DELAY;
\r
1775 appData.timeControl = TIME_CONTROL;
\r
1776 appData.timeIncrement = TIME_INCREMENT;
\r
1777 appData.icsActive = FALSE;
\r
1778 appData.icsHost = "";
\r
1779 appData.icsPort = ICS_PORT;
\r
1780 appData.icsCommPort = ICS_COMM_PORT;
\r
1781 appData.icsLogon = ICS_LOGON;
\r
1782 appData.icsHelper = "";
\r
1783 appData.useTelnet = FALSE;
\r
1784 appData.telnetProgram = TELNET_PROGRAM;
\r
1785 appData.gateway = "";
\r
1786 appData.loadGameFile = "";
\r
1787 appData.loadGameIndex = 0;
\r
1788 appData.saveGameFile = "";
\r
1789 appData.autoSaveGames = FALSE;
\r
1790 appData.loadPositionFile = "";
\r
1791 appData.loadPositionIndex = 1;
\r
1792 appData.savePositionFile = "";
\r
1793 appData.matchMode = FALSE;
\r
1794 appData.matchGames = 0;
\r
1795 appData.monoMode = FALSE;
\r
1796 appData.debugMode = FALSE;
\r
1797 appData.clockMode = TRUE;
\r
1798 boardSize = (BoardSize) -1; /* determine by screen size */
\r
1799 appData.Iconic = FALSE; /*unused*/
\r
1800 appData.searchTime = "";
\r
1801 appData.searchDepth = 0;
\r
1802 appData.showCoords = FALSE;
\r
1803 appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/
\r
1804 appData.autoCallFlag = FALSE;
\r
1805 appData.flipView = FALSE;
\r
1806 appData.autoFlipView = TRUE;
\r
1807 appData.cmailGameName = "";
\r
1808 appData.alwaysPromoteToQueen = FALSE;
\r
1809 appData.oldSaveStyle = FALSE;
\r
1810 appData.quietPlay = FALSE;
\r
1811 appData.showThinking = FALSE;
\r
1812 appData.ponderNextMove = TRUE;
\r
1813 appData.periodicUpdates = TRUE;
\r
1814 appData.popupExitMessage = TRUE;
\r
1815 appData.popupMoveErrors = FALSE;
\r
1816 appData.autoObserve = FALSE;
\r
1817 appData.autoComment = FALSE;
\r
1818 appData.animate = TRUE;
\r
1819 appData.animSpeed = 10;
\r
1820 appData.animateDragging = TRUE;
\r
1821 appData.highlightLastMove = TRUE;
\r
1822 appData.getMoveList = TRUE;
\r
1823 appData.testLegality = TRUE;
\r
1824 appData.premove = TRUE;
\r
1825 appData.premoveWhite = FALSE;
\r
1826 appData.premoveWhiteText = "";
\r
1827 appData.premoveBlack = FALSE;
\r
1828 appData.premoveBlackText = "";
\r
1829 appData.icsAlarm = TRUE;
\r
1830 appData.icsAlarmTime = 5000;
\r
1831 appData.autoRaiseBoard = TRUE;
\r
1832 appData.localLineEditing = TRUE;
\r
1833 appData.colorize = TRUE;
\r
1834 appData.reuseFirst = TRUE;
\r
1835 appData.reuseSecond = TRUE;
\r
1836 appData.blindfold = FALSE;
\r
1837 appData.icsEngineAnalyze = FALSE;
\r
1838 dcb.DCBlength = sizeof(DCB);
\r
1839 dcb.BaudRate = 9600;
\r
1840 dcb.fBinary = TRUE;
\r
1841 dcb.fParity = FALSE;
\r
1842 dcb.fOutxCtsFlow = FALSE;
\r
1843 dcb.fOutxDsrFlow = FALSE;
\r
1844 dcb.fDtrControl = DTR_CONTROL_ENABLE;
\r
1845 dcb.fDsrSensitivity = FALSE;
\r
1846 dcb.fTXContinueOnXoff = TRUE;
\r
1847 dcb.fOutX = FALSE;
\r
1849 dcb.fNull = FALSE;
\r
1850 dcb.fRtsControl = RTS_CONTROL_ENABLE;
\r
1851 dcb.fAbortOnError = FALSE;
\r
1852 /* Microsoft SDK >= Feb. 2003 (MS VS >= 2002) */
\r
1853 #if (defined(_MSC_VER) && _MSC_VER <= 1200)
\r
1854 //dcb.wReserved = 0;
\r
1856 dcb.wReserved = 0;
\r
1859 dcb.Parity = SPACEPARITY;
\r
1860 dcb.StopBits = ONESTOPBIT;
\r
1861 settingsFileName = SETTINGS_FILE;
\r
1862 saveSettingsOnExit = TRUE;
\r
1863 boardX = CW_USEDEFAULT;
\r
1864 boardY = CW_USEDEFAULT;
\r
1865 consoleX = CW_USEDEFAULT;
\r
1866 consoleY = CW_USEDEFAULT;
\r
1867 consoleW = CW_USEDEFAULT;
\r
1868 consoleH = CW_USEDEFAULT;
\r
1869 analysisX = CW_USEDEFAULT;
\r
1870 analysisY = CW_USEDEFAULT;
\r
1871 analysisW = CW_USEDEFAULT;
\r
1872 analysisH = CW_USEDEFAULT;
\r
1873 commentX = CW_USEDEFAULT;
\r
1874 commentY = CW_USEDEFAULT;
\r
1875 commentW = CW_USEDEFAULT;
\r
1876 commentH = CW_USEDEFAULT;
\r
1877 editTagsX = CW_USEDEFAULT;
\r
1878 editTagsY = CW_USEDEFAULT;
\r
1879 editTagsW = CW_USEDEFAULT;
\r
1880 editTagsH = CW_USEDEFAULT;
\r
1881 gameListX = CW_USEDEFAULT;
\r
1882 gameListY = CW_USEDEFAULT;
\r
1883 gameListW = CW_USEDEFAULT;
\r
1884 gameListH = CW_USEDEFAULT;
\r
1885 icsTextMenuString = ICS_TEXT_MENU_DEFAULT;
\r
1886 icsNames = ICS_NAMES;
\r
1887 firstChessProgramNames = FCP_NAMES;
\r
1888 secondChessProgramNames = SCP_NAMES;
\r
1889 appData.initialMode = "";
\r
1890 appData.variant = "normal";
\r
1891 appData.firstProtocolVersion = PROTOVER;
\r
1892 appData.secondProtocolVersion = PROTOVER;
\r
1893 appData.showButtonBar = TRUE;
\r
1895 /* [AS] New properties (see comments in header file) */
\r
1896 appData.firstScoreIsAbsolute = FALSE;
\r
1897 appData.secondScoreIsAbsolute = FALSE;
\r
1898 appData.saveExtendedInfoInPGN = FALSE;
\r
1899 appData.hideThinkingFromHuman = FALSE;
\r
1900 appData.liteBackTextureFile = "";
\r
1901 appData.liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
1902 appData.darkBackTextureFile = "";
\r
1903 appData.darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
1904 appData.renderPiecesWithFont = "";
\r
1905 appData.fontToPieceTable = "";
\r
1906 appData.fontBackColorWhite = 0;
\r
1907 appData.fontForeColorWhite = 0;
\r
1908 appData.fontBackColorBlack = 0;
\r
1909 appData.fontForeColorBlack = 0;
\r
1910 appData.fontPieceSize = 80;
\r
1911 appData.overrideLineGap = 1;
\r
1912 appData.adjudicateLossThreshold = 0;
\r
1913 appData.delayBeforeQuit = 0;
\r
1914 appData.delayAfterQuit = 0;
\r
1915 appData.nameOfDebugFile = "winboard.debug";
\r
1916 appData.pgnEventHeader = "Computer Chess Game";
\r
1917 appData.defaultFrcPosition = -1;
\r
1918 appData.gameListTags = GLT_DEFAULT_TAGS;
\r
1919 appData.saveOutOfBookInfo = TRUE;
\r
1920 appData.showEvalInMoveHistory = TRUE;
\r
1921 appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );
\r
1922 appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );
\r
1923 appData.highlightMoveWithArrow = FALSE;
\r
1924 appData.highlightArrowColor = ParseColorName( "#FFFF80" );
\r
1925 appData.useStickyWindows = TRUE;
\r
1926 appData.adjudicateDrawMoves = 0;
\r
1927 appData.autoDisplayComment = TRUE;
\r
1928 appData.autoDisplayTags = TRUE;
\r
1929 appData.firstIsUCI = FALSE;
\r
1930 appData.secondIsUCI = FALSE;
\r
1931 appData.firstHasOwnBookUCI = TRUE;
\r
1932 appData.secondHasOwnBookUCI = TRUE;
\r
1933 appData.polyglotDir = "";
\r
1934 appData.usePolyglotBook = FALSE;
\r
1935 appData.polyglotBook = "";
\r
1936 appData.defaultHashSize = 64;
\r
1937 appData.defaultCacheSizeEGTB = 4;
\r
1938 appData.defaultPathEGTB = "c:\\egtb";
\r
1940 InitWindowPlacement( &wpMoveHistory );
\r
1941 InitWindowPlacement( &wpEvalGraph );
\r
1942 InitWindowPlacement( &wpEngineOutput );
\r
1944 /* [HGM] User-selectable board size, adjudication control, miscellaneous */
\r
1945 appData.NrFiles = -1;
\r
1946 appData.NrRanks = -1;
\r
1947 appData.holdingsSize = -1;
\r
1948 appData.testClaims = FALSE;
\r
1949 appData.checkMates = FALSE;
\r
1950 appData.materialDraws= FALSE;
\r
1951 appData.trivialDraws = FALSE;
\r
1952 appData.ruleMoves = 51;
\r
1953 appData.drawRepeats = 6;
\r
1954 appData.matchPause = 10000;
\r
1955 appData.alphaRank = FALSE;
\r
1956 appData.allWhite = FALSE;
\r
1957 appData.upsideDown = FALSE;
\r
1958 appData.serverPause = 15;
\r
1959 appData.serverMovesName = NULL;
\r
1960 appData.suppressLoadMoves = FALSE;
\r
1961 appData.firstTimeOdds = 1;
\r
1962 appData.secondTimeOdds = 1;
\r
1963 appData.firstAccumulateTC = 1; // combine previous and current sessions
\r
1964 appData.secondAccumulateTC = 1;
\r
1965 appData.firstNPS = -1; // [HGM] nps: use wall-clock time
\r
1966 appData.secondNPS = -1;
\r
1967 appData.engineComments = 1;
\r
1968 appData.smpCores = 1; // [HGM] SMP: max nr of cores
\r
1969 appData.egtFormats = "";
\r
1972 appData.zippyTalk = ZIPPY_TALK;
\r
1973 appData.zippyPlay = ZIPPY_PLAY;
\r
1974 appData.zippyLines = ZIPPY_LINES;
\r
1975 appData.zippyPinhead = ZIPPY_PINHEAD;
\r
1976 appData.zippyPassword = ZIPPY_PASSWORD;
\r
1977 appData.zippyPassword2 = ZIPPY_PASSWORD2;
\r
1978 appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;
\r
1979 appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;
\r
1980 appData.zippyUseI = ZIPPY_USE_I;
\r
1981 appData.zippyBughouse = ZIPPY_BUGHOUSE;
\r
1982 appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;
\r
1983 appData.zippyGameEnd = ZIPPY_GAME_END;
\r
1984 appData.zippyGameStart = ZIPPY_GAME_START;
\r
1985 appData.zippyAdjourn = ZIPPY_ADJOURN;
\r
1986 appData.zippyAbort = ZIPPY_ABORT;
\r
1987 appData.zippyVariants = ZIPPY_VARIANTS;
\r
1988 appData.zippyMaxGames = ZIPPY_MAX_GAMES;
\r
1989 appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;
\r
1992 /* Point font array elements to structures and
\r
1993 parse default font names */
\r
1994 for (i=0; i<NUM_FONTS; i++) {
\r
1995 for (j=0; j<NUM_SIZES; j++) {
\r
1996 font[j][i] = &fontRec[j][i];
\r
1997 ParseFontName(font[j][i]->def, &font[j][i]->mfp);
\r
2001 /* Parse default settings file if any */
\r
2002 if (ParseSettingsFile(settingsFileName, buf)) {
\r
2003 settingsFileName = strdup(buf);
\r
2006 /* Parse command line */
\r
2007 ParseArgs(StringGet, &lpCmdLine);
\r
2009 /* [HGM] make sure board size is acceptable */
\r
2010 if(appData.NrFiles > BOARD_SIZE ||
\r
2011 appData.NrRanks > BOARD_SIZE )
\r
2012 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
2014 /* [HGM] After parsing the options from the .ini file, and overruling them
\r
2015 * with options from the command line, we now make an even higher priority
\r
2016 * overrule by WB options attached to the engine command line. This so that
\r
2017 * tournament managers can use WB options (such as /timeOdds) that follow
\r
2020 if(appData.firstChessProgram != NULL) {
\r
2021 char *p = StrStr(appData.firstChessProgram, "WBopt");
\r
2022 static char *f = "first";
\r
2023 char buf[MSG_SIZ], *q = buf;
\r
2024 if(p != NULL) { // engine command line contains WinBoard options
\r
2025 sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"
\r
2026 ParseArgs(StringGet, &q);
\r
2027 p[-1] = 0; // cut them offengine command line
\r
2030 // now do same for second chess program
\r
2031 if(appData.secondChessProgram != NULL) {
\r
2032 char *p = StrStr(appData.secondChessProgram, "WBopt");
\r
2033 static char *s = "second";
\r
2034 char buf[MSG_SIZ], *q = buf;
\r
2035 if(p != NULL) { // engine command line contains WinBoard options
\r
2036 sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"
\r
2037 ParseArgs(StringGet, &q);
\r
2038 p[-1] = 0; // cut them offengine command line
\r
2043 /* Propagate options that affect others */
\r
2044 if (appData.matchMode || appData.matchGames) chessProgram = TRUE;
\r
2045 if (appData.icsActive || appData.noChessProgram) {
\r
2046 chessProgram = FALSE; /* not local chess program mode */
\r
2049 /* Open startup dialog if needed */
\r
2050 if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||
\r
2051 (appData.icsActive && *appData.icsHost == NULLCHAR) ||
\r
2052 (chessProgram && (*appData.firstChessProgram == NULLCHAR ||
\r
2053 *appData.secondChessProgram == NULLCHAR))) {
\r
2056 lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);
\r
2057 DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);
\r
2058 FreeProcInstance(lpProc);
\r
2061 /* Make sure save files land in the right (?) directory */
\r
2062 if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {
\r
2063 appData.saveGameFile = strdup(buf);
\r
2065 if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {
\r
2066 appData.savePositionFile = strdup(buf);
\r
2069 /* Finish initialization for fonts and sounds */
\r
2070 for (i=0; i<NUM_FONTS; i++) {
\r
2071 for (j=0; j<NUM_SIZES; j++) {
\r
2072 CreateFontInMF(font[j][i]);
\r
2075 /* xboard, and older WinBoards, controlled the move sound with the
\r
2076 appData.ringBellAfterMoves option. In the current WinBoard, we
\r
2077 always turn the option on (so that the backend will call us),
\r
2078 then let the user turn the sound off by setting it to silence if
\r
2079 desired. To accommodate old winboard.ini files saved by old
\r
2080 versions of WinBoard, we also turn off the sound if the option
\r
2081 was initially set to false. */
\r
2082 if (!appData.ringBellAfterMoves) {
\r
2083 sounds[(int)SoundMove].name = strdup("");
\r
2084 appData.ringBellAfterMoves = TRUE;
\r
2086 GetCurrentDirectory(MSG_SIZ, currDir);
\r
2087 SetCurrentDirectory(installDir);
\r
2089 SetCurrentDirectory(currDir);
\r
2091 p = icsTextMenuString;
\r
2092 if (p[0] == '@') {
\r
2093 FILE* f = fopen(p + 1, "r");
\r
2095 DisplayFatalError(p + 1, errno, 2);
\r
2098 i = fread(buf, 1, sizeof(buf)-1, f);
\r
2100 buf[i] = NULLCHAR;
\r
2103 ParseIcsTextMenu(strdup(p));
\r
2110 HMENU hmenu = GetMenu(hwndMain);
\r
2112 (void) EnableMenuItem(hmenu, IDM_CommPort,
\r
2113 MF_BYCOMMAND|((appData.icsActive &&
\r
2114 *appData.icsCommPort != NULLCHAR) ?
\r
2115 MF_ENABLED : MF_GRAYED));
\r
2116 (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,
\r
2117 MF_BYCOMMAND|(saveSettingsOnExit ?
\r
2118 MF_CHECKED : MF_UNCHECKED));
\r
2123 SaveSettings(char* name)
\r
2126 ArgDescriptor *ad;
\r
2127 WINDOWPLACEMENT wp;
\r
2128 char dir[MSG_SIZ];
\r
2130 if (!hwndMain) return;
\r
2132 GetCurrentDirectory(MSG_SIZ, dir);
\r
2133 SetCurrentDirectory(installDir);
\r
2134 f = fopen(name, "w");
\r
2135 SetCurrentDirectory(dir);
\r
2137 DisplayError(name, errno);
\r
2140 fprintf(f, ";\n");
\r
2141 fprintf(f, "; %s %s.%s Save Settings file\n", PRODUCT, VERSION, PATCHLEVEL);
\r
2142 fprintf(f, ";\n");
\r
2143 fprintf(f, "; You can edit the values of options that are already set in this file,\n");
\r
2144 fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");
\r
2145 fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");
\r
2146 fprintf(f, ";\n");
\r
2148 wp.length = sizeof(WINDOWPLACEMENT);
\r
2149 GetWindowPlacement(hwndMain, &wp);
\r
2150 boardX = wp.rcNormalPosition.left;
\r
2151 boardY = wp.rcNormalPosition.top;
\r
2153 if (hwndConsole) {
\r
2154 GetWindowPlacement(hwndConsole, &wp);
\r
2155 consoleX = wp.rcNormalPosition.left;
\r
2156 consoleY = wp.rcNormalPosition.top;
\r
2157 consoleW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2158 consoleH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2161 if (analysisDialog) {
\r
2162 GetWindowPlacement(analysisDialog, &wp);
\r
2163 analysisX = wp.rcNormalPosition.left;
\r
2164 analysisY = wp.rcNormalPosition.top;
\r
2165 analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2166 analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2169 if (commentDialog) {
\r
2170 GetWindowPlacement(commentDialog, &wp);
\r
2171 commentX = wp.rcNormalPosition.left;
\r
2172 commentY = wp.rcNormalPosition.top;
\r
2173 commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2174 commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2177 if (editTagsDialog) {
\r
2178 GetWindowPlacement(editTagsDialog, &wp);
\r
2179 editTagsX = wp.rcNormalPosition.left;
\r
2180 editTagsY = wp.rcNormalPosition.top;
\r
2181 editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2182 editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2185 if (gameListDialog) {
\r
2186 GetWindowPlacement(gameListDialog, &wp);
\r
2187 gameListX = wp.rcNormalPosition.left;
\r
2188 gameListY = wp.rcNormalPosition.top;
\r
2189 gameListW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2190 gameListH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2193 /* [AS] Move history */
\r
2194 wpMoveHistory.visible = MoveHistoryIsUp();
\r
2196 if( moveHistoryDialog ) {
\r
2197 GetWindowPlacement(moveHistoryDialog, &wp);
\r
2198 wpMoveHistory.x = wp.rcNormalPosition.left;
\r
2199 wpMoveHistory.y = wp.rcNormalPosition.top;
\r
2200 wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2201 wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2204 /* [AS] Eval graph */
\r
2205 wpEvalGraph.visible = EvalGraphIsUp();
\r
2207 if( evalGraphDialog ) {
\r
2208 GetWindowPlacement(evalGraphDialog, &wp);
\r
2209 wpEvalGraph.x = wp.rcNormalPosition.left;
\r
2210 wpEvalGraph.y = wp.rcNormalPosition.top;
\r
2211 wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2212 wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2215 /* [AS] Engine output */
\r
2216 wpEngineOutput.visible = EngineOutputIsUp();
\r
2218 if( engineOutputDialog ) {
\r
2219 GetWindowPlacement(engineOutputDialog, &wp);
\r
2220 wpEngineOutput.x = wp.rcNormalPosition.left;
\r
2221 wpEngineOutput.y = wp.rcNormalPosition.top;
\r
2222 wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2223 wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2226 for (ad = argDescriptors; ad->argName != NULL; ad++) {
\r
2227 if (!ad->save) continue;
\r
2228 switch (ad->argType) {
\r
2231 char *p = *(char **)ad->argLoc;
\r
2232 if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {
\r
2233 /* Quote multiline values or \-containing values
\r
2234 with { } if possible */
\r
2235 fprintf(f, "/%s={%s}\n", ad->argName, p);
\r
2237 /* Else quote with " " */
\r
2238 fprintf(f, "/%s=\"", ad->argName);
\r
2240 if (*p == '\n') fprintf(f, "\n");
\r
2241 else if (*p == '\r') fprintf(f, "\\r");
\r
2242 else if (*p == '\t') fprintf(f, "\\t");
\r
2243 else if (*p == '\b') fprintf(f, "\\b");
\r
2244 else if (*p == '\f') fprintf(f, "\\f");
\r
2245 else if (*p < ' ') fprintf(f, "\\%03o", *p);
\r
2246 else if (*p == '\"') fprintf(f, "\\\"");
\r
2247 else if (*p == '\\') fprintf(f, "\\\\");
\r
2251 fprintf(f, "\"\n");
\r
2256 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);
\r
2259 fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);
\r
2262 fprintf(f, "/%s=%s\n", ad->argName,
\r
2263 (*(Boolean *)ad->argLoc) ? "true" : "false");
\r
2266 if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2269 if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2273 COLORREF color = *(COLORREF *)ad->argLoc;
\r
2274 fprintf(f, "/%s=#%02x%02x%02x\n", ad->argName,
\r
2275 color&0xff, (color>>8)&0xff, (color>>16)&0xff);
\r
2280 MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];
\r
2281 fprintf(f, "/%s=\"%s%s%s%s%s#%02x%02x%02x\"\n", ad->argName,
\r
2282 (ta->effects & CFE_BOLD) ? "b" : "",
\r
2283 (ta->effects & CFE_ITALIC) ? "i" : "",
\r
2284 (ta->effects & CFE_UNDERLINE) ? "u" : "",
\r
2285 (ta->effects & CFE_STRIKEOUT) ? "s" : "",
\r
2286 (ta->effects) ? " " : "",
\r
2287 ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);
\r
2291 if (strchr(*(char **)ad->argLoc, '\"')) {
\r
2292 fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);
\r
2294 fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);
\r
2297 case ArgBoardSize:
\r
2298 fprintf(f, "/%s=%s\n", ad->argName,
\r
2299 sizeInfo[*(BoardSize *)ad->argLoc].name);
\r
2304 for (bs=0; bs<NUM_SIZES; bs++) {
\r
2305 MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;
\r
2306 fprintf(f, "/size=%s ", sizeInfo[bs].name);
\r
2307 fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n",
\r
2308 ad->argName, mfp->faceName, mfp->pointSize,
\r
2309 mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",
\r
2310 mfp->bold ? "b" : "",
\r
2311 mfp->italic ? "i" : "",
\r
2312 mfp->underline ? "u" : "",
\r
2313 mfp->strikeout ? "s" : "");
\r
2317 case ArgCommSettings:
\r
2318 PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);
\r
2326 /*---------------------------------------------------------------------------*\
\r
2328 * GDI board drawing routines
\r
2330 \*---------------------------------------------------------------------------*/
\r
2332 /* [AS] Draw square using background texture */
\r
2333 static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )
\r
2338 return; /* Should never happen! */
\r
2341 SetGraphicsMode( dst, GM_ADVANCED );
\r
2348 /* X reflection */
\r
2353 x.eDx = (FLOAT) dw + dx - 1;
\r
2356 SetWorldTransform( dst, &x );
\r
2359 /* Y reflection */
\r
2365 x.eDy = (FLOAT) dh + dy - 1;
\r
2367 SetWorldTransform( dst, &x );
\r
2375 x.eDx = (FLOAT) dx;
\r
2376 x.eDy = (FLOAT) dy;
\r
2379 SetWorldTransform( dst, &x );
\r
2383 BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );
\r
2391 SetWorldTransform( dst, &x );
\r
2393 ModifyWorldTransform( dst, 0, MWT_IDENTITY );
\r
2396 /* [AS] [HGM] Make room for more piece types, so all pieces can be different */
\r
2398 PM_WP = (int) WhitePawn,
\r
2399 PM_WN = (int) WhiteKnight,
\r
2400 PM_WB = (int) WhiteBishop,
\r
2401 PM_WR = (int) WhiteRook,
\r
2402 PM_WQ = (int) WhiteQueen,
\r
2403 PM_WF = (int) WhiteFerz,
\r
2404 PM_WW = (int) WhiteWazir,
\r
2405 PM_WE = (int) WhiteAlfil,
\r
2406 PM_WM = (int) WhiteMan,
\r
2407 PM_WO = (int) WhiteCannon,
\r
2408 PM_WU = (int) WhiteUnicorn,
\r
2409 PM_WH = (int) WhiteNightrider,
\r
2410 PM_WA = (int) WhiteAngel,
\r
2411 PM_WC = (int) WhiteMarshall,
\r
2412 PM_WAB = (int) WhiteCardinal,
\r
2413 PM_WD = (int) WhiteDragon,
\r
2414 PM_WL = (int) WhiteLance,
\r
2415 PM_WS = (int) WhiteCobra,
\r
2416 PM_WV = (int) WhiteFalcon,
\r
2417 PM_WSG = (int) WhiteSilver,
\r
2418 PM_WG = (int) WhiteGrasshopper,
\r
2419 PM_WK = (int) WhiteKing,
\r
2420 PM_BP = (int) BlackPawn,
\r
2421 PM_BN = (int) BlackKnight,
\r
2422 PM_BB = (int) BlackBishop,
\r
2423 PM_BR = (int) BlackRook,
\r
2424 PM_BQ = (int) BlackQueen,
\r
2425 PM_BF = (int) BlackFerz,
\r
2426 PM_BW = (int) BlackWazir,
\r
2427 PM_BE = (int) BlackAlfil,
\r
2428 PM_BM = (int) BlackMan,
\r
2429 PM_BO = (int) BlackCannon,
\r
2430 PM_BU = (int) BlackUnicorn,
\r
2431 PM_BH = (int) BlackNightrider,
\r
2432 PM_BA = (int) BlackAngel,
\r
2433 PM_BC = (int) BlackMarshall,
\r
2434 PM_BG = (int) BlackGrasshopper,
\r
2435 PM_BAB = (int) BlackCardinal,
\r
2436 PM_BD = (int) BlackDragon,
\r
2437 PM_BL = (int) BlackLance,
\r
2438 PM_BS = (int) BlackCobra,
\r
2439 PM_BV = (int) BlackFalcon,
\r
2440 PM_BSG = (int) BlackSilver,
\r
2441 PM_BK = (int) BlackKing
\r
2444 static HFONT hPieceFont = NULL;
\r
2445 static HBITMAP hPieceMask[(int) EmptySquare];
\r
2446 static HBITMAP hPieceFace[(int) EmptySquare];
\r
2447 static int fontBitmapSquareSize = 0;
\r
2448 static char pieceToFontChar[(int) EmptySquare] =
\r
2449 { 'p', 'n', 'b', 'r', 'q',
\r
2450 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',
\r
2451 'k', 'o', 'm', 'v', 't', 'w',
\r
2452 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',
\r
2455 extern BOOL SetCharTable( char *table, const char * map );
\r
2456 /* [HGM] moved to backend.c */
\r
2458 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )
\r
2461 BYTE r1 = GetRValue( color );
\r
2462 BYTE g1 = GetGValue( color );
\r
2463 BYTE b1 = GetBValue( color );
\r
2469 /* Create a uniform background first */
\r
2470 hbrush = CreateSolidBrush( color );
\r
2471 SetRect( &rc, 0, 0, squareSize, squareSize );
\r
2472 FillRect( hdc, &rc, hbrush );
\r
2473 DeleteObject( hbrush );
\r
2476 /* Vertical gradient, good for pawn, knight and rook, less for queen and king */
\r
2477 int steps = squareSize / 2;
\r
2480 for( i=0; i<steps; i++ ) {
\r
2481 BYTE r = r1 - (r1-r2) * i / steps;
\r
2482 BYTE g = g1 - (g1-g2) * i / steps;
\r
2483 BYTE b = b1 - (b1-b2) * i / steps;
\r
2485 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2486 SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );
\r
2487 FillRect( hdc, &rc, hbrush );
\r
2488 DeleteObject(hbrush);
\r
2491 else if( mode == 2 ) {
\r
2492 /* Diagonal gradient, good more or less for every piece */
\r
2493 POINT triangle[3];
\r
2494 HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );
\r
2495 HBRUSH hbrush_old;
\r
2496 int steps = squareSize;
\r
2499 triangle[0].x = squareSize - steps;
\r
2500 triangle[0].y = squareSize;
\r
2501 triangle[1].x = squareSize;
\r
2502 triangle[1].y = squareSize;
\r
2503 triangle[2].x = squareSize;
\r
2504 triangle[2].y = squareSize - steps;
\r
2506 for( i=0; i<steps; i++ ) {
\r
2507 BYTE r = r1 - (r1-r2) * i / steps;
\r
2508 BYTE g = g1 - (g1-g2) * i / steps;
\r
2509 BYTE b = b1 - (b1-b2) * i / steps;
\r
2511 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2512 hbrush_old = SelectObject( hdc, hbrush );
\r
2513 Polygon( hdc, triangle, 3 );
\r
2514 SelectObject( hdc, hbrush_old );
\r
2515 DeleteObject(hbrush);
\r
2520 SelectObject( hdc, hpen );
\r
2525 [AS] The method I use to create the bitmaps it a bit tricky, but it
\r
2526 seems to work ok. The main problem here is to find the "inside" of a chess
\r
2527 piece: follow the steps as explained below.
\r
2529 static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
\r
2533 COLORREF chroma = RGB(0xFF,0x00,0xFF);
\r
2537 int backColor = whitePieceColor;
\r
2538 int foreColor = blackPieceColor;
\r
2540 if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {
\r
2541 backColor = appData.fontBackColorWhite;
\r
2542 foreColor = appData.fontForeColorWhite;
\r
2544 else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {
\r
2545 backColor = appData.fontBackColorBlack;
\r
2546 foreColor = appData.fontForeColorBlack;
\r
2550 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2552 hbm_old = SelectObject( hdc, hbm );
\r
2556 rc.right = squareSize;
\r
2557 rc.bottom = squareSize;
\r
2559 /* Step 1: background is now black */
\r
2560 FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );
\r
2562 GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );
\r
2564 pt.x = (squareSize - sz.cx) / 2;
\r
2565 pt.y = (squareSize - sz.cy) / 2;
\r
2567 SetBkMode( hdc, TRANSPARENT );
\r
2568 SetTextColor( hdc, chroma );
\r
2569 /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */
\r
2570 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2572 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
\r
2573 /* Step 3: the area outside the piece is filled with white */
\r
2574 // FloodFill( hdc, 0, 0, chroma );
\r
2575 ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );
\r
2576 ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big
\r
2577 ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );
\r
2578 ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );
\r
2579 SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
\r
2581 Step 4: this is the tricky part, the area inside the piece is filled with black,
\r
2582 but if the start point is not inside the piece we're lost!
\r
2583 There should be a better way to do this... if we could create a region or path
\r
2584 from the fill operation we would be fine for example.
\r
2586 // FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );
\r
2587 ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );
\r
2589 { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */
\r
2590 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2591 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2593 SelectObject( dc2, bm2 );
\r
2594 BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy
\r
2595 BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2596 BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2597 BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2598 BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2601 DeleteObject( bm2 );
\r
2604 SetTextColor( hdc, 0 );
\r
2606 Step 5: some fonts have "disconnected" areas that are skipped by the fill:
\r
2607 draw the piece again in black for safety.
\r
2609 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2611 SelectObject( hdc, hbm_old );
\r
2613 if( hPieceMask[index] != NULL ) {
\r
2614 DeleteObject( hPieceMask[index] );
\r
2617 hPieceMask[index] = hbm;
\r
2620 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2622 SelectObject( hdc, hbm );
\r
2625 HDC dc1 = CreateCompatibleDC( hdc_window );
\r
2626 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2627 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2629 SelectObject( dc1, hPieceMask[index] );
\r
2630 SelectObject( dc2, bm2 );
\r
2631 FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );
\r
2632 BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );
\r
2635 Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves
\r
2636 the piece background and deletes (makes transparent) the rest.
\r
2637 Thanks to that mask, we are free to paint the background with the greates
\r
2638 freedom, as we'll be able to mask off the unwanted parts when finished.
\r
2639 We use this, to make gradients and give the pieces a "roundish" look.
\r
2641 SetPieceBackground( hdc, backColor, 2 );
\r
2642 BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );
\r
2646 DeleteObject( bm2 );
\r
2649 SetTextColor( hdc, foreColor );
\r
2650 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2652 SelectObject( hdc, hbm_old );
\r
2654 if( hPieceFace[index] != NULL ) {
\r
2655 DeleteObject( hPieceFace[index] );
\r
2658 hPieceFace[index] = hbm;
\r
2661 static int TranslatePieceToFontPiece( int piece )
\r
2691 case BlackMarshall:
\r
2695 case BlackNightrider:
\r
2701 case BlackUnicorn:
\r
2705 case BlackGrasshopper:
\r
2717 case BlackCardinal:
\r
2724 case WhiteMarshall:
\r
2728 case WhiteNightrider:
\r
2734 case WhiteUnicorn:
\r
2738 case WhiteGrasshopper:
\r
2750 case WhiteCardinal:
\r
2759 void CreatePiecesFromFont()
\r
2762 HDC hdc_window = NULL;
\r
2768 if( fontBitmapSquareSize < 0 ) {
\r
2769 /* Something went seriously wrong in the past: do not try to recreate fonts! */
\r
2773 if( appData.renderPiecesWithFont == NULL || appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {
\r
2774 fontBitmapSquareSize = -1;
\r
2778 if( fontBitmapSquareSize != squareSize ) {
\r
2779 hdc_window = GetDC( hwndMain );
\r
2780 hdc = CreateCompatibleDC( hdc_window );
\r
2782 if( hPieceFont != NULL ) {
\r
2783 DeleteObject( hPieceFont );
\r
2786 for( i=0; i<=(int)BlackKing; i++ ) {
\r
2787 hPieceMask[i] = NULL;
\r
2788 hPieceFace[i] = NULL;
\r
2794 if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {
\r
2795 fontHeight = appData.fontPieceSize;
\r
2798 fontHeight = (fontHeight * squareSize) / 100;
\r
2800 lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
\r
2802 lf.lfEscapement = 0;
\r
2803 lf.lfOrientation = 0;
\r
2804 lf.lfWeight = FW_NORMAL;
\r
2806 lf.lfUnderline = 0;
\r
2807 lf.lfStrikeOut = 0;
\r
2808 lf.lfCharSet = DEFAULT_CHARSET;
\r
2809 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
2810 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
2811 lf.lfQuality = PROOF_QUALITY;
\r
2812 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
\r
2813 strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );
\r
2814 lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';
\r
2816 hPieceFont = CreateFontIndirect( &lf );
\r
2818 if( hPieceFont == NULL ) {
\r
2819 fontBitmapSquareSize = -2;
\r
2822 /* Setup font-to-piece character table */
\r
2823 if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {
\r
2824 /* No (or wrong) global settings, try to detect the font */
\r
2825 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {
\r
2827 SetCharTable(pieceToFontChar, "phbrqkojntwl");
\r
2829 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {
\r
2830 /* DiagramTT* family */
\r
2831 SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");
\r
2833 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {
\r
2834 /* Fairy symbols */
\r
2835 SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
\r
2837 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {
\r
2838 /* Good Companion (Some characters get warped as literal :-( */
\r
2839 char s[] = "1cmWG0ñueOS¯®oYI23wgQU";
\r
2840 s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;
\r
2841 SetCharTable(pieceToFontChar, s);
\r
2844 /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */
\r
2845 SetCharTable(pieceToFontChar, "pnbrqkomvtwl");
\r
2849 /* Create bitmaps */
\r
2850 hfont_old = SelectObject( hdc, hPieceFont );
\r
2852 CreatePieceMaskFromFont( hdc_window, hdc, PM_WP );
\r
2853 CreatePieceMaskFromFont( hdc_window, hdc, PM_WN );
\r
2854 CreatePieceMaskFromFont( hdc_window, hdc, PM_WB );
\r
2855 CreatePieceMaskFromFont( hdc_window, hdc, PM_WR );
\r
2856 CreatePieceMaskFromFont( hdc_window, hdc, PM_WQ );
\r
2857 CreatePieceMaskFromFont( hdc_window, hdc, PM_WK );
\r
2858 CreatePieceMaskFromFont( hdc_window, hdc, PM_BP );
\r
2859 CreatePieceMaskFromFont( hdc_window, hdc, PM_BN );
\r
2860 CreatePieceMaskFromFont( hdc_window, hdc, PM_BB );
\r
2861 CreatePieceMaskFromFont( hdc_window, hdc, PM_BR );
\r
2862 CreatePieceMaskFromFont( hdc_window, hdc, PM_BQ );
\r
2863 CreatePieceMaskFromFont( hdc_window, hdc, PM_BK );
\r
2865 CreatePieceMaskFromFont( hdc_window, hdc, PM_WA );
\r
2866 CreatePieceMaskFromFont( hdc_window, hdc, PM_WC );
\r
2867 CreatePieceMaskFromFont( hdc_window, hdc, PM_WF );
\r
2868 CreatePieceMaskFromFont( hdc_window, hdc, PM_WH );
\r
2869 CreatePieceMaskFromFont( hdc_window, hdc, PM_WE );
\r
2870 CreatePieceMaskFromFont( hdc_window, hdc, PM_WW );
\r
2871 CreatePieceMaskFromFont( hdc_window, hdc, PM_WU );
\r
2872 CreatePieceMaskFromFont( hdc_window, hdc, PM_WO );
\r
2873 CreatePieceMaskFromFont( hdc_window, hdc, PM_WG );
\r
2874 CreatePieceMaskFromFont( hdc_window, hdc, PM_WM );
\r
2875 CreatePieceMaskFromFont( hdc_window, hdc, PM_WSG );
\r
2876 CreatePieceMaskFromFont( hdc_window, hdc, PM_WV );
\r
2877 CreatePieceMaskFromFont( hdc_window, hdc, PM_WAB );
\r
2878 CreatePieceMaskFromFont( hdc_window, hdc, PM_WD );
\r
2879 CreatePieceMaskFromFont( hdc_window, hdc, PM_WL );
\r
2880 CreatePieceMaskFromFont( hdc_window, hdc, PM_WS );
\r
2881 CreatePieceMaskFromFont( hdc_window, hdc, PM_BA );
\r
2882 CreatePieceMaskFromFont( hdc_window, hdc, PM_BC );
\r
2883 CreatePieceMaskFromFont( hdc_window, hdc, PM_BF );
\r
2884 CreatePieceMaskFromFont( hdc_window, hdc, PM_BH );
\r
2885 CreatePieceMaskFromFont( hdc_window, hdc, PM_BE );
\r
2886 CreatePieceMaskFromFont( hdc_window, hdc, PM_BW );
\r
2887 CreatePieceMaskFromFont( hdc_window, hdc, PM_BU );
\r
2888 CreatePieceMaskFromFont( hdc_window, hdc, PM_BO );
\r
2889 CreatePieceMaskFromFont( hdc_window, hdc, PM_BG );
\r
2890 CreatePieceMaskFromFont( hdc_window, hdc, PM_BM );
\r
2891 CreatePieceMaskFromFont( hdc_window, hdc, PM_BSG );
\r
2892 CreatePieceMaskFromFont( hdc_window, hdc, PM_BV );
\r
2893 CreatePieceMaskFromFont( hdc_window, hdc, PM_BAB );
\r
2894 CreatePieceMaskFromFont( hdc_window, hdc, PM_BD );
\r
2895 CreatePieceMaskFromFont( hdc_window, hdc, PM_BL );
\r
2896 CreatePieceMaskFromFont( hdc_window, hdc, PM_BS );
\r
2898 for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */
\r
2899 if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */
\r
2900 CreatePieceMaskFromFont( hdc_window, hdc, i );
\r
2902 SelectObject( hdc, hfont_old );
\r
2904 fontBitmapSquareSize = squareSize;
\r
2908 if( hdc != NULL ) {
\r
2912 if( hdc_window != NULL ) {
\r
2913 ReleaseDC( hwndMain, hdc_window );
\r
2918 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)
\r
2922 sprintf(name, "%s%d%s", piece, squareSize, suffix);
\r
2923 if (gameInfo.event &&
\r
2924 strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&
\r
2925 strcmp(name, "k80s") == 0) {
\r
2926 strcpy(name, "tim");
\r
2928 return LoadBitmap(hinst, name);
\r
2932 /* Insert a color into the program's logical palette
\r
2933 structure. This code assumes the given color is
\r
2934 the result of the RGB or PALETTERGB macro, and it
\r
2935 knows how those macros work (which is documented).
\r
2938 InsertInPalette(COLORREF color)
\r
2940 LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);
\r
2942 if (pLogPal->palNumEntries++ >= PALETTESIZE) {
\r
2943 DisplayFatalError("Too many colors", 0, 1);
\r
2944 pLogPal->palNumEntries--;
\r
2948 pe->peFlags = (char) 0;
\r
2949 pe->peRed = (char) (0xFF & color);
\r
2950 pe->peGreen = (char) (0xFF & (color >> 8));
\r
2951 pe->peBlue = (char) (0xFF & (color >> 16));
\r
2957 InitDrawingColors()
\r
2959 if (pLogPal == NULL) {
\r
2960 /* Allocate enough memory for a logical palette with
\r
2961 * PALETTESIZE entries and set the size and version fields
\r
2962 * of the logical palette structure.
\r
2964 pLogPal = (NPLOGPALETTE)
\r
2965 LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +
\r
2966 (sizeof(PALETTEENTRY) * (PALETTESIZE))));
\r
2967 pLogPal->palVersion = 0x300;
\r
2969 pLogPal->palNumEntries = 0;
\r
2971 InsertInPalette(lightSquareColor);
\r
2972 InsertInPalette(darkSquareColor);
\r
2973 InsertInPalette(whitePieceColor);
\r
2974 InsertInPalette(blackPieceColor);
\r
2975 InsertInPalette(highlightSquareColor);
\r
2976 InsertInPalette(premoveHighlightColor);
\r
2978 /* create a logical color palette according the information
\r
2979 * in the LOGPALETTE structure.
\r
2981 hPal = CreatePalette((LPLOGPALETTE) pLogPal);
\r
2983 lightSquareBrush = CreateSolidBrush(lightSquareColor);
\r
2984 blackSquareBrush = CreateSolidBrush(blackPieceColor);
\r
2985 darkSquareBrush = CreateSolidBrush(darkSquareColor);
\r
2986 whitePieceBrush = CreateSolidBrush(whitePieceColor);
\r
2987 blackPieceBrush = CreateSolidBrush(blackPieceColor);
\r
2988 iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
\r
2990 /* [AS] Force rendering of the font-based pieces */
\r
2991 if( fontBitmapSquareSize > 0 ) {
\r
2992 fontBitmapSquareSize = 0;
\r
2998 BoardWidth(int boardSize, int n)
\r
2999 { /* [HGM] argument n added to allow different width and height */
\r
3000 int lineGap = sizeInfo[boardSize].lineGap;
\r
3002 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3003 lineGap = appData.overrideLineGap;
\r
3006 return (n + 1) * lineGap +
\r
3007 n * sizeInfo[boardSize].squareSize;
\r
3010 /* Respond to board resize by dragging edge */
\r
3012 ResizeBoard(int newSizeX, int newSizeY, int flags)
\r
3014 BoardSize newSize = NUM_SIZES - 1;
\r
3015 static int recurse = 0;
\r
3016 if (IsIconic(hwndMain)) return;
\r
3017 if (recurse > 0) return;
\r
3019 while (newSize > 0) {
\r
3020 InitDrawingSizes(newSize, 0);
\r
3021 if(newSizeX >= sizeInfo[newSize].cliWidth ||
\r
3022 newSizeY >= sizeInfo[newSize].cliHeight) break;
\r
3025 boardSize = newSize;
\r
3026 InitDrawingSizes(boardSize, flags);
\r
3033 InitDrawingSizes(BoardSize boardSize, int flags)
\r
3035 int i, boardWidth, boardHeight; /* [HGM] height treated separately */
\r
3036 ChessSquare piece;
\r
3037 static int oldBoardSize = -1, oldTinyLayout = 0;
\r
3039 SIZE clockSize, messageSize;
\r
3041 char buf[MSG_SIZ];
\r
3043 HMENU hmenu = GetMenu(hwndMain);
\r
3044 RECT crect, wrect;
\r
3046 LOGBRUSH logbrush;
\r
3048 /* [HGM] call with -1 uses old size (for if nr of files, ranks changes) */
\r
3049 if(boardSize == (BoardSize)(-2) ) boardSize = oldBoardSize;
\r
3051 tinyLayout = sizeInfo[boardSize].tinyLayout;
\r
3052 smallLayout = sizeInfo[boardSize].smallLayout;
\r
3053 squareSize = sizeInfo[boardSize].squareSize;
\r
3054 lineGap = sizeInfo[boardSize].lineGap;
\r
3055 minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted */
\r
3057 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3058 lineGap = appData.overrideLineGap;
\r
3061 if (tinyLayout != oldTinyLayout) {
\r
3062 long style = GetWindowLong(hwndMain, GWL_STYLE);
\r
3064 style &= ~WS_SYSMENU;
\r
3065 InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize,
\r
3066 "&Minimize\tCtrl+F4");
\r
3068 style |= WS_SYSMENU;
\r
3069 RemoveMenu(hmenu, IDM_Minimize, MF_BYCOMMAND);
\r
3071 SetWindowLong(hwndMain, GWL_STYLE, style);
\r
3073 for (i=0; menuBarText[tinyLayout][i]; i++) {
\r
3074 ModifyMenu(hmenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP,
\r
3075 (UINT)GetSubMenu(hmenu, i), menuBarText[tinyLayout][i]);
\r
3077 DrawMenuBar(hwndMain);
\r
3080 boardWidth = BoardWidth(boardSize, BOARD_WIDTH);
\r
3081 boardHeight = BoardWidth(boardSize, BOARD_HEIGHT);
\r
3083 /* Get text area sizes */
\r
3084 hdc = GetDC(hwndMain);
\r
3085 if (appData.clockMode) {
\r
3086 sprintf(buf, "White: %s", TimeString(23*60*60*1000L));
\r
3088 sprintf(buf, "White");
\r
3090 oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);
\r
3091 GetTextExtentPoint(hdc, buf, strlen(buf), &clockSize);
\r
3092 SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);
\r
3093 str = "We only care about the height here";
\r
3094 GetTextExtentPoint(hdc, str, strlen(str), &messageSize);
\r
3095 SelectObject(hdc, oldFont);
\r
3096 ReleaseDC(hwndMain, hdc);
\r
3098 /* Compute where everything goes */
\r
3099 if(first.programLogo || second.programLogo) {
\r
3100 /* [HGM] logo: if either logo is on, reserve space for it */
\r
3101 logoHeight = 2*clockSize.cy;
\r
3102 leftLogoRect.left = OUTER_MARGIN;
\r
3103 leftLogoRect.right = leftLogoRect.left + 4*clockSize.cy;
\r
3104 leftLogoRect.top = OUTER_MARGIN;
\r
3105 leftLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3107 rightLogoRect.right = OUTER_MARGIN + boardWidth;
\r
3108 rightLogoRect.left = rightLogoRect.right - 4*clockSize.cy;
\r
3109 rightLogoRect.top = OUTER_MARGIN;
\r
3110 rightLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3113 blackRect.left = leftLogoRect.right;
\r
3114 blackRect.right = rightLogoRect.left;
\r
3115 blackRect.top = OUTER_MARGIN;
\r
3116 blackRect.bottom = blackRect.top + clockSize.cy;
\r
3118 whiteRect.left = blackRect.left ;
\r
3119 whiteRect.right = blackRect.right;
\r
3120 whiteRect.top = blackRect.bottom;
\r
3121 whiteRect.bottom = leftLogoRect.bottom;
\r
3123 whiteRect.left = OUTER_MARGIN;
\r
3124 whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2;
\r
3125 whiteRect.top = OUTER_MARGIN + logoHeight;
\r
3126 whiteRect.bottom = whiteRect.top + clockSize.cy;
\r
3128 blackRect.left = whiteRect.right + INNER_MARGIN;
\r
3129 blackRect.right = blackRect.left + boardWidth/2 - 1;
\r
3130 blackRect.top = whiteRect.top;
\r
3131 blackRect.bottom = whiteRect.bottom;
\r
3134 messageRect.left = OUTER_MARGIN + MESSAGE_LINE_LEFTMARGIN;
\r
3135 if (appData.showButtonBar) {
\r
3136 messageRect.right = OUTER_MARGIN + boardWidth // [HGM] logo: expressed independent of clock placement
\r
3137 - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN;
\r
3139 messageRect.right = OUTER_MARGIN + boardWidth;
\r
3141 messageRect.top = whiteRect.bottom + INNER_MARGIN;
\r
3142 messageRect.bottom = messageRect.top + messageSize.cy;
\r
3144 boardRect.left = OUTER_MARGIN;
\r
3145 boardRect.right = boardRect.left + boardWidth;
\r
3146 boardRect.top = messageRect.bottom + INNER_MARGIN;
\r
3147 boardRect.bottom = boardRect.top + boardHeight;
\r
3149 sizeInfo[boardSize].cliWidth = boardRect.right + OUTER_MARGIN;
\r
3150 sizeInfo[boardSize].cliHeight = boardRect.bottom + OUTER_MARGIN;
\r
3151 winWidth = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN;
\r
3152 winHeight = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) +
\r
3153 GetSystemMetrics(SM_CYCAPTION) + boardRect.bottom + OUTER_MARGIN;
\r
3154 GetWindowRect(hwndMain, &wrect);
\r
3155 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3156 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3157 /* compensate if menu bar wrapped */
\r
3158 GetClientRect(hwndMain, &crect);
\r
3159 offby = boardRect.bottom + OUTER_MARGIN - crect.bottom;
\r
3160 winHeight += offby;
\r
3162 case WMSZ_TOPLEFT:
\r
3163 SetWindowPos(hwndMain, NULL,
\r
3164 wrect.right - winWidth, wrect.bottom - winHeight,
\r
3165 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3168 case WMSZ_TOPRIGHT:
\r
3170 SetWindowPos(hwndMain, NULL,
\r
3171 wrect.left, wrect.bottom - winHeight,
\r
3172 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3175 case WMSZ_BOTTOMLEFT:
\r
3177 SetWindowPos(hwndMain, NULL,
\r
3178 wrect.right - winWidth, wrect.top,
\r
3179 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3182 case WMSZ_BOTTOMRIGHT:
\r
3186 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3187 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3192 for (i = 0; i < N_BUTTONS; i++) {
\r
3193 if (buttonDesc[i].hwnd != NULL) {
\r
3194 DestroyWindow(buttonDesc[i].hwnd);
\r
3195 buttonDesc[i].hwnd = NULL;
\r
3197 if (appData.showButtonBar) {
\r
3198 buttonDesc[i].hwnd =
\r
3199 CreateWindow("BUTTON", buttonDesc[i].label,
\r
3200 WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
\r
3201 boardRect.right - BUTTON_WIDTH*(N_BUTTONS-i),
\r
3202 messageRect.top, BUTTON_WIDTH, messageSize.cy, hwndMain,
\r
3203 (HMENU) buttonDesc[i].id,
\r
3204 (HINSTANCE) GetWindowLong(hwndMain, GWL_HINSTANCE), NULL);
\r
3206 SendMessage(buttonDesc[i].hwnd, WM_SETFONT,
\r
3207 (WPARAM)font[boardSize][MESSAGE_FONT]->hf,
\r
3208 MAKELPARAM(FALSE, 0));
\r
3210 if (buttonDesc[i].id == IDM_Pause)
\r
3211 hwndPause = buttonDesc[i].hwnd;
\r
3212 buttonDesc[i].wndproc = (WNDPROC)
\r
3213 SetWindowLong(buttonDesc[i].hwnd, GWL_WNDPROC, (LONG) ButtonProc);
\r
3216 if (gridPen != NULL) DeleteObject(gridPen);
\r
3217 if (highlightPen != NULL) DeleteObject(highlightPen);
\r
3218 if (premovePen != NULL) DeleteObject(premovePen);
\r
3219 if (lineGap != 0) {
\r
3220 logbrush.lbStyle = BS_SOLID;
\r
3221 logbrush.lbColor = RGB(0, 0, 0); /* grid pen color = black */
\r
3223 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3224 lineGap, &logbrush, 0, NULL);
\r
3225 logbrush.lbColor = highlightSquareColor;
\r
3227 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3228 lineGap, &logbrush, 0, NULL);
\r
3230 logbrush.lbColor = premoveHighlightColor;
\r
3232 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3233 lineGap, &logbrush, 0, NULL);
\r
3235 /* [HGM] Loop had to be split in part for vert. and hor. lines */
\r
3236 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
\r
3237 gridEndpoints[i*2].x = boardRect.left + lineGap / 2;
\r
3238 gridEndpoints[i*2].y = gridEndpoints[i*2 + 1].y =
\r
3239 boardRect.top + lineGap / 2 + (i * (squareSize + lineGap));
\r
3240 gridEndpoints[i*2 + 1].x = boardRect.left + lineGap / 2 +
\r
3241 BOARD_WIDTH * (squareSize + lineGap);
\r
3242 lineGap / 2 + (i * (squareSize + lineGap));
\r
3243 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3245 for (i = 0; i < BOARD_WIDTH + 1; i++) {
\r
3246 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].y = boardRect.top + lineGap / 2;
\r
3247 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].x =
\r
3248 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].x = boardRect.left +
\r
3249 lineGap / 2 + (i * (squareSize + lineGap));
\r
3250 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].y =
\r
3251 boardRect.top + BOARD_HEIGHT * (squareSize + lineGap);
\r
3252 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3256 /* [HGM] Licensing requirement */
\r
3258 if(gameInfo.variant == VariantGothic) GothicPopUp( GOTHIC, VariantGothic); else
\r
3261 if(gameInfo.variant == VariantFalcon) GothicPopUp( FALCON, VariantFalcon); else
\r
3263 GothicPopUp( "", VariantNormal);
\r
3266 /* if (boardSize == oldBoardSize) return; [HGM] variant might have changed */
\r
3267 oldBoardSize = boardSize;
\r
3268 oldTinyLayout = tinyLayout;
\r
3270 /* Load piece bitmaps for this board size */
\r
3271 for (i=0; i<=2; i++) {
\r
3272 for (piece = WhitePawn;
\r
3273 (int) piece < (int) BlackPawn;
\r
3274 piece = (ChessSquare) ((int) piece + 1)) {
\r
3275 if (pieceBitmap[i][piece] != NULL)
\r
3276 DeleteObject(pieceBitmap[i][piece]);
\r
3280 fontBitmapSquareSize = 0; /* [HGM] render: make sure pieces will be recreated, as we might need others now */
\r
3281 // Orthodox Chess pieces
\r
3282 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s");
\r
3283 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s");
\r
3284 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "s");
\r
3285 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "s");
\r
3286 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "s");
\r
3287 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "o");
\r
3288 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "o");
\r
3289 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "o");
\r
3290 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "o");
\r
3291 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "o");
\r
3292 pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "w");
\r
3293 pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "w");
\r
3294 pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "w");
\r
3295 pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w");
\r
3296 pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w");
\r
3297 if( !strcmp(appData.variant, "shogi") && (squareSize==72 || squareSize==49)) {
\r
3298 // in Shogi, Hijack the unused Queen for Lance
\r
3299 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3300 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3301 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3303 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s");
\r
3304 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o");
\r
3305 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w");
\r
3308 if(squareSize <= 72 && squareSize >= 33) {
\r
3309 /* A & C are available in most sizes now */
\r
3310 if(squareSize != 49 && squareSize != 72 && squareSize != 33) { // Vortex-like
\r
3311 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3312 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3313 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3314 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3315 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3316 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3317 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3318 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3319 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3320 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3321 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3322 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3323 } else { // Smirf-like
\r
3324 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "s");
\r
3325 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "o");
\r
3326 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "w");
\r
3328 if(gameInfo.variant == VariantGothic) { // Vortex-like
\r
3329 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3330 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3331 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3332 } else { // WinBoard standard
\r
3333 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s");
\r
3334 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o");
\r
3335 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "w");
\r
3340 if(squareSize==72 || squareSize==49 || squareSize==33) { /* experiment with some home-made bitmaps */
\r
3341 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "s");
\r
3342 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "o");
\r
3343 pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "w");
\r
3344 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "s");
\r
3345 pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "o");
\r
3346 pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3347 pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "s");
\r
3348 pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "o");
\r
3349 pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "w");
\r
3350 pieceBitmap[0][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "s");
\r
3351 pieceBitmap[1][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "o");
\r
3352 pieceBitmap[2][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "w");
\r
3353 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3354 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3355 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3356 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "s");
\r
3357 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "o");
\r
3358 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "w");
\r
3359 pieceBitmap[0][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "s");
\r
3360 pieceBitmap[1][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "o");
\r
3361 pieceBitmap[2][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "w");
\r
3362 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "s");
\r
3363 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "o");
\r
3364 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "w");
\r
3365 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3366 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3367 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3368 pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s");
\r
3369 pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o");
\r
3370 pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w");
\r
3372 if(gameInfo.variant == VariantShogi) { /* promoted Gold represemtations */
\r
3373 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s");
\r
3374 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "o");
\r
3375 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3376 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "s");
\r
3377 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "o");
\r
3378 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3379 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "s");
\r
3380 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "o");
\r
3381 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3382 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "s");
\r
3383 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "o");
\r
3384 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3386 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "s");
\r
3387 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "o");
\r
3388 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "w");
\r
3389 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "s");
\r
3390 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "o");
\r
3391 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "w");
\r
3392 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3393 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3394 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3395 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "s");
\r
3396 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "o");
\r
3397 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "w");
\r
3400 } else { /* other size, no special bitmaps available. Use smaller symbols */
\r
3401 if((int)boardSize < 2) minorSize = sizeInfo[0].squareSize;
\r
3402 else minorSize = sizeInfo[(int)boardSize - 2].squareSize;
\r
3403 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "s");
\r
3404 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "o");
\r
3405 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "w");
\r
3406 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "s");
\r
3407 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "o");
\r
3408 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "w");
\r
3409 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "s");
\r
3410 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "o");
\r
3411 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "w");
\r
3412 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "s");
\r
3413 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "o");
\r
3414 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "w");
\r
3418 if(gameInfo.variant == VariantShogi && squareSize == 58)
\r
3419 /* special Shogi support in this size */
\r
3420 { for (i=0; i<=2; i++) { /* replace all bitmaps */
\r
3421 for (piece = WhitePawn;
\r
3422 (int) piece < (int) BlackPawn;
\r
3423 piece = (ChessSquare) ((int) piece + 1)) {
\r
3424 if (pieceBitmap[i][piece] != NULL)
\r
3425 DeleteObject(pieceBitmap[i][piece]);
\r
3428 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3429 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3430 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3431 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3432 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3433 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3434 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r
3435 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");
\r
3436 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");
\r
3437 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");
\r
3438 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");
\r
3439 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");
\r
3440 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");
\r
3441 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");
\r
3442 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3443 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3444 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3445 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3446 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3447 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3448 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r
3449 pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");
\r
3450 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");
\r
3451 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");
\r
3452 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");
\r
3453 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");
\r
3454 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");
\r
3455 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");
\r
3456 pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "w");
\r
3457 pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "w");
\r
3458 pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3459 pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3460 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "w");
\r
3461 pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "w");
\r
3462 pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3463 pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3464 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "sp", squareSize, "w");
\r
3465 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "sn", squareSize, "w");
\r
3466 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3467 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3468 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "sl", squareSize, "w");
\r
3469 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3475 PieceBitmap(ChessSquare p, int kind)
\r
3477 if ((int) p >= (int) BlackPawn)
\r
3478 p = (ChessSquare) ((int) p - (int) BlackPawn + (int) WhitePawn);
\r
3480 return pieceBitmap[kind][(int) p];
\r
3483 /***************************************************************/
\r
3485 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
\r
3486 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
\r
3488 #define MIN3(a,b,c) (((a) < (b) && (a) < (c)) ? (a) : (((b) < (a) && (b) < (c)) ? (b) : (c)))
\r
3489 #define MAX3(a,b,c) (((a) > (b) && (a) > (c)) ? (a) : (((b) > (a) && (b) > (c)) ? (b) : (c)))
\r
3493 SquareToPos(int row, int column, int * x, int * y)
\r
3496 *x = boardRect.left + lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
\r
3497 *y = boardRect.top + lineGap + row * (squareSize + lineGap);
\r
3499 *x = boardRect.left + lineGap + column * (squareSize + lineGap);
\r
3500 *y = boardRect.top + lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
\r
3505 DrawCoordsOnDC(HDC hdc)
\r
3507 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
3508 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
3509 char str[2] = { NULLCHAR, NULLCHAR };
\r
3510 int oldMode, oldAlign, x, y, start, i;
\r
3514 if (!appData.showCoords)
\r
3517 start = flipView ? 1-(ONE!='1') : 23+(ONE!='1')-BOARD_HEIGHT;
\r
3519 oldBrush = SelectObject(hdc, GetStockObject(BLACK_BRUSH));
\r
3520 oldMode = SetBkMode(hdc, (appData.monoMode ? OPAQUE : TRANSPARENT));
\r
3521 oldAlign = GetTextAlign(hdc);
\r
3522 oldFont = SelectObject(hdc, font[boardSize][COORD_FONT]->hf);
\r
3524 y = boardRect.top + lineGap;
\r
3525 x = boardRect.left + lineGap + gameInfo.holdingsWidth*(squareSize + lineGap);
\r
3527 SetTextAlign(hdc, TA_LEFT|TA_TOP);
\r
3528 for (i = 0; i < BOARD_HEIGHT; i++) {
\r
3529 str[0] = files[start + i];
\r
3530 ExtTextOut(hdc, x + 2, y + 1, 0, NULL, str, 1, NULL);
\r
3531 y += squareSize + lineGap;
\r
3534 start = flipView ? 12-(BOARD_RGHT-BOARD_LEFT) : 12;
\r
3536 SetTextAlign(hdc, TA_RIGHT|TA_BOTTOM);
\r
3537 for (i = 0; i < BOARD_RGHT - BOARD_LEFT; i++) {
\r
3538 str[0] = ranks[start + i];
\r
3539 ExtTextOut(hdc, x + squareSize - 2, y - 1, 0, NULL, str, 1, NULL);
\r
3540 x += squareSize + lineGap;
\r
3543 SelectObject(hdc, oldBrush);
\r
3544 SetBkMode(hdc, oldMode);
\r
3545 SetTextAlign(hdc, oldAlign);
\r
3546 SelectObject(hdc, oldFont);
\r
3550 DrawGridOnDC(HDC hdc)
\r
3554 if (lineGap != 0) {
\r
3555 oldPen = SelectObject(hdc, gridPen);
\r
3556 PolyPolyline(hdc, gridEndpoints, gridVertexCounts, BOARD_WIDTH+BOARD_HEIGHT + 2);
\r
3557 SelectObject(hdc, oldPen);
\r
3561 #define HIGHLIGHT_PEN 0
\r
3562 #define PREMOVE_PEN 1
\r
3565 DrawHighlightOnDC(HDC hdc, BOOLEAN on, int x, int y, int pen)
\r
3568 HPEN oldPen, hPen;
\r
3569 if (lineGap == 0) return;
\r
3571 x1 = boardRect.left +
\r
3572 lineGap/2 + ((BOARD_WIDTH-1)-x) * (squareSize + lineGap);
\r
3573 y1 = boardRect.top +
\r
3574 lineGap/2 + y * (squareSize + lineGap);
\r
3576 x1 = boardRect.left +
\r
3577 lineGap/2 + x * (squareSize + lineGap);
\r
3578 y1 = boardRect.top +
\r
3579 lineGap/2 + ((BOARD_HEIGHT-1)-y) * (squareSize + lineGap);
\r
3581 hPen = pen ? premovePen : highlightPen;
\r
3582 oldPen = SelectObject(hdc, on ? hPen : gridPen);
\r
3583 MoveToEx(hdc, x1, y1, NULL);
\r
3584 LineTo(hdc, x1 + squareSize + lineGap, y1);
\r
3585 LineTo(hdc, x1 + squareSize + lineGap, y1 + squareSize + lineGap);
\r
3586 LineTo(hdc, x1, y1 + squareSize + lineGap);
\r
3587 LineTo(hdc, x1, y1);
\r
3588 SelectObject(hdc, oldPen);
\r
3592 DrawHighlightsOnDC(HDC hdc)
\r
3595 for (i=0; i<2; i++) {
\r
3596 if (highlightInfo.sq[i].x >= 0 && highlightInfo.sq[i].y >= 0)
\r
3597 DrawHighlightOnDC(hdc, TRUE,
\r
3598 highlightInfo.sq[i].x, highlightInfo.sq[i].y,
\r
3601 for (i=0; i<2; i++) {
\r
3602 if (premoveHighlightInfo.sq[i].x >= 0 &&
\r
3603 premoveHighlightInfo.sq[i].y >= 0) {
\r
3604 DrawHighlightOnDC(hdc, TRUE,
\r
3605 premoveHighlightInfo.sq[i].x,
\r
3606 premoveHighlightInfo.sq[i].y,
\r
3612 /* Note: sqcolor is used only in monoMode */
\r
3613 /* Note that this code is largely duplicated in woptions.c,
\r
3614 function DrawSampleSquare, so that needs to be updated too */
\r
3616 DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, HDC tmphdc)
\r
3618 HBITMAP oldBitmap;
\r
3622 if (appData.blindfold) return;
\r
3624 /* [AS] Use font-based pieces if needed */
\r
3625 if( fontBitmapSquareSize >= 0 && squareSize > 32 ) {
\r
3626 /* Create piece bitmaps, or do nothing if piece set is up to date */
\r
3627 CreatePiecesFromFont();
\r
3629 if( fontBitmapSquareSize == squareSize ) {
\r
3630 int index = TranslatePieceToFontPiece(piece);
\r
3632 SelectObject( tmphdc, hPieceMask[ index ] );
\r
3636 squareSize, squareSize,
\r
3641 SelectObject( tmphdc, hPieceFace[ index ] );
\r
3645 squareSize, squareSize,
\r
3654 if (appData.monoMode) {
\r
3655 SelectObject(tmphdc, PieceBitmap(piece,
\r
3656 color == sqcolor ? OUTLINE_PIECE : SOLID_PIECE));
\r
3657 BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0,
\r
3658 sqcolor ? SRCCOPY : NOTSRCCOPY);
\r