2 * WinBoard.c -- Windows NT front end to XBoard
\r
3 * $Id: winboard.c,v 2.3 2003/11/25 05:25:20 mann Exp $
\r
5 * Copyright 1991 by Digital Equipment Corporation, Maynard,
\r
6 * Massachusetts. Enhancements Copyright
\r
7 * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software
\r
10 * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,
\r
11 * which was written and is copyrighted by Wayne Christopher.
\r
13 * The following terms apply to Digital Equipment Corporation's copyright
\r
14 * interest in XBoard:
\r
15 * ------------------------------------------------------------------------
\r
16 * All Rights Reserved
\r
18 * Permission to use, copy, modify, and distribute this software and its
\r
19 * documentation for any purpose and without fee is hereby granted,
\r
20 * provided that the above copyright notice appear in all copies and that
\r
21 * both that copyright notice and this permission notice appear in
\r
22 * supporting documentation, and that the name of Digital not be
\r
23 * used in advertising or publicity pertaining to distribution of the
\r
24 * software without specific, written prior permission.
\r
26 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
\r
27 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
\r
28 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
\r
29 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
\r
30 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
\r
31 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
\r
33 * ------------------------------------------------------------------------
\r
35 * The following terms apply to the enhanced version of XBoard
\r
36 * distributed by the Free Software Foundation:
\r
37 * ------------------------------------------------------------------------
\r
39 * GNU XBoard is free software: you can redistribute it and/or modify
\r
40 * it under the terms of the GNU General Public License as published by
\r
41 * the Free Software Foundation, either version 3 of the License, or (at
\r
42 * your option) any later version.
\r
44 * GNU XBoard is distributed in the hope that it will be useful, but
\r
45 * WITHOUT ANY WARRANTY; without even the implied warranty of
\r
46 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
47 * General Public License for more details.
\r
49 * You should have received a copy of the GNU General Public License
\r
50 * along with this program. If not, see http://www.gnu.org/licenses/. *
\r
52 *------------------------------------------------------------------------
\r
53 ** See the file ChangeLog for a revision history. */
\r
57 #include <windows.h>
\r
58 #include <winuser.h>
\r
59 #include <winsock.h>
\r
60 #include <commctrl.h>
\r
66 #include <sys/stat.h>
\r
69 #include <commdlg.h>
\r
71 #include <richedit.h>
\r
72 #include <mmsystem.h>
\r
80 #include "winboard.h"
\r
81 #include "frontend.h"
\r
82 #include "backend.h"
\r
84 #include "wclipbrd.h"
\r
85 #include "wgamelist.h"
\r
86 #include "wedittags.h"
\r
87 #include "woptions.h"
\r
88 #include "wsockerr.h"
\r
89 #include "defaults.h"
\r
93 //void InitEngineUCI( const char * iniDir, ChessProgramState * cps );
\r
96 void mysrandom(unsigned int seed);
\r
98 extern int whiteFlag, blackFlag;
\r
99 Boolean flipClock = FALSE;
\r
101 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);
\r
104 ChessSquare piece;
\r
105 POINT pos; /* window coordinates of current pos */
\r
106 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
107 POINT from; /* board coordinates of the piece's orig pos */
\r
108 POINT to; /* board coordinates of the piece's new pos */
\r
111 static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };
\r
114 POINT start; /* window coordinates of start pos */
\r
115 POINT pos; /* window coordinates of current pos */
\r
116 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
117 POINT from; /* board coordinates of the piece's orig pos */
\r
120 static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} };
\r
123 POINT sq[2]; /* board coordinates of from, to squares */
\r
126 static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} };
\r
127 static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };
\r
129 /* Window class names */
\r
130 char szAppName[] = "WinBoard";
\r
131 char szConsoleName[] = "WBConsole";
\r
133 /* Title bar text */
\r
134 char szTitle[] = "WinBoard";
\r
135 char szConsoleTitle[] = "ICS Interaction";
\r
138 char *settingsFileName;
\r
139 BOOLEAN saveSettingsOnExit;
\r
140 char installDir[MSG_SIZ];
\r
142 BoardSize boardSize;
\r
143 BOOLEAN chessProgram;
\r
144 static int boardX, boardY, consoleX, consoleY, consoleW, consoleH;
\r
145 static int squareSize, lineGap, minorSize;
\r
146 static int winWidth, winHeight;
\r
147 static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo
\r
148 static int logoHeight = 0;
\r
149 static char messageText[MESSAGE_TEXT_MAX];
\r
150 static int clockTimerEvent = 0;
\r
151 static int loadGameTimerEvent = 0;
\r
152 static int analysisTimerEvent = 0;
\r
153 static DelayedEventCallback delayedTimerCallback;
\r
154 static int delayedTimerEvent = 0;
\r
155 static int buttonCount = 2;
\r
156 char *icsTextMenuString;
\r
158 char *firstChessProgramNames;
\r
159 char *secondChessProgramNames;
\r
161 #define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */
\r
163 #define PALETTESIZE 256
\r
165 HINSTANCE hInst; /* current instance */
\r
166 HWND hwndMain = NULL; /* root window*/
\r
167 HWND hwndConsole = NULL;
\r
168 BOOLEAN alwaysOnTop = FALSE;
\r
170 COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
\r
171 blackPieceColor, highlightSquareColor, premoveHighlightColor;
\r
173 ColorClass currentColorClass;
\r
175 HWND hCommPort = NULL; /* currently open comm port */
\r
176 static HWND hwndPause; /* pause button */
\r
177 static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */
\r
178 static HBRUSH lightSquareBrush, darkSquareBrush,
\r
179 blackSquareBrush, /* [HGM] for band between board and holdings */
\r
180 whitePieceBrush, blackPieceBrush, iconBkgndBrush, outlineBrush;
\r
181 static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];
\r
182 static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];
\r
183 static HPEN gridPen = NULL;
\r
184 static HPEN highlightPen = NULL;
\r
185 static HPEN premovePen = NULL;
\r
186 static NPLOGPALETTE pLogPal;
\r
187 static BOOL paletteChanged = FALSE;
\r
188 static HICON iconWhite, iconBlack, iconCurrent;
\r
189 static int doingSizing = FALSE;
\r
190 static int lastSizing = 0;
\r
191 static int prevStderrPort;
\r
193 /* [AS] Support for background textures */
\r
194 #define BACK_TEXTURE_MODE_DISABLED 0
\r
195 #define BACK_TEXTURE_MODE_PLAIN 1
\r
196 #define BACK_TEXTURE_MODE_FULL_RANDOM 2
\r
198 static HBITMAP liteBackTexture = NULL;
\r
199 static HBITMAP darkBackTexture = NULL;
\r
200 static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
201 static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
202 static int backTextureSquareSize = 0;
\r
203 static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_SIZE][BOARD_SIZE];
\r
205 #if __GNUC__ && !defined(_winmajor)
\r
206 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */
\r
208 #define oldDialog (_winmajor < 4)
\r
211 char *defaultTextAttribs[] =
\r
213 COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,
\r
214 COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,
\r
224 int cliWidth, cliHeight;
\r
227 SizeInfo sizeInfo[] =
\r
229 { "tiny", 21, 0, 1, 1, 0, 0 },
\r
230 { "teeny", 25, 1, 1, 1, 0, 0 },
\r
231 { "dinky", 29, 1, 1, 1, 0, 0 },
\r
232 { "petite", 33, 1, 1, 1, 0, 0 },
\r
233 { "slim", 37, 2, 1, 0, 0, 0 },
\r
234 { "small", 40, 2, 1, 0, 0, 0 },
\r
235 { "mediocre", 45, 2, 1, 0, 0, 0 },
\r
236 { "middling", 49, 2, 0, 0, 0, 0 },
\r
237 { "average", 54, 2, 0, 0, 0, 0 },
\r
238 { "moderate", 58, 3, 0, 0, 0, 0 },
\r
239 { "medium", 64, 3, 0, 0, 0, 0 },
\r
240 { "bulky", 72, 3, 0, 0, 0, 0 },
\r
241 { "large", 80, 3, 0, 0, 0, 0 },
\r
242 { "big", 87, 3, 0, 0, 0, 0 },
\r
243 { "huge", 95, 3, 0, 0, 0, 0 },
\r
244 { "giant", 108, 3, 0, 0, 0, 0 },
\r
245 { "colossal", 116, 4, 0, 0, 0, 0 },
\r
246 { "titanic", 129, 4, 0, 0, 0, 0 },
\r
247 { NULL, 0, 0, 0, 0, 0, 0 }
\r
250 #define MF(x) {x, {0, }, {0, }, 0}
\r
251 MyFont fontRec[NUM_SIZES][NUM_FONTS] =
\r
253 { 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
254 { 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
255 { 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
256 { 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
257 { 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
258 { 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
259 { 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
260 { 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
261 { 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
262 { 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
263 { 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
264 { 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
265 { 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
266 { 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
267 { 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
268 { 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
269 { 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
270 { 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
273 MyFont *font[NUM_SIZES][NUM_FONTS];
\r
282 #define BUTTON_WIDTH (tinyLayout ? 16 : 32)
\r
283 #define N_BUTTONS 5
\r
285 MyButtonDesc buttonDesc[N_BUTTONS] =
\r
287 {"<<", IDM_ToStart, NULL, NULL},
\r
288 {"<", IDM_Backward, NULL, NULL},
\r
289 {"P", IDM_Pause, NULL, NULL},
\r
290 {">", IDM_Forward, NULL, NULL},
\r
291 {">>", IDM_ToEnd, NULL, NULL},
\r
294 int tinyLayout = 0, smallLayout = 0;
\r
295 #define MENU_BAR_ITEMS 6
\r
296 char *menuBarText[2][MENU_BAR_ITEMS+1] = {
\r
297 { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },
\r
298 { "&F", "&M", "&A", "&S", "&O", "&H", NULL },
\r
302 MySound sounds[(int)NSoundClasses];
\r
303 MyTextAttribs textAttribs[(int)NColorClasses];
\r
305 MyColorizeAttribs colorizeAttribs[] = {
\r
306 { (COLORREF)0, 0, "Shout Text" },
\r
307 { (COLORREF)0, 0, "SShout/CShout" },
\r
308 { (COLORREF)0, 0, "Channel 1 Text" },
\r
309 { (COLORREF)0, 0, "Channel Text" },
\r
310 { (COLORREF)0, 0, "Kibitz Text" },
\r
311 { (COLORREF)0, 0, "Tell Text" },
\r
312 { (COLORREF)0, 0, "Challenge Text" },
\r
313 { (COLORREF)0, 0, "Request Text" },
\r
314 { (COLORREF)0, 0, "Seek Text" },
\r
315 { (COLORREF)0, 0, "Normal Text" },
\r
316 { (COLORREF)0, 0, "None" }
\r
321 static char *commentTitle;
\r
322 static char *commentText;
\r
323 static int commentIndex;
\r
324 static Boolean editComment = FALSE;
\r
325 HWND commentDialog = NULL;
\r
326 BOOLEAN commentDialogUp = FALSE;
\r
327 static int commentX, commentY, commentH, commentW;
\r
329 static char *analysisTitle;
\r
330 static char *analysisText;
\r
331 HWND analysisDialog = NULL;
\r
332 BOOLEAN analysisDialogUp = FALSE;
\r
333 static int analysisX, analysisY, analysisH, analysisW;
\r
335 char errorTitle[MSG_SIZ];
\r
336 char errorMessage[2*MSG_SIZ];
\r
337 HWND errorDialog = NULL;
\r
338 BOOLEAN moveErrorMessageUp = FALSE;
\r
339 BOOLEAN consoleEcho = TRUE;
\r
340 CHARFORMAT consoleCF;
\r
341 COLORREF consoleBackgroundColor;
\r
343 char *programVersion;
\r
349 typedef int CPKind;
\r
358 SOCKET sock2; /* stderr socket for OpenRcmd */
\r
361 #define INPUT_SOURCE_BUF_SIZE 4096
\r
363 typedef struct _InputSource {
\r
370 char buf[INPUT_SOURCE_BUF_SIZE];
\r
374 InputCallback func;
\r
375 struct _InputSource *second; /* for stderr thread on CPRcmd */
\r
379 InputSource *consoleInputSource;
\r
384 VOID ConsoleOutput(char* data, int length, int forceVisible);
\r
385 VOID ConsoleCreate();
\r
387 ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
388 VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
\r
389 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
\r
390 VOID ParseCommSettings(char *arg, DCB *dcb);
\r
392 StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
393 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
\r
394 void ParseIcsTextMenu(char *icsTextMenuString);
\r
395 VOID PopUpMoveDialog(char firstchar);
\r
396 VOID PopUpNameDialog(char firstchar);
\r
397 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
\r
401 int GameListOptions();
\r
403 HWND moveHistoryDialog = NULL;
\r
404 BOOLEAN moveHistoryDialogUp = FALSE;
\r
406 WindowPlacement wpMoveHistory;
\r
408 HWND evalGraphDialog = NULL;
\r
409 BOOLEAN evalGraphDialogUp = FALSE;
\r
411 WindowPlacement wpEvalGraph;
\r
413 HWND engineOutputDialog = NULL;
\r
414 BOOLEAN engineOutputDialogUp = FALSE;
\r
416 WindowPlacement wpEngineOutput;
\r
418 VOID MoveHistoryPopUp();
\r
419 VOID MoveHistoryPopDown();
\r
420 VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
421 BOOL MoveHistoryIsUp();
\r
423 VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
424 VOID EvalGraphPopUp();
\r
425 VOID EvalGraphPopDown();
\r
426 BOOL EvalGraphIsUp();
\r
428 VOID EngineOutputPopUp();
\r
429 VOID EngineOutputPopDown();
\r
430 BOOL EngineOutputIsUp();
\r
431 VOID EngineOutputUpdate( FrontEndProgramStats * stats );
\r
433 VOID GothicPopUp(char *title, VariantClass variant);
\r
435 * Setting "frozen" should disable all user input other than deleting
\r
436 * the window. We do this while engines are initializing themselves.
\r
438 static int frozen = 0;
\r
439 static int oldMenuItemState[MENU_BAR_ITEMS];
\r
445 if (frozen) return;
\r
447 hmenu = GetMenu(hwndMain);
\r
448 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
449 oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
\r
451 DrawMenuBar(hwndMain);
\r
454 /* Undo a FreezeUI */
\r
460 if (!frozen) return;
\r
462 hmenu = GetMenu(hwndMain);
\r
463 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
464 EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
\r
466 DrawMenuBar(hwndMain);
\r
469 /*---------------------------------------------------------------------------*\
\r
473 \*---------------------------------------------------------------------------*/
\r
476 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
\r
477 LPSTR lpCmdLine, int nCmdShow)
\r
480 HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
\r
484 LoadLibrary("RICHED32.DLL");
\r
485 consoleCF.cbSize = sizeof(CHARFORMAT);
\r
487 if (!InitApplication(hInstance)) {
\r
490 if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
\r
494 hAccelMain = LoadAccelerators (hInstance, szAppName);
\r
495 hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
\r
496 hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
\r
498 /* Acquire and dispatch messages until a WM_QUIT message is received. */
\r
500 while (GetMessage(&msg, /* message structure */
\r
501 NULL, /* handle of window receiving the message */
\r
502 0, /* lowest message to examine */
\r
503 0)) /* highest message to examine */
\r
505 if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
\r
506 !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
\r
507 !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
\r
508 !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
\r
509 !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
\r
510 !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
\r
511 !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
\r
512 !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) &&
\r
513 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
\r
514 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
\r
515 TranslateMessage(&msg); /* Translates virtual key codes */
\r
516 DispatchMessage(&msg); /* Dispatches message to window */
\r
521 return (msg.wParam); /* Returns the value from PostQuitMessage */
\r
524 /*---------------------------------------------------------------------------*\
\r
526 * Initialization functions
\r
528 \*---------------------------------------------------------------------------*/
\r
531 InitApplication(HINSTANCE hInstance)
\r
535 /* Fill in window class structure with parameters that describe the */
\r
538 wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
\r
539 wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
\r
540 wc.cbClsExtra = 0; /* No per-class extra data. */
\r
541 wc.cbWndExtra = 0; /* No per-window extra data. */
\r
542 wc.hInstance = hInstance; /* Owner of this class */
\r
543 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
544 wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
\r
545 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
\r
546 wc.lpszMenuName = szAppName; /* Menu name from .RC */
\r
547 wc.lpszClassName = szAppName; /* Name to register as */
\r
549 /* Register the window class and return success/failure code. */
\r
550 if (!RegisterClass(&wc)) return FALSE;
\r
552 wc.style = CS_HREDRAW | CS_VREDRAW;
\r
553 wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
\r
555 wc.cbWndExtra = DLGWINDOWEXTRA;
\r
556 wc.hInstance = hInstance;
\r
557 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
558 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
\r
559 wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
\r
560 wc.lpszMenuName = NULL;
\r
561 wc.lpszClassName = szConsoleName;
\r
563 if (!RegisterClass(&wc)) return FALSE;
\r
568 /* Set by InitInstance, used by EnsureOnScreen */
\r
569 int screenHeight, screenWidth;
\r
572 EnsureOnScreen(int *x, int *y)
\r
574 // int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
\r
575 /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
\r
576 if (*x > screenWidth - 32) *x = 0;
\r
577 if (*y > screenHeight - 32) *y = 0;
\r
578 if (*x < 0) *x = 0;
\r
579 if (*y < 0) *y = 0;
\r
580 // if (*x < 10) *x = 10;
\r
581 // if (*y < gap) *y = gap;
\r
585 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
\r
587 HWND hwnd; /* Main window handle. */
\r
589 WINDOWPLACEMENT wp;
\r
592 hInst = hInstance; /* Store instance handle in our global variable */
\r
594 if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
\r
595 *filepart = NULLCHAR;
\r
597 GetCurrentDirectory(MSG_SIZ, installDir);
\r
599 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise
\r
600 InitAppData(lpCmdLine); /* Get run-time parameters */
\r
601 if (appData.debugMode) {
\r
602 debugFP = fopen(appData.nameOfDebugFile, "w");
\r
603 setbuf(debugFP, NULL);
\r
608 // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()
\r
609 // InitEngineUCI( installDir, &second );
\r
611 /* Create a main window for this application instance. */
\r
612 hwnd = CreateWindow(szAppName, szTitle,
\r
613 (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
\r
614 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
\r
615 NULL, NULL, hInstance, NULL);
\r
618 /* If window could not be created, return "failure" */
\r
623 /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */
\r
624 if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {
\r
625 first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
627 if (first.programLogo == NULL && appData.debugMode) {
\r
628 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );
\r
630 } else if(appData.autoLogo) {
\r
631 if(appData.firstDirectory && appData.firstDirectory[0]) {
\r
633 sprintf(buf, "%s/logo.bmp", appData.firstDirectory);
\r
634 first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
638 if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {
\r
639 second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
641 if (second.programLogo == NULL && appData.debugMode) {
\r
642 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );
\r
644 } else if(appData.autoLogo) {
\r
645 if(appData.secondDirectory && appData.secondDirectory[0]) {
\r
647 sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);
\r
648 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
652 iconWhite = LoadIcon(hInstance, "icon_white");
\r
653 iconBlack = LoadIcon(hInstance, "icon_black");
\r
654 iconCurrent = iconWhite;
\r
655 InitDrawingColors();
\r
656 screenHeight = GetSystemMetrics(SM_CYSCREEN);
\r
657 screenWidth = GetSystemMetrics(SM_CXSCREEN);
\r
658 for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
\r
659 /* Compute window size for each board size, and use the largest
\r
660 size that fits on this screen as the default. */
\r
661 InitDrawingSizes((BoardSize)ibs, 0);
\r
662 if (boardSize == (BoardSize)-1 &&
\r
663 winHeight <= screenHeight
\r
664 - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10
\r
665 && winWidth <= screenWidth) {
\r
666 boardSize = (BoardSize)ibs;
\r
670 InitDrawingSizes(boardSize, 0);
\r
672 buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
\r
674 /* [AS] Load textures if specified */
\r
675 ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );
\r
677 if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {
\r
678 liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
679 liteBackTextureMode = appData.liteBackTextureMode;
\r
681 if (liteBackTexture == NULL && appData.debugMode) {
\r
682 fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );
\r
686 if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {
\r
687 darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
688 darkBackTextureMode = appData.darkBackTextureMode;
\r
690 if (darkBackTexture == NULL && appData.debugMode) {
\r
691 fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );
\r
695 mysrandom( (unsigned) time(NULL) );
\r
697 /* [AS] Restore layout */
\r
698 if( wpMoveHistory.visible ) {
\r
699 MoveHistoryPopUp();
\r
702 if( wpEvalGraph.visible ) {
\r
706 if( wpEngineOutput.visible ) {
\r
707 EngineOutputPopUp();
\r
712 /* Make the window visible; update its client area; and return "success" */
\r
713 EnsureOnScreen(&boardX, &boardY);
\r
714 wp.length = sizeof(WINDOWPLACEMENT);
\r
716 wp.showCmd = nCmdShow;
\r
717 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
\r
718 wp.rcNormalPosition.left = boardX;
\r
719 wp.rcNormalPosition.right = boardX + winWidth;
\r
720 wp.rcNormalPosition.top = boardY;
\r
721 wp.rcNormalPosition.bottom = boardY + winHeight;
\r
722 SetWindowPlacement(hwndMain, &wp);
\r
724 SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
725 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
728 /* [AS] Disable the FRC stuff if not playing the proper variant */
\r
729 if( gameInfo.variant != VariantFischeRandom ) {
\r
730 EnableMenuItem( GetMenu(hwndMain), IDM_NewGameFRC, MF_GRAYED );
\r
735 SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
736 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
738 ShowWindow(hwndConsole, nCmdShow);
\r
740 UpdateWindow(hwnd);
\r
748 ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
\r
749 ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
\r
750 ArgSettingsFilename
\r
758 String *pString; // ArgString
\r
759 int *pInt; // ArgInt
\r
760 float *pFloat; // ArgFloat
\r
761 Boolean *pBoolean; // ArgBoolean
\r
762 COLORREF *pColor; // ArgColor
\r
763 ColorClass cc; // ArgAttribs
\r
764 String *pFilename; // ArgFilename
\r
765 BoardSize *pBoardSize; // ArgBoardSize
\r
766 int whichFont; // ArgFont
\r
767 DCB *pDCB; // ArgCommSettings
\r
768 String *pFilename; // ArgSettingsFilename
\r
776 ArgDescriptor argDescriptors[] = {
\r
777 /* positional arguments */
\r
778 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
779 { "", ArgNone, NULL },
\r
780 /* keyword arguments */
\r
781 { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },
\r
782 { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },
\r
783 { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },
\r
784 { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },
\r
785 { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },
\r
786 { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },
\r
787 { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },
\r
788 { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },
\r
789 { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },
\r
790 { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },
\r
791 { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },
\r
792 { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },
\r
793 { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },
\r
794 { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },
\r
795 { "initString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
796 { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
797 { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },
\r
798 { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,
\r
800 { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,
\r
802 { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,
\r
804 { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },
\r
805 { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,
\r
807 { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },
\r
808 { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
809 { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
810 { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
811 { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
812 { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },
\r
813 { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },
\r
814 { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
815 { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
816 { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
817 { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
818 { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
819 { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
820 { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
821 { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
822 { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
823 { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
824 /*!!bitmapDirectory?*/
\r
825 { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
826 { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
827 { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
828 { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
829 { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },
\r
830 { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },
\r
831 { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },
\r
832 { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },
\r
833 { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },
\r
834 { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },
\r
835 { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },
\r
836 { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },
\r
837 { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
838 { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
839 { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
840 { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
841 { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
842 { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
843 { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
844 { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
845 { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
846 { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
847 { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
848 { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
849 { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },
\r
850 { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },
\r
851 { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
852 { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
853 { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },
\r
854 { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },
\r
855 { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },
\r
856 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
857 { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
858 { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
859 { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
860 { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },
\r
861 { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },
\r
862 { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },
\r
863 { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },
\r
864 { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
865 { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
866 { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
867 { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
868 { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
869 { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
870 { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
871 { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
872 { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },
\r
873 { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },
\r
874 { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
875 { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
876 { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
877 { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
878 { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },
\r
879 { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },
\r
880 { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
881 { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
882 { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },
\r
883 { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },
\r
884 { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
885 { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
886 { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },
\r
887 { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },
\r
888 { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
889 { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
890 { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
891 { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
892 { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
893 { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
894 { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },
\r
895 { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },
\r
896 { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
897 { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
898 { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },
\r
899 { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },
\r
900 { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
901 { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
902 { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },
\r
903 { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },
\r
904 { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
905 { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
906 { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },
\r
907 { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },
\r
908 { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
909 { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
910 { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },
\r
911 { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },
\r
912 { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
913 { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
914 { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },
\r
915 { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
916 { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
917 { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
918 { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors,
\r
919 FALSE }, /* only so that old WinBoard.ini files from betas can be read */
\r
920 { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },
\r
921 { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },
\r
922 { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },
\r
923 { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },
\r
924 { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },
\r
925 { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },
\r
926 { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE }, /* [AS] */
\r
927 { "boardSize", ArgBoardSize, (LPVOID) &boardSize,
\r
928 TRUE }, /* must come after all fonts */
\r
929 { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },
\r
930 { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,
\r
931 FALSE }, /* historical; kept only so old winboard.ini files will parse */
\r
932 { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },
\r
933 { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },
\r
934 { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
935 { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
936 { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },
\r
937 { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },
\r
938 { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
939 { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
940 { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },
\r
941 { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },
\r
942 { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
943 { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
944 { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },
\r
945 { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },
\r
946 { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
947 { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
948 { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },
\r
949 { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },
\r
950 { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
951 { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
952 { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },
\r
953 { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },
\r
954 { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
955 { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
956 { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },
\r
957 { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
958 { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
959 { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
961 { "cmailGameName", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
962 { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
964 { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },
\r
965 { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
966 { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
967 { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
968 { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },
\r
969 { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
970 { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
971 { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
972 { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },
\r
973 { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },
\r
974 { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
975 { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
976 { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },
\r
977 { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },
\r
978 { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
979 { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
980 { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },
\r
981 { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },
\r
982 { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
983 { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
984 { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },
\r
985 { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },
\r
986 { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
987 { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
988 { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },
\r
989 { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },
\r
990 { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
991 { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
992 { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },
\r
993 { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },
\r
994 { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },
\r
995 { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
996 { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
997 { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },
\r
998 { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},
\r
999 { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},
\r
1000 { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1001 { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1002 { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},
\r
1003 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1004 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1005 { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },
\r
1006 { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1007 { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1008 { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },
\r
1009 { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },
\r
1010 { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1011 { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1012 { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },
\r
1013 { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },
\r
1014 { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },
\r
1015 { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1016 { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1017 { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },
\r
1018 { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },
\r
1019 { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1020 { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1021 { "highlightLastMove", ArgBoolean,
\r
1022 (LPVOID) &appData.highlightLastMove, TRUE },
\r
1023 { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1024 { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1025 { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1026 { "highlightDragging", ArgBoolean,
\r
1027 (LPVOID) &appData.highlightDragging, TRUE },
\r
1028 { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },
\r
1029 { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1030 { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1031 { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },
\r
1032 { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },
\r
1033 { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1034 { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1035 { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },
\r
1036 { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },
\r
1037 { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },
\r
1038 { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },
\r
1039 { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },
\r
1040 { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },
\r
1041 { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },
\r
1042 { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },
\r
1043 { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },
\r
1044 { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },
\r
1045 { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },
\r
1046 { "soundShout", ArgFilename,
\r
1047 (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },
\r
1048 { "soundSShout", ArgFilename,
\r
1049 (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },
\r
1050 { "soundChannel1", ArgFilename,
\r
1051 (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },
\r
1052 { "soundChannel", ArgFilename,
\r
1053 (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },
\r
1054 { "soundKibitz", ArgFilename,
\r
1055 (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },
\r
1056 { "soundTell", ArgFilename,
\r
1057 (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },
\r
1058 { "soundChallenge", ArgFilename,
\r
1059 (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },
\r
1060 { "soundRequest", ArgFilename,
\r
1061 (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },
\r
1062 { "soundSeek", ArgFilename,
\r
1063 (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },
\r
1064 { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },
\r
1065 { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },
\r
1066 { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },
\r
1067 { "soundIcsLoss", ArgFilename,
\r
1068 (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },
\r
1069 { "soundIcsDraw", ArgFilename,
\r
1070 (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },
\r
1071 { "soundIcsUnfinished", ArgFilename,
\r
1072 (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},
\r
1073 { "soundIcsAlarm", ArgFilename,
\r
1074 (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },
\r
1075 { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },
\r
1076 { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },
\r
1077 { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1078 { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1079 { "reuseChessPrograms", ArgBoolean,
\r
1080 (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */
\r
1081 { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },
\r
1082 { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },
\r
1083 { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1084 { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1085 { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },
\r
1086 { "x", ArgInt, (LPVOID) &boardX, TRUE },
\r
1087 { "y", ArgInt, (LPVOID) &boardY, TRUE },
\r
1088 { "icsX", ArgInt, (LPVOID) &consoleX, TRUE },
\r
1089 { "icsY", ArgInt, (LPVOID) &consoleY, TRUE },
\r
1090 { "icsW", ArgInt, (LPVOID) &consoleW, TRUE },
\r
1091 { "icsH", ArgInt, (LPVOID) &consoleH, TRUE },
\r
1092 { "analysisX", ArgInt, (LPVOID) &analysisX, TRUE },
\r
1093 { "analysisY", ArgInt, (LPVOID) &analysisY, TRUE },
\r
1094 { "analysisW", ArgInt, (LPVOID) &analysisW, TRUE },
\r
1095 { "analysisH", ArgInt, (LPVOID) &analysisH, TRUE },
\r
1096 { "commentX", ArgInt, (LPVOID) &commentX, TRUE },
\r
1097 { "commentY", ArgInt, (LPVOID) &commentY, TRUE },
\r
1098 { "commentW", ArgInt, (LPVOID) &commentW, TRUE },
\r
1099 { "commentH", ArgInt, (LPVOID) &commentH, TRUE },
\r
1100 { "tagsX", ArgInt, (LPVOID) &editTagsX, TRUE },
\r
1101 { "tagsY", ArgInt, (LPVOID) &editTagsY, TRUE },
\r
1102 { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },
\r
1103 { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },
\r
1104 { "gameListX", ArgInt, (LPVOID) &gameListX, TRUE },
\r
1105 { "gameListY", ArgInt, (LPVOID) &gameListY, TRUE },
\r
1106 { "gameListW", ArgInt, (LPVOID) &gameListW, TRUE },
\r
1107 { "gameListH", ArgInt, (LPVOID) &gameListH, TRUE },
\r
1108 { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1109 { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1110 { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },
\r
1111 { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },
\r
1112 { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },
\r
1113 { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1114 { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1115 { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },
\r
1116 { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },
\r
1117 { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,
\r
1119 { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,
\r
1121 { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1122 { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1123 { "variant", ArgString, (LPVOID) &appData.variant, FALSE },
\r
1124 { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion, FALSE },
\r
1125 { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,FALSE },
\r
1126 { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },
\r
1127 { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },
\r
1128 { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1129 { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1130 /* [AS] New features */
\r
1131 { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE },
\r
1132 { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE },
\r
1133 { "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE },
\r
1134 { "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE },
\r
1135 { "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE },
\r
1136 { "darkBackTextureFile", ArgString, (LPVOID) &appData.darkBackTextureFile, TRUE },
\r
1137 { "liteBackTextureMode", ArgInt, (LPVOID) &appData.liteBackTextureMode, TRUE },
\r
1138 { "darkBackTextureMode", ArgInt, (LPVOID) &appData.darkBackTextureMode, TRUE },
\r
1139 { "renderPiecesWithFont", ArgString, (LPVOID) &appData.renderPiecesWithFont, TRUE },
\r
1140 { "fontPieceToCharTable", ArgString, (LPVOID) &appData.fontToPieceTable, TRUE },
\r
1141 { "fontPieceBackColorWhite", ArgColor, (LPVOID) &appData.fontBackColorWhite, TRUE },
\r
1142 { "fontPieceForeColorWhite", ArgColor, (LPVOID) &appData.fontForeColorWhite, TRUE },
\r
1143 { "fontPieceBackColorBlack", ArgColor, (LPVOID) &appData.fontBackColorBlack, TRUE },
\r
1144 { "fontPieceForeColorBlack", ArgColor, (LPVOID) &appData.fontForeColorBlack, TRUE },
\r
1145 { "fontPieceSize", ArgInt, (LPVOID) &appData.fontPieceSize, TRUE },
\r
1146 { "overrideLineGap", ArgInt, (LPVOID) &appData.overrideLineGap, TRUE },
\r
1147 { "adjudicateLossThreshold", ArgInt, (LPVOID) &appData.adjudicateLossThreshold, TRUE },
\r
1148 { "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE },
\r
1149 { "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE },
\r
1150 { "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1151 { "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1152 { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },
\r
1153 { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE },
\r
1154 { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE },
\r
1155 { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE },
\r
1156 { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE },
\r
1157 { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE },
\r
1158 { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE },
\r
1159 { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE },
\r
1160 { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE },
\r
1161 { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE },
\r
1162 { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE },
\r
1163 { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE },
\r
1164 { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE },
\r
1165 { "firstIsUCI", ArgBoolean, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1166 { "fUCI", ArgTrue, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1167 { "secondIsUCI", ArgBoolean, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1168 { "sUCI", ArgTrue, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1169 { "firstHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1170 { "fNoOwnBookUCI", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1171 { "firstXBook", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1172 { "secondHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1173 { "sNoOwnBookUCI", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1174 { "secondXBook", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1175 { "polyglotDir", ArgFilename, (LPVOID) &appData.polyglotDir, TRUE },
\r
1176 { "usePolyglotBook", ArgBoolean, (LPVOID) &appData.usePolyglotBook, TRUE },
\r
1177 { "polyglotBook", ArgFilename, (LPVOID) &appData.polyglotBook, TRUE },
\r
1178 { "defaultHashSize", ArgInt, (LPVOID) &appData.defaultHashSize, TRUE },
\r
1179 { "defaultCacheSizeEGTB", ArgInt, (LPVOID) &appData.defaultCacheSizeEGTB, TRUE },
\r
1180 { "defaultPathEGTB", ArgFilename, (LPVOID) &appData.defaultPathEGTB, TRUE },
\r
1182 /* [AS] Layout stuff */
\r
1183 { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },
\r
1184 { "moveHistoryX", ArgInt, (LPVOID) &wpMoveHistory.x, TRUE },
\r
1185 { "moveHistoryY", ArgInt, (LPVOID) &wpMoveHistory.y, TRUE },
\r
1186 { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },
\r
1187 { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },
\r
1189 { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },
\r
1190 { "evalGraphX", ArgInt, (LPVOID) &wpEvalGraph.x, TRUE },
\r
1191 { "evalGraphY", ArgInt, (LPVOID) &wpEvalGraph.y, TRUE },
\r
1192 { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },
\r
1193 { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },
\r
1195 { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },
\r
1196 { "engineOutputX", ArgInt, (LPVOID) &wpEngineOutput.x, TRUE },
\r
1197 { "engineOutputY", ArgInt, (LPVOID) &wpEngineOutput.y, TRUE },
\r
1198 { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },
\r
1199 { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },
\r
1201 /* [HGM] board-size, adjudication and misc. options */
\r
1202 { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE },
\r
1203 { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE },
\r
1204 { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE },
\r
1205 { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE },
\r
1206 { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE },
\r
1207 { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE },
\r
1208 { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE },
\r
1209 { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE },
\r
1210 { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE },
\r
1211 { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE },
\r
1212 { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE },
\r
1213 { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE },
\r
1214 { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE },
\r
1215 { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE },
\r
1216 { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE },
\r
1217 { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE },
\r
1218 { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE },
\r
1219 { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE },
\r
1220 { "userName", ArgString, (LPVOID) &appData.userName, FALSE },
\r
1221 { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE },
\r
1222 { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE },
\r
1223 { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE },
\r
1224 { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE },
\r
1225 { "niceEngines", ArgInt, (LPVOID) &appData.niceEngines, TRUE },
\r
1226 { "firstLogo", ArgFilename, (LPVOID) &appData.firstLogo, FALSE },
\r
1227 { "secondLogo", ArgFilename, (LPVOID) &appData.secondLogo, FALSE },
\r
1228 { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE },
\r
1229 { "firstOptions", ArgString, (LPVOID) &appData.firstOptions, FALSE },
\r
1230 { "secondOptions", ArgString, (LPVOID) &appData.secondOptions, FALSE },
\r
1233 { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },
\r
1234 { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },
\r
1235 { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1236 { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1237 { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },
\r
1238 { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },
\r
1239 { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1240 { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1241 { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },
\r
1242 { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },
\r
1243 { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },
\r
1244 { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE },
\r
1245 { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,
\r
1247 { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE },
\r
1248 { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE },
\r
1249 { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE },
\r
1250 { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1251 { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1252 { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE },
\r
1253 { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,
\r
1255 { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1256 { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1257 { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1258 { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE },
\r
1259 { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE },
\r
1260 { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1261 { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1262 { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1263 { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1264 { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE },
\r
1265 { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE },
\r
1266 { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1267 { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1268 { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },
\r
1269 { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },
\r
1270 { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },
\r
1271 /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */
\r
1272 { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },
\r
1274 /* [HGM] options for broadcasting and time odds */
\r
1275 { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },
\r
1276 { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },
\r
1277 { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },
\r
1278 { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },
\r
1279 { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },
\r
1280 { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },
\r
1281 { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },
\r
1282 { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },
\r
1283 { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },
\r
1284 { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },
\r
1285 { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE },
\r
1286 { NULL, ArgNone, NULL, FALSE }
\r
1290 /* Kludge for indirection files on command line */
\r
1291 char* lastIndirectionFilename;
\r
1292 ArgDescriptor argDescriptorIndirection =
\r
1293 { "", ArgSettingsFilename, (LPVOID) NULL, FALSE };
\r
1297 ExitArgError(char *msg, char *badArg)
\r
1299 char buf[MSG_SIZ];
\r
1301 sprintf(buf, "%s %s", msg, badArg);
\r
1302 DisplayFatalError(buf, 0, 2);
\r
1306 /* Command line font name parser. NULL name means do nothing.
\r
1307 Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"
\r
1308 For backward compatibility, syntax without the colon is also
\r
1309 accepted, but font names with digits in them won't work in that case.
\r
1312 ParseFontName(char *name, MyFontParams *mfp)
\r
1315 if (name == NULL) return;
\r
1317 q = strchr(p, ':');
\r
1319 if (q - p >= sizeof(mfp->faceName))
\r
1320 ExitArgError("Font name too long:", name);
\r
1321 memcpy(mfp->faceName, p, q - p);
\r
1322 mfp->faceName[q - p] = NULLCHAR;
\r
1325 q = mfp->faceName;
\r
1326 while (*p && !isdigit(*p)) {
\r
1328 if (q - mfp->faceName >= sizeof(mfp->faceName))
\r
1329 ExitArgError("Font name too long:", name);
\r
1331 while (q > mfp->faceName && q[-1] == ' ') q--;
\r
1334 if (!*p) ExitArgError("Font point size missing:", name);
\r
1335 mfp->pointSize = (float) atof(p);
\r
1336 mfp->bold = (strchr(p, 'b') != NULL);
\r
1337 mfp->italic = (strchr(p, 'i') != NULL);
\r
1338 mfp->underline = (strchr(p, 'u') != NULL);
\r
1339 mfp->strikeout = (strchr(p, 's') != NULL);
\r
1342 /* Color name parser.
\r
1343 X version accepts X color names, but this one
\r
1344 handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */
\r
1346 ParseColorName(char *name)
\r
1348 int red, green, blue, count;
\r
1349 char buf[MSG_SIZ];
\r
1351 count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);
\r
1353 count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d",
\r
1354 &red, &green, &blue);
\r
1357 sprintf(buf, "Can't parse color name %s", name);
\r
1358 DisplayError(buf, 0);
\r
1359 return RGB(0, 0, 0);
\r
1361 return PALETTERGB(red, green, blue);
\r
1365 void ParseAttribs(COLORREF *color, int *effects, char* argValue)
\r
1367 char *e = argValue;
\r
1371 if (*e == 'b') eff |= CFE_BOLD;
\r
1372 else if (*e == 'i') eff |= CFE_ITALIC;
\r
1373 else if (*e == 'u') eff |= CFE_UNDERLINE;
\r
1374 else if (*e == 's') eff |= CFE_STRIKEOUT;
\r
1375 else if (*e == '#' || isdigit(*e)) break;
\r
1379 *color = ParseColorName(e);
\r
1384 ParseBoardSize(char *name)
\r
1386 BoardSize bs = SizeTiny;
\r
1387 while (sizeInfo[bs].name != NULL) {
\r
1388 if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;
\r
1391 ExitArgError("Unrecognized board size value", name);
\r
1392 return bs; /* not reached */
\r
1397 StringGet(void *getClosure)
\r
1399 char **p = (char **) getClosure;
\r
1404 FileGet(void *getClosure)
\r
1407 FILE* f = (FILE*) getClosure;
\r
1416 /* Parse settings file named "name". If file found, return the
\r
1417 full name in fullname and return TRUE; else return FALSE */
\r
1419 ParseSettingsFile(char *name, char fullname[MSG_SIZ])
\r
1424 if (SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy)) {
\r
1425 f = fopen(fullname, "r");
\r
1427 ParseArgs(FileGet, f);
\r
1436 ParseArgs(GetFunc get, void *cl)
\r
1438 char argName[ARG_MAX];
\r
1439 char argValue[ARG_MAX];
\r
1440 ArgDescriptor *ad;
\r
1449 while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);
\r
1450 if (ch == NULLCHAR) break;
\r
1452 /* Comment to end of line */
\r
1454 while (ch != '\n' && ch != NULLCHAR) ch = get(cl);
\r
1456 } else if (ch == '/' || ch == '-') {
\r
1459 while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&
\r
1460 ch != '\n' && ch != '\t') {
\r
1466 for (ad = argDescriptors; ad->argName != NULL; ad++)
\r
1467 if (strcmp(ad->argName, argName + 1) == 0) break;
\r
1469 if (ad->argName == NULL)
\r
1470 ExitArgError("Unrecognized argument", argName);
\r
1472 } else if (ch == '@') {
\r
1473 /* Indirection file */
\r
1474 ad = &argDescriptorIndirection;
\r
1477 /* Positional argument */
\r
1478 ad = &argDescriptors[posarg++];
\r
1479 strcpy(argName, ad->argName);
\r
1482 if (ad->argType == ArgTrue) {
\r
1483 *(Boolean *) ad->argLoc = TRUE;
\r
1486 if (ad->argType == ArgFalse) {
\r
1487 *(Boolean *) ad->argLoc = FALSE;
\r
1491 while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
\r
1492 if (ch == NULLCHAR || ch == '\n') {
\r
1493 ExitArgError("No value provided for argument", argName);
\r
1497 // Quoting with { }. No characters have to (or can) be escaped.
\r
1498 // Thus the string cannot contain a '}' character.
\r
1518 } else if (ch == '\'' || ch == '"') {
\r
1519 // Quoting with ' ' or " ", with \ as escape character.
\r
1520 // Inconvenient for long strings that may contain Windows filenames.
\r
1537 if (ch == start) {
\r
1546 if (ad->argType == ArgFilename
\r
1547 || ad->argType == ArgSettingsFilename) {
\r
1553 ExitArgError("Incomplete \\ escape in value for", argName);
\r
1577 for (i = 0; i < 3; i++) {
\r
1578 if (ch >= '0' && ch <= '7') {
\r
1579 octval = octval*8 + (ch - '0');
\r
1586 *q++ = (char) octval;
\r
1597 while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {
\r
1604 switch (ad->argType) {
\r
1606 *(int *) ad->argLoc = atoi(argValue);
\r
1610 *(float *) ad->argLoc = (float) atof(argValue);
\r
1615 *(char **) ad->argLoc = strdup(argValue);
\r
1618 case ArgSettingsFilename:
\r
1620 char fullname[MSG_SIZ];
\r
1621 if (ParseSettingsFile(argValue, fullname)) {
\r
1622 if (ad->argLoc != NULL) {
\r
1623 *(char **) ad->argLoc = strdup(fullname);
\r
1626 if (ad->argLoc != NULL) {
\r
1628 ExitArgError("Failed to open indirection file", argValue);
\r
1635 switch (argValue[0]) {
\r
1638 *(Boolean *) ad->argLoc = TRUE;
\r
1642 *(Boolean *) ad->argLoc = FALSE;
\r
1645 ExitArgError("Unrecognized boolean argument value", argValue);
\r
1651 *(COLORREF *)ad->argLoc = ParseColorName(argValue);
\r
1654 case ArgAttribs: {
\r
1655 ColorClass cc = (ColorClass)ad->argLoc;
\r
1656 ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);
\r
1660 case ArgBoardSize:
\r
1661 *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);
\r
1665 ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);
\r
1668 case ArgCommSettings:
\r
1669 ParseCommSettings(argValue, &dcb);
\r
1673 ExitArgError("Unrecognized argument", argValue);
\r
1682 LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
\r
1684 HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
\r
1685 lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);
\r
1688 lf->lfEscapement = 0;
\r
1689 lf->lfOrientation = 0;
\r
1690 lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;
\r
1691 lf->lfItalic = mfp->italic;
\r
1692 lf->lfUnderline = mfp->underline;
\r
1693 lf->lfStrikeOut = mfp->strikeout;
\r
1694 lf->lfCharSet = DEFAULT_CHARSET;
\r
1695 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
1696 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
1697 lf->lfQuality = DEFAULT_QUALITY;
\r
1698 lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
\r
1699 strcpy(lf->lfFaceName, mfp->faceName);
\r
1703 CreateFontInMF(MyFont *mf)
\r
1705 LFfromMFP(&mf->lf, &mf->mfp);
\r
1706 if (mf->hf) DeleteObject(mf->hf);
\r
1707 mf->hf = CreateFontIndirect(&mf->lf);
\r
1711 SetDefaultTextAttribs()
\r
1714 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1715 ParseAttribs(&textAttribs[cc].color,
\r
1716 &textAttribs[cc].effects,
\r
1717 defaultTextAttribs[cc]);
\r
1722 SetDefaultSounds()
\r
1726 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1727 textAttribs[cc].sound.name = strdup("");
\r
1728 textAttribs[cc].sound.data = NULL;
\r
1730 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1731 sounds[sc].name = strdup("");
\r
1732 sounds[sc].data = NULL;
\r
1734 sounds[(int)SoundBell].name = strdup(SOUND_BELL);
\r
1742 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1743 MyLoadSound(&textAttribs[cc].sound);
\r
1745 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1746 MyLoadSound(&sounds[sc]);
\r
1751 InitAppData(LPSTR lpCmdLine)
\r
1754 char buf[ARG_MAX], currDir[MSG_SIZ];
\r
1757 programName = szAppName;
\r
1759 /* Initialize to defaults */
\r
1760 lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);
\r
1761 darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);
\r
1762 whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);
\r
1763 blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);
\r
1764 highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);
\r
1765 premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);
\r
1766 consoleBackgroundColor = ParseColorName(COLOR_BKGD);
\r
1767 SetDefaultTextAttribs();
\r
1768 SetDefaultSounds();
\r
1769 appData.movesPerSession = MOVES_PER_SESSION;
\r
1770 appData.initString = INIT_STRING;
\r
1771 appData.secondInitString = INIT_STRING;
\r
1772 appData.firstComputerString = COMPUTER_STRING;
\r
1773 appData.secondComputerString = COMPUTER_STRING;
\r
1774 appData.firstChessProgram = FIRST_CHESS_PROGRAM;
\r
1775 appData.secondChessProgram = SECOND_CHESS_PROGRAM;
\r
1776 appData.firstPlaysBlack = FALSE;
\r
1777 appData.noChessProgram = FALSE;
\r
1778 chessProgram = FALSE;
\r
1779 appData.firstHost = FIRST_HOST;
\r
1780 appData.secondHost = SECOND_HOST;
\r
1781 appData.firstDirectory = FIRST_DIRECTORY;
\r
1782 appData.secondDirectory = SECOND_DIRECTORY;
\r
1783 appData.bitmapDirectory = "";
\r
1784 appData.remoteShell = REMOTE_SHELL;
\r
1785 appData.remoteUser = "";
\r
1786 appData.timeDelay = TIME_DELAY;
\r
1787 appData.timeControl = TIME_CONTROL;
\r
1788 appData.timeIncrement = TIME_INCREMENT;
\r
1789 appData.icsActive = FALSE;
\r
1790 appData.icsHost = "";
\r
1791 appData.icsPort = ICS_PORT;
\r
1792 appData.icsCommPort = ICS_COMM_PORT;
\r
1793 appData.icsLogon = ICS_LOGON;
\r
1794 appData.icsHelper = "";
\r
1795 appData.useTelnet = FALSE;
\r
1796 appData.telnetProgram = TELNET_PROGRAM;
\r
1797 appData.gateway = "";
\r
1798 appData.loadGameFile = "";
\r
1799 appData.loadGameIndex = 0;
\r
1800 appData.saveGameFile = "";
\r
1801 appData.autoSaveGames = FALSE;
\r
1802 appData.loadPositionFile = "";
\r
1803 appData.loadPositionIndex = 1;
\r
1804 appData.savePositionFile = "";
\r
1805 appData.matchMode = FALSE;
\r
1806 appData.matchGames = 0;
\r
1807 appData.monoMode = FALSE;
\r
1808 appData.debugMode = FALSE;
\r
1809 appData.clockMode = TRUE;
\r
1810 boardSize = (BoardSize) -1; /* determine by screen size */
\r
1811 appData.Iconic = FALSE; /*unused*/
\r
1812 appData.searchTime = "";
\r
1813 appData.searchDepth = 0;
\r
1814 appData.showCoords = FALSE;
\r
1815 appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/
\r
1816 appData.autoCallFlag = FALSE;
\r
1817 appData.flipView = FALSE;
\r
1818 appData.autoFlipView = TRUE;
\r
1819 appData.cmailGameName = "";
\r
1820 appData.alwaysPromoteToQueen = FALSE;
\r
1821 appData.oldSaveStyle = FALSE;
\r
1822 appData.quietPlay = FALSE;
\r
1823 appData.showThinking = FALSE;
\r
1824 appData.ponderNextMove = TRUE;
\r
1825 appData.periodicUpdates = TRUE;
\r
1826 appData.popupExitMessage = TRUE;
\r
1827 appData.popupMoveErrors = FALSE;
\r
1828 appData.autoObserve = FALSE;
\r
1829 appData.autoComment = FALSE;
\r
1830 appData.animate = TRUE;
\r
1831 appData.animSpeed = 10;
\r
1832 appData.animateDragging = TRUE;
\r
1833 appData.highlightLastMove = TRUE;
\r
1834 appData.getMoveList = TRUE;
\r
1835 appData.testLegality = TRUE;
\r
1836 appData.premove = TRUE;
\r
1837 appData.premoveWhite = FALSE;
\r
1838 appData.premoveWhiteText = "";
\r
1839 appData.premoveBlack = FALSE;
\r
1840 appData.premoveBlackText = "";
\r
1841 appData.icsAlarm = TRUE;
\r
1842 appData.icsAlarmTime = 5000;
\r
1843 appData.autoRaiseBoard = TRUE;
\r
1844 appData.localLineEditing = TRUE;
\r
1845 appData.colorize = TRUE;
\r
1846 appData.reuseFirst = TRUE;
\r
1847 appData.reuseSecond = TRUE;
\r
1848 appData.blindfold = FALSE;
\r
1849 appData.icsEngineAnalyze = FALSE;
\r
1850 memset(&dcb, 0, sizeof(DCB)); // required by VS 2002 +
\r
1851 dcb.DCBlength = sizeof(DCB);
\r
1852 dcb.BaudRate = 9600;
\r
1853 dcb.fBinary = TRUE;
\r
1854 dcb.fParity = FALSE;
\r
1855 dcb.fOutxCtsFlow = FALSE;
\r
1856 dcb.fOutxDsrFlow = FALSE;
\r
1857 dcb.fDtrControl = DTR_CONTROL_ENABLE;
\r
1858 dcb.fDsrSensitivity = FALSE;
\r
1859 dcb.fTXContinueOnXoff = TRUE;
\r
1860 dcb.fOutX = FALSE;
\r
1862 dcb.fNull = FALSE;
\r
1863 dcb.fRtsControl = RTS_CONTROL_ENABLE;
\r
1864 dcb.fAbortOnError = FALSE;
\r
1865 /* Microsoft SDK >= Feb. 2003 (MS VS >= 2002) */
\r
1866 #if (defined(_MSC_VER) && _MSC_VER <= 1200)
\r
1867 //dcb.wReserved = 0;
\r
1869 dcb.wReserved = 0;
\r
1872 dcb.Parity = SPACEPARITY;
\r
1873 dcb.StopBits = ONESTOPBIT;
\r
1874 settingsFileName = SETTINGS_FILE;
\r
1875 saveSettingsOnExit = TRUE;
\r
1876 boardX = CW_USEDEFAULT;
\r
1877 boardY = CW_USEDEFAULT;
\r
1878 consoleX = CW_USEDEFAULT;
\r
1879 consoleY = CW_USEDEFAULT;
\r
1880 consoleW = CW_USEDEFAULT;
\r
1881 consoleH = CW_USEDEFAULT;
\r
1882 analysisX = CW_USEDEFAULT;
\r
1883 analysisY = CW_USEDEFAULT;
\r
1884 analysisW = CW_USEDEFAULT;
\r
1885 analysisH = CW_USEDEFAULT;
\r
1886 commentX = CW_USEDEFAULT;
\r
1887 commentY = CW_USEDEFAULT;
\r
1888 commentW = CW_USEDEFAULT;
\r
1889 commentH = CW_USEDEFAULT;
\r
1890 editTagsX = CW_USEDEFAULT;
\r
1891 editTagsY = CW_USEDEFAULT;
\r
1892 editTagsW = CW_USEDEFAULT;
\r
1893 editTagsH = CW_USEDEFAULT;
\r
1894 gameListX = CW_USEDEFAULT;
\r
1895 gameListY = CW_USEDEFAULT;
\r
1896 gameListW = CW_USEDEFAULT;
\r
1897 gameListH = CW_USEDEFAULT;
\r
1898 icsTextMenuString = ICS_TEXT_MENU_DEFAULT;
\r
1899 icsNames = ICS_NAMES;
\r
1900 firstChessProgramNames = FCP_NAMES;
\r
1901 secondChessProgramNames = SCP_NAMES;
\r
1902 appData.initialMode = "";
\r
1903 appData.variant = "normal";
\r
1904 appData.firstProtocolVersion = PROTOVER;
\r
1905 appData.secondProtocolVersion = PROTOVER;
\r
1906 appData.showButtonBar = TRUE;
\r
1908 /* [AS] New properties (see comments in header file) */
\r
1909 appData.firstScoreIsAbsolute = FALSE;
\r
1910 appData.secondScoreIsAbsolute = FALSE;
\r
1911 appData.saveExtendedInfoInPGN = FALSE;
\r
1912 appData.hideThinkingFromHuman = FALSE;
\r
1913 appData.liteBackTextureFile = "";
\r
1914 appData.liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
1915 appData.darkBackTextureFile = "";
\r
1916 appData.darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
1917 appData.renderPiecesWithFont = "";
\r
1918 appData.fontToPieceTable = "";
\r
1919 appData.fontBackColorWhite = 0;
\r
1920 appData.fontForeColorWhite = 0;
\r
1921 appData.fontBackColorBlack = 0;
\r
1922 appData.fontForeColorBlack = 0;
\r
1923 appData.fontPieceSize = 80;
\r
1924 appData.overrideLineGap = 1;
\r
1925 appData.adjudicateLossThreshold = 0;
\r
1926 appData.delayBeforeQuit = 0;
\r
1927 appData.delayAfterQuit = 0;
\r
1928 appData.nameOfDebugFile = "winboard.debug";
\r
1929 appData.pgnEventHeader = "Computer Chess Game";
\r
1930 appData.defaultFrcPosition = -1;
\r
1931 appData.gameListTags = GLT_DEFAULT_TAGS;
\r
1932 appData.saveOutOfBookInfo = TRUE;
\r
1933 appData.showEvalInMoveHistory = TRUE;
\r
1934 appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );
\r
1935 appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );
\r
1936 appData.highlightMoveWithArrow = FALSE;
\r
1937 appData.highlightArrowColor = ParseColorName( "#FFFF80" );
\r
1938 appData.useStickyWindows = TRUE;
\r
1939 appData.adjudicateDrawMoves = 0;
\r
1940 appData.autoDisplayComment = TRUE;
\r
1941 appData.autoDisplayTags = TRUE;
\r
1942 appData.firstIsUCI = FALSE;
\r
1943 appData.secondIsUCI = FALSE;
\r
1944 appData.firstHasOwnBookUCI = TRUE;
\r
1945 appData.secondHasOwnBookUCI = TRUE;
\r
1946 appData.polyglotDir = "";
\r
1947 appData.usePolyglotBook = FALSE;
\r
1948 appData.polyglotBook = "";
\r
1949 appData.defaultHashSize = 64;
\r
1950 appData.defaultCacheSizeEGTB = 4;
\r
1951 appData.defaultPathEGTB = "c:\\egtb";
\r
1952 appData.firstOptions = "";
\r
1953 appData.secondOptions = "";
\r
1955 InitWindowPlacement( &wpMoveHistory );
\r
1956 InitWindowPlacement( &wpEvalGraph );
\r
1957 InitWindowPlacement( &wpEngineOutput );
\r
1959 /* [HGM] User-selectable board size, adjudication control, miscellaneous */
\r
1960 appData.NrFiles = -1;
\r
1961 appData.NrRanks = -1;
\r
1962 appData.holdingsSize = -1;
\r
1963 appData.testClaims = FALSE;
\r
1964 appData.checkMates = FALSE;
\r
1965 appData.materialDraws= FALSE;
\r
1966 appData.trivialDraws = FALSE;
\r
1967 appData.ruleMoves = 51;
\r
1968 appData.drawRepeats = 6;
\r
1969 appData.matchPause = 10000;
\r
1970 appData.alphaRank = FALSE;
\r
1971 appData.allWhite = FALSE;
\r
1972 appData.upsideDown = FALSE;
\r
1973 appData.serverPause = 15;
\r
1974 appData.serverMovesName = NULL;
\r
1975 appData.suppressLoadMoves = FALSE;
\r
1976 appData.firstTimeOdds = 1;
\r
1977 appData.secondTimeOdds = 1;
\r
1978 appData.firstAccumulateTC = 1; // combine previous and current sessions
\r
1979 appData.secondAccumulateTC = 1;
\r
1980 appData.firstNPS = -1; // [HGM] nps: use wall-clock time
\r
1981 appData.secondNPS = -1;
\r
1982 appData.engineComments = 1;
\r
1983 appData.smpCores = 1; // [HGM] SMP: max nr of cores
\r
1984 appData.egtFormats = "";
\r
1987 appData.zippyTalk = ZIPPY_TALK;
\r
1988 appData.zippyPlay = ZIPPY_PLAY;
\r
1989 appData.zippyLines = ZIPPY_LINES;
\r
1990 appData.zippyPinhead = ZIPPY_PINHEAD;
\r
1991 appData.zippyPassword = ZIPPY_PASSWORD;
\r
1992 appData.zippyPassword2 = ZIPPY_PASSWORD2;
\r
1993 appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;
\r
1994 appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;
\r
1995 appData.zippyUseI = ZIPPY_USE_I;
\r
1996 appData.zippyBughouse = ZIPPY_BUGHOUSE;
\r
1997 appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;
\r
1998 appData.zippyGameEnd = ZIPPY_GAME_END;
\r
1999 appData.zippyGameStart = ZIPPY_GAME_START;
\r
2000 appData.zippyAdjourn = ZIPPY_ADJOURN;
\r
2001 appData.zippyAbort = ZIPPY_ABORT;
\r
2002 appData.zippyVariants = ZIPPY_VARIANTS;
\r
2003 appData.zippyMaxGames = ZIPPY_MAX_GAMES;
\r
2004 appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;
\r
2007 /* Point font array elements to structures and
\r
2008 parse default font names */
\r
2009 for (i=0; i<NUM_FONTS; i++) {
\r
2010 for (j=0; j<NUM_SIZES; j++) {
\r
2011 font[j][i] = &fontRec[j][i];
\r
2012 ParseFontName(font[j][i]->def, &font[j][i]->mfp);
\r
2016 /* Parse default settings file if any */
\r
2017 if (ParseSettingsFile(settingsFileName, buf)) {
\r
2018 settingsFileName = strdup(buf);
\r
2021 /* Parse command line */
\r
2022 ParseArgs(StringGet, &lpCmdLine);
\r
2024 /* [HGM] make sure board size is acceptable */
\r
2025 if(appData.NrFiles > BOARD_SIZE ||
\r
2026 appData.NrRanks > BOARD_SIZE )
\r
2027 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
2029 /* [HGM] After parsing the options from the .ini file, and overruling them
\r
2030 * with options from the command line, we now make an even higher priority
\r
2031 * overrule by WB options attached to the engine command line. This so that
\r
2032 * tournament managers can use WB options (such as /timeOdds) that follow
\r
2035 if(appData.firstChessProgram != NULL) {
\r
2036 char *p = StrStr(appData.firstChessProgram, "WBopt");
\r
2037 static char *f = "first";
\r
2038 char buf[MSG_SIZ], *q = buf;
\r
2039 if(p != NULL) { // engine command line contains WinBoard options
\r
2040 sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"
\r
2041 ParseArgs(StringGet, &q);
\r
2042 p[-1] = 0; // cut them offengine command line
\r
2045 // now do same for second chess program
\r
2046 if(appData.secondChessProgram != NULL) {
\r
2047 char *p = StrStr(appData.secondChessProgram, "WBopt");
\r
2048 static char *s = "second";
\r
2049 char buf[MSG_SIZ], *q = buf;
\r
2050 if(p != NULL) { // engine command line contains WinBoard options
\r
2051 sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"
\r
2052 ParseArgs(StringGet, &q);
\r
2053 p[-1] = 0; // cut them offengine command line
\r
2058 /* Propagate options that affect others */
\r
2059 if (appData.matchMode || appData.matchGames) chessProgram = TRUE;
\r
2060 if (appData.icsActive || appData.noChessProgram) {
\r
2061 chessProgram = FALSE; /* not local chess program mode */
\r
2064 /* Open startup dialog if needed */
\r
2065 if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||
\r
2066 (appData.icsActive && *appData.icsHost == NULLCHAR) ||
\r
2067 (chessProgram && (*appData.firstChessProgram == NULLCHAR ||
\r
2068 *appData.secondChessProgram == NULLCHAR))) {
\r
2071 lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);
\r
2072 DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);
\r
2073 FreeProcInstance(lpProc);
\r
2076 /* Make sure save files land in the right (?) directory */
\r
2077 if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {
\r
2078 appData.saveGameFile = strdup(buf);
\r
2080 if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {
\r
2081 appData.savePositionFile = strdup(buf);
\r
2084 /* Finish initialization for fonts and sounds */
\r
2085 for (i=0; i<NUM_FONTS; i++) {
\r
2086 for (j=0; j<NUM_SIZES; j++) {
\r
2087 CreateFontInMF(font[j][i]);
\r
2090 /* xboard, and older WinBoards, controlled the move sound with the
\r
2091 appData.ringBellAfterMoves option. In the current WinBoard, we
\r
2092 always turn the option on (so that the backend will call us),
\r
2093 then let the user turn the sound off by setting it to silence if
\r
2094 desired. To accommodate old winboard.ini files saved by old
\r
2095 versions of WinBoard, we also turn off the sound if the option
\r
2096 was initially set to false. */
\r
2097 if (!appData.ringBellAfterMoves) {
\r
2098 sounds[(int)SoundMove].name = strdup("");
\r
2099 appData.ringBellAfterMoves = TRUE;
\r
2101 GetCurrentDirectory(MSG_SIZ, currDir);
\r
2102 SetCurrentDirectory(installDir);
\r
2104 SetCurrentDirectory(currDir);
\r
2106 p = icsTextMenuString;
\r
2107 if (p[0] == '@') {
\r
2108 FILE* f = fopen(p + 1, "r");
\r
2110 DisplayFatalError(p + 1, errno, 2);
\r
2113 i = fread(buf, 1, sizeof(buf)-1, f);
\r
2115 buf[i] = NULLCHAR;
\r
2118 ParseIcsTextMenu(strdup(p));
\r
2125 HMENU hmenu = GetMenu(hwndMain);
\r
2127 (void) EnableMenuItem(hmenu, IDM_CommPort,
\r
2128 MF_BYCOMMAND|((appData.icsActive &&
\r
2129 *appData.icsCommPort != NULLCHAR) ?
\r
2130 MF_ENABLED : MF_GRAYED));
\r
2131 (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,
\r
2132 MF_BYCOMMAND|(saveSettingsOnExit ?
\r
2133 MF_CHECKED : MF_UNCHECKED));
\r
2138 SaveSettings(char* name)
\r
2141 ArgDescriptor *ad;
\r
2142 WINDOWPLACEMENT wp;
\r
2143 char dir[MSG_SIZ];
\r
2145 if (!hwndMain) return;
\r
2147 GetCurrentDirectory(MSG_SIZ, dir);
\r
2148 SetCurrentDirectory(installDir);
\r
2149 f = fopen(name, "w");
\r
2150 SetCurrentDirectory(dir);
\r
2152 DisplayError(name, errno);
\r
2155 fprintf(f, ";\n");
\r
2156 fprintf(f, "; %s %s.%s Save Settings file\n", PRODUCT, VERSION, PATCHLEVEL);
\r
2157 fprintf(f, ";\n");
\r
2158 fprintf(f, "; You can edit the values of options that are already set in this file,\n");
\r
2159 fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");
\r
2160 fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");
\r
2161 fprintf(f, ";\n");
\r
2163 wp.length = sizeof(WINDOWPLACEMENT);
\r
2164 GetWindowPlacement(hwndMain, &wp);
\r
2165 boardX = wp.rcNormalPosition.left;
\r
2166 boardY = wp.rcNormalPosition.top;
\r
2168 if (hwndConsole) {
\r
2169 GetWindowPlacement(hwndConsole, &wp);
\r
2170 consoleX = wp.rcNormalPosition.left;
\r
2171 consoleY = wp.rcNormalPosition.top;
\r
2172 consoleW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2173 consoleH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2176 if (analysisDialog) {
\r
2177 GetWindowPlacement(analysisDialog, &wp);
\r
2178 analysisX = wp.rcNormalPosition.left;
\r
2179 analysisY = wp.rcNormalPosition.top;
\r
2180 analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2181 analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2184 if (commentDialog) {
\r
2185 GetWindowPlacement(commentDialog, &wp);
\r
2186 commentX = wp.rcNormalPosition.left;
\r
2187 commentY = wp.rcNormalPosition.top;
\r
2188 commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2189 commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2192 if (editTagsDialog) {
\r
2193 GetWindowPlacement(editTagsDialog, &wp);
\r
2194 editTagsX = wp.rcNormalPosition.left;
\r
2195 editTagsY = wp.rcNormalPosition.top;
\r
2196 editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2197 editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2200 if (gameListDialog) {
\r
2201 GetWindowPlacement(gameListDialog, &wp);
\r
2202 gameListX = wp.rcNormalPosition.left;
\r
2203 gameListY = wp.rcNormalPosition.top;
\r
2204 gameListW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2205 gameListH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2208 /* [AS] Move history */
\r
2209 wpMoveHistory.visible = MoveHistoryIsUp();
\r
2211 if( moveHistoryDialog ) {
\r
2212 GetWindowPlacement(moveHistoryDialog, &wp);
\r
2213 wpMoveHistory.x = wp.rcNormalPosition.left;
\r
2214 wpMoveHistory.y = wp.rcNormalPosition.top;
\r
2215 wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2216 wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2219 /* [AS] Eval graph */
\r
2220 wpEvalGraph.visible = EvalGraphIsUp();
\r
2222 if( evalGraphDialog ) {
\r
2223 GetWindowPlacement(evalGraphDialog, &wp);
\r
2224 wpEvalGraph.x = wp.rcNormalPosition.left;
\r
2225 wpEvalGraph.y = wp.rcNormalPosition.top;
\r
2226 wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2227 wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2230 /* [AS] Engine output */
\r
2231 wpEngineOutput.visible = EngineOutputIsUp();
\r
2233 if( engineOutputDialog ) {
\r
2234 GetWindowPlacement(engineOutputDialog, &wp);
\r
2235 wpEngineOutput.x = wp.rcNormalPosition.left;
\r
2236 wpEngineOutput.y = wp.rcNormalPosition.top;
\r
2237 wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2238 wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2241 for (ad = argDescriptors; ad->argName != NULL; ad++) {
\r
2242 if (!ad->save) continue;
\r
2243 switch (ad->argType) {
\r
2246 char *p = *(char **)ad->argLoc;
\r
2247 if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {
\r
2248 /* Quote multiline values or \-containing values
\r
2249 with { } if possible */
\r
2250 fprintf(f, "/%s={%s}\n", ad->argName, p);
\r
2252 /* Else quote with " " */
\r
2253 fprintf(f, "/%s=\"", ad->argName);
\r
2255 if (*p == '\n') fprintf(f, "\n");
\r
2256 else if (*p == '\r') fprintf(f, "\\r");
\r
2257 else if (*p == '\t') fprintf(f, "\\t");
\r
2258 else if (*p == '\b') fprintf(f, "\\b");
\r
2259 else if (*p == '\f') fprintf(f, "\\f");
\r
2260 else if (*p < ' ') fprintf(f, "\\%03o", *p);
\r
2261 else if (*p == '\"') fprintf(f, "\\\"");
\r
2262 else if (*p == '\\') fprintf(f, "\\\\");
\r
2266 fprintf(f, "\"\n");
\r
2271 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);
\r
2274 fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);
\r
2277 fprintf(f, "/%s=%s\n", ad->argName,
\r
2278 (*(Boolean *)ad->argLoc) ? "true" : "false");
\r
2281 if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2284 if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2288 COLORREF color = *(COLORREF *)ad->argLoc;
\r
2289 fprintf(f, "/%s=#%02x%02x%02x\n", ad->argName,
\r
2290 color&0xff, (color>>8)&0xff, (color>>16)&0xff);
\r
2295 MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];
\r
2296 fprintf(f, "/%s=\"%s%s%s%s%s#%02x%02x%02x\"\n", ad->argName,
\r
2297 (ta->effects & CFE_BOLD) ? "b" : "",
\r
2298 (ta->effects & CFE_ITALIC) ? "i" : "",
\r
2299 (ta->effects & CFE_UNDERLINE) ? "u" : "",
\r
2300 (ta->effects & CFE_STRIKEOUT) ? "s" : "",
\r
2301 (ta->effects) ? " " : "",
\r
2302 ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);
\r
2306 if (strchr(*(char **)ad->argLoc, '\"')) {
\r
2307 fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);
\r
2309 fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);
\r
2312 case ArgBoardSize:
\r
2313 fprintf(f, "/%s=%s\n", ad->argName,
\r
2314 sizeInfo[*(BoardSize *)ad->argLoc].name);
\r
2319 for (bs=0; bs<NUM_SIZES; bs++) {
\r
2320 MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;
\r
2321 fprintf(f, "/size=%s ", sizeInfo[bs].name);
\r
2322 fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n",
\r
2323 ad->argName, mfp->faceName, mfp->pointSize,
\r
2324 mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",
\r
2325 mfp->bold ? "b" : "",
\r
2326 mfp->italic ? "i" : "",
\r
2327 mfp->underline ? "u" : "",
\r
2328 mfp->strikeout ? "s" : "");
\r
2332 case ArgCommSettings:
\r
2333 PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);
\r
2341 /*---------------------------------------------------------------------------*\
\r
2343 * GDI board drawing routines
\r
2345 \*---------------------------------------------------------------------------*/
\r
2347 /* [AS] Draw square using background texture */
\r
2348 static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )
\r
2353 return; /* Should never happen! */
\r
2356 SetGraphicsMode( dst, GM_ADVANCED );
\r
2363 /* X reflection */
\r
2368 x.eDx = (FLOAT) dw + dx - 1;
\r
2371 SetWorldTransform( dst, &x );
\r
2374 /* Y reflection */
\r
2380 x.eDy = (FLOAT) dh + dy - 1;
\r
2382 SetWorldTransform( dst, &x );
\r
2390 x.eDx = (FLOAT) dx;
\r
2391 x.eDy = (FLOAT) dy;
\r
2394 SetWorldTransform( dst, &x );
\r
2398 BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );
\r
2406 SetWorldTransform( dst, &x );
\r
2408 ModifyWorldTransform( dst, 0, MWT_IDENTITY );
\r
2411 /* [AS] [HGM] Make room for more piece types, so all pieces can be different */
\r
2413 PM_WP = (int) WhitePawn,
\r
2414 PM_WN = (int) WhiteKnight,
\r
2415 PM_WB = (int) WhiteBishop,
\r
2416 PM_WR = (int) WhiteRook,
\r
2417 PM_WQ = (int) WhiteQueen,
\r
2418 PM_WF = (int) WhiteFerz,
\r
2419 PM_WW = (int) WhiteWazir,
\r
2420 PM_WE = (int) WhiteAlfil,
\r
2421 PM_WM = (int) WhiteMan,
\r
2422 PM_WO = (int) WhiteCannon,
\r
2423 PM_WU = (int) WhiteUnicorn,
\r
2424 PM_WH = (int) WhiteNightrider,
\r
2425 PM_WA = (int) WhiteAngel,
\r
2426 PM_WC = (int) WhiteMarshall,
\r
2427 PM_WAB = (int) WhiteCardinal,
\r
2428 PM_WD = (int) WhiteDragon,
\r
2429 PM_WL = (int) WhiteLance,
\r
2430 PM_WS = (int) WhiteCobra,
\r
2431 PM_WV = (int) WhiteFalcon,
\r
2432 PM_WSG = (int) WhiteSilver,
\r
2433 PM_WG = (int) WhiteGrasshopper,
\r
2434 PM_WK = (int) WhiteKing,
\r
2435 PM_BP = (int) BlackPawn,
\r
2436 PM_BN = (int) BlackKnight,
\r
2437 PM_BB = (int) BlackBishop,
\r
2438 PM_BR = (int) BlackRook,
\r
2439 PM_BQ = (int) BlackQueen,
\r
2440 PM_BF = (int) BlackFerz,
\r
2441 PM_BW = (int) BlackWazir,
\r
2442 PM_BE = (int) BlackAlfil,
\r
2443 PM_BM = (int) BlackMan,
\r
2444 PM_BO = (int) BlackCannon,
\r
2445 PM_BU = (int) BlackUnicorn,
\r
2446 PM_BH = (int) BlackNightrider,
\r
2447 PM_BA = (int) BlackAngel,
\r
2448 PM_BC = (int) BlackMarshall,
\r
2449 PM_BG = (int) BlackGrasshopper,
\r
2450 PM_BAB = (int) BlackCardinal,
\r
2451 PM_BD = (int) BlackDragon,
\r
2452 PM_BL = (int) BlackLance,
\r
2453 PM_BS = (int) BlackCobra,
\r
2454 PM_BV = (int) BlackFalcon,
\r
2455 PM_BSG = (int) BlackSilver,
\r
2456 PM_BK = (int) BlackKing
\r
2459 static HFONT hPieceFont = NULL;
\r
2460 static HBITMAP hPieceMask[(int) EmptySquare];
\r
2461 static HBITMAP hPieceFace[(int) EmptySquare];
\r
2462 static int fontBitmapSquareSize = 0;
\r
2463 static char pieceToFontChar[(int) EmptySquare] =
\r
2464 { 'p', 'n', 'b', 'r', 'q',
\r
2465 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',
\r
2466 'k', 'o', 'm', 'v', 't', 'w',
\r
2467 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',
\r
2470 extern BOOL SetCharTable( char *table, const char * map );
\r
2471 /* [HGM] moved to backend.c */
\r
2473 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )
\r
2476 BYTE r1 = GetRValue( color );
\r
2477 BYTE g1 = GetGValue( color );
\r
2478 BYTE b1 = GetBValue( color );
\r
2484 /* Create a uniform background first */
\r
2485 hbrush = CreateSolidBrush( color );
\r
2486 SetRect( &rc, 0, 0, squareSize, squareSize );
\r
2487 FillRect( hdc, &rc, hbrush );
\r
2488 DeleteObject( hbrush );
\r
2491 /* Vertical gradient, good for pawn, knight and rook, less for queen and king */
\r
2492 int steps = squareSize / 2;
\r
2495 for( i=0; i<steps; i++ ) {
\r
2496 BYTE r = r1 - (r1-r2) * i / steps;
\r
2497 BYTE g = g1 - (g1-g2) * i / steps;
\r
2498 BYTE b = b1 - (b1-b2) * i / steps;
\r
2500 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2501 SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );
\r
2502 FillRect( hdc, &rc, hbrush );
\r
2503 DeleteObject(hbrush);
\r
2506 else if( mode == 2 ) {
\r
2507 /* Diagonal gradient, good more or less for every piece */
\r
2508 POINT triangle[3];
\r
2509 HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );
\r
2510 HBRUSH hbrush_old;
\r
2511 int steps = squareSize;
\r
2514 triangle[0].x = squareSize - steps;
\r
2515 triangle[0].y = squareSize;
\r
2516 triangle[1].x = squareSize;
\r
2517 triangle[1].y = squareSize;
\r
2518 triangle[2].x = squareSize;
\r
2519 triangle[2].y = squareSize - steps;
\r
2521 for( i=0; i<steps; i++ ) {
\r
2522 BYTE r = r1 - (r1-r2) * i / steps;
\r
2523 BYTE g = g1 - (g1-g2) * i / steps;
\r
2524 BYTE b = b1 - (b1-b2) * i / steps;
\r
2526 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2527 hbrush_old = SelectObject( hdc, hbrush );
\r
2528 Polygon( hdc, triangle, 3 );
\r
2529 SelectObject( hdc, hbrush_old );
\r
2530 DeleteObject(hbrush);
\r
2535 SelectObject( hdc, hpen );
\r
2540 [AS] The method I use to create the bitmaps it a bit tricky, but it
\r
2541 seems to work ok. The main problem here is to find the "inside" of a chess
\r
2542 piece: follow the steps as explained below.
\r
2544 static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
\r
2548 COLORREF chroma = RGB(0xFF,0x00,0xFF);
\r
2552 int backColor = whitePieceColor;
\r
2553 int foreColor = blackPieceColor;
\r
2555 if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {
\r
2556 backColor = appData.fontBackColorWhite;
\r
2557 foreColor = appData.fontForeColorWhite;
\r
2559 else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {
\r
2560 backColor = appData.fontBackColorBlack;
\r
2561 foreColor = appData.fontForeColorBlack;
\r
2565 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2567 hbm_old = SelectObject( hdc, hbm );
\r
2571 rc.right = squareSize;
\r
2572 rc.bottom = squareSize;
\r
2574 /* Step 1: background is now black */
\r
2575 FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );
\r
2577 GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );
\r
2579 pt.x = (squareSize - sz.cx) / 2;
\r
2580 pt.y = (squareSize - sz.cy) / 2;
\r
2582 SetBkMode( hdc, TRANSPARENT );
\r
2583 SetTextColor( hdc, chroma );
\r
2584 /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */
\r
2585 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2587 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
\r
2588 /* Step 3: the area outside the piece is filled with white */
\r
2589 // FloodFill( hdc, 0, 0, chroma );
\r
2590 ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );
\r
2591 ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big
\r
2592 ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );
\r
2593 ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );
\r
2594 SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
\r
2596 Step 4: this is the tricky part, the area inside the piece is filled with black,
\r
2597 but if the start point is not inside the piece we're lost!
\r
2598 There should be a better way to do this... if we could create a region or path
\r
2599 from the fill operation we would be fine for example.
\r
2601 // FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );
\r
2602 ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );
\r
2604 { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */
\r
2605 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2606 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2608 SelectObject( dc2, bm2 );
\r
2609 BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy
\r
2610 BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2611 BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2612 BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2613 BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2616 DeleteObject( bm2 );
\r
2619 SetTextColor( hdc, 0 );
\r
2621 Step 5: some fonts have "disconnected" areas that are skipped by the fill:
\r
2622 draw the piece again in black for safety.
\r
2624 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2626 SelectObject( hdc, hbm_old );
\r
2628 if( hPieceMask[index] != NULL ) {
\r
2629 DeleteObject( hPieceMask[index] );
\r
2632 hPieceMask[index] = hbm;
\r
2635 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2637 SelectObject( hdc, hbm );
\r
2640 HDC dc1 = CreateCompatibleDC( hdc_window );
\r
2641 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2642 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2644 SelectObject( dc1, hPieceMask[index] );
\r
2645 SelectObject( dc2, bm2 );
\r
2646 FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );
\r
2647 BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );
\r
2650 Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves
\r
2651 the piece background and deletes (makes transparent) the rest.
\r
2652 Thanks to that mask, we are free to paint the background with the greates
\r
2653 freedom, as we'll be able to mask off the unwanted parts when finished.
\r
2654 We use this, to make gradients and give the pieces a "roundish" look.
\r
2656 SetPieceBackground( hdc, backColor, 2 );
\r
2657 BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );
\r
2661 DeleteObject( bm2 );
\r
2664 SetTextColor( hdc, foreColor );
\r
2665 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2667 SelectObject( hdc, hbm_old );
\r
2669 if( hPieceFace[index] != NULL ) {
\r
2670 DeleteObject( hPieceFace[index] );
\r
2673 hPieceFace[index] = hbm;
\r
2676 static int TranslatePieceToFontPiece( int piece )
\r
2706 case BlackMarshall:
\r
2710 case BlackNightrider:
\r
2716 case BlackUnicorn:
\r
2720 case BlackGrasshopper:
\r
2732 case BlackCardinal:
\r
2739 case WhiteMarshall:
\r
2743 case WhiteNightrider:
\r
2749 case WhiteUnicorn:
\r
2753 case WhiteGrasshopper:
\r
2765 case WhiteCardinal:
\r
2774 void CreatePiecesFromFont()
\r
2777 HDC hdc_window = NULL;
\r
2783 if( fontBitmapSquareSize < 0 ) {
\r
2784 /* Something went seriously wrong in the past: do not try to recreate fonts! */
\r
2788 if( appData.renderPiecesWithFont == NULL || appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {
\r
2789 fontBitmapSquareSize = -1;
\r
2793 if( fontBitmapSquareSize != squareSize ) {
\r
2794 hdc_window = GetDC( hwndMain );
\r
2795 hdc = CreateCompatibleDC( hdc_window );
\r
2797 if( hPieceFont != NULL ) {
\r
2798 DeleteObject( hPieceFont );
\r
2801 for( i=0; i<=(int)BlackKing; i++ ) {
\r
2802 hPieceMask[i] = NULL;
\r
2803 hPieceFace[i] = NULL;
\r
2809 if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {
\r
2810 fontHeight = appData.fontPieceSize;
\r
2813 fontHeight = (fontHeight * squareSize) / 100;
\r
2815 lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
\r
2817 lf.lfEscapement = 0;
\r
2818 lf.lfOrientation = 0;
\r
2819 lf.lfWeight = FW_NORMAL;
\r
2821 lf.lfUnderline = 0;
\r
2822 lf.lfStrikeOut = 0;
\r
2823 lf.lfCharSet = DEFAULT_CHARSET;
\r
2824 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
2825 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
2826 lf.lfQuality = PROOF_QUALITY;
\r
2827 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
\r
2828 strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );
\r
2829 lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';
\r
2831 hPieceFont = CreateFontIndirect( &lf );
\r
2833 if( hPieceFont == NULL ) {
\r
2834 fontBitmapSquareSize = -2;
\r
2837 /* Setup font-to-piece character table */
\r
2838 if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {
\r
2839 /* No (or wrong) global settings, try to detect the font */
\r
2840 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {
\r
2842 SetCharTable(pieceToFontChar, "phbrqkojntwl");
\r
2844 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {
\r
2845 /* DiagramTT* family */
\r
2846 SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");
\r
2848 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {
\r
2849 /* Fairy symbols */
\r
2850 SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
\r
2852 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {
\r
2853 /* Good Companion (Some characters get warped as literal :-( */
\r
2854 char s[] = "1cmWG0ñueOS¯®oYI23wgQU";
\r
2855 s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;
\r
2856 SetCharTable(pieceToFontChar, s);
\r
2859 /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */
\r
2860 SetCharTable(pieceToFontChar, "pnbrqkomvtwl");
\r
2864 /* Create bitmaps */
\r
2865 hfont_old = SelectObject( hdc, hPieceFont );
\r
2867 CreatePieceMaskFromFont( hdc_window, hdc, PM_WP );
\r
2868 CreatePieceMaskFromFont( hdc_window, hdc, PM_WN );
\r
2869 CreatePieceMaskFromFont( hdc_window, hdc, PM_WB );
\r
2870 CreatePieceMaskFromFont( hdc_window, hdc, PM_WR );
\r
2871 CreatePieceMaskFromFont( hdc_window, hdc, PM_WQ );
\r
2872 CreatePieceMaskFromFont( hdc_window, hdc, PM_WK );
\r
2873 CreatePieceMaskFromFont( hdc_window, hdc, PM_BP );
\r
2874 CreatePieceMaskFromFont( hdc_window, hdc, PM_BN );
\r
2875 CreatePieceMaskFromFont( hdc_window, hdc, PM_BB );
\r
2876 CreatePieceMaskFromFont( hdc_window, hdc, PM_BR );
\r
2877 CreatePieceMaskFromFont( hdc_window, hdc, PM_BQ );
\r
2878 CreatePieceMaskFromFont( hdc_window, hdc, PM_BK );
\r
2880 CreatePieceMaskFromFont( hdc_window, hdc, PM_WA );
\r
2881 CreatePieceMaskFromFont( hdc_window, hdc, PM_WC );
\r
2882 CreatePieceMaskFromFont( hdc_window, hdc, PM_WF );
\r
2883 CreatePieceMaskFromFont( hdc_window, hdc, PM_WH );
\r
2884 CreatePieceMaskFromFont( hdc_window, hdc, PM_WE );
\r
2885 CreatePieceMaskFromFont( hdc_window, hdc, PM_WW );
\r
2886 CreatePieceMaskFromFont( hdc_window, hdc, PM_WU );
\r
2887 CreatePieceMaskFromFont( hdc_window, hdc, PM_WO );
\r
2888 CreatePieceMaskFromFont( hdc_window, hdc, PM_WG );
\r
2889 CreatePieceMaskFromFont( hdc_window, hdc, PM_WM );
\r
2890 CreatePieceMaskFromFont( hdc_window, hdc, PM_WSG );
\r
2891 CreatePieceMaskFromFont( hdc_window, hdc, PM_WV );
\r
2892 CreatePieceMaskFromFont( hdc_window, hdc, PM_WAB );
\r
2893 CreatePieceMaskFromFont( hdc_window, hdc, PM_WD );
\r
2894 CreatePieceMaskFromFont( hdc_window, hdc, PM_WL );
\r
2895 CreatePieceMaskFromFont( hdc_window, hdc, PM_WS );
\r
2896 CreatePieceMaskFromFont( hdc_window, hdc, PM_BA );
\r
2897 CreatePieceMaskFromFont( hdc_window, hdc, PM_BC );
\r
2898 CreatePieceMaskFromFont( hdc_window, hdc, PM_BF );
\r
2899 CreatePieceMaskFromFont( hdc_window, hdc, PM_BH );
\r
2900 CreatePieceMaskFromFont( hdc_window, hdc, PM_BE );
\r
2901 CreatePieceMaskFromFont( hdc_window, hdc, PM_BW );
\r
2902 CreatePieceMaskFromFont( hdc_window, hdc, PM_BU );
\r
2903 CreatePieceMaskFromFont( hdc_window, hdc, PM_BO );
\r
2904 CreatePieceMaskFromFont( hdc_window, hdc, PM_BG );
\r
2905 CreatePieceMaskFromFont( hdc_window, hdc, PM_BM );
\r
2906 CreatePieceMaskFromFont( hdc_window, hdc, PM_BSG );
\r
2907 CreatePieceMaskFromFont( hdc_window, hdc, PM_BV );
\r
2908 CreatePieceMaskFromFont( hdc_window, hdc, PM_BAB );
\r
2909 CreatePieceMaskFromFont( hdc_window, hdc, PM_BD );
\r
2910 CreatePieceMaskFromFont( hdc_window, hdc, PM_BL );
\r
2911 CreatePieceMaskFromFont( hdc_window, hdc, PM_BS );
\r
2913 for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */
\r
2914 if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */
\r
2915 CreatePieceMaskFromFont( hdc_window, hdc, i );
\r
2917 SelectObject( hdc, hfont_old );
\r
2919 fontBitmapSquareSize = squareSize;
\r
2923 if( hdc != NULL ) {
\r
2927 if( hdc_window != NULL ) {
\r
2928 ReleaseDC( hwndMain, hdc_window );
\r
2933 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)
\r
2937 sprintf(name, "%s%d%s", piece, squareSize, suffix);
\r
2938 if (gameInfo.event &&
\r
2939 strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&
\r
2940 strcmp(name, "k80s") == 0) {
\r
2941 strcpy(name, "tim");
\r
2943 return LoadBitmap(hinst, name);
\r
2947 /* Insert a color into the program's logical palette
\r
2948 structure. This code assumes the given color is
\r
2949 the result of the RGB or PALETTERGB macro, and it
\r
2950 knows how those macros work (which is documented).
\r
2953 InsertInPalette(COLORREF color)
\r
2955 LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);
\r
2957 if (pLogPal->palNumEntries++ >= PALETTESIZE) {
\r
2958 DisplayFatalError("Too many colors", 0, 1);
\r
2959 pLogPal->palNumEntries--;
\r
2963 pe->peFlags = (char) 0;
\r
2964 pe->peRed = (char) (0xFF & color);
\r
2965 pe->peGreen = (char) (0xFF & (color >> 8));
\r
2966 pe->peBlue = (char) (0xFF & (color >> 16));
\r
2972 InitDrawingColors()
\r
2974 if (pLogPal == NULL) {
\r
2975 /* Allocate enough memory for a logical palette with
\r
2976 * PALETTESIZE entries and set the size and version fields
\r
2977 * of the logical palette structure.
\r
2979 pLogPal = (NPLOGPALETTE)
\r
2980 LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +
\r
2981 (sizeof(PALETTEENTRY) * (PALETTESIZE))));
\r
2982 pLogPal->palVersion = 0x300;
\r
2984 pLogPal->palNumEntries = 0;
\r
2986 InsertInPalette(lightSquareColor);
\r
2987 InsertInPalette(darkSquareColor);
\r
2988 InsertInPalette(whitePieceColor);
\r
2989 InsertInPalette(blackPieceColor);
\r
2990 InsertInPalette(highlightSquareColor);
\r
2991 InsertInPalette(premoveHighlightColor);
\r
2993 /* create a logical color palette according the information
\r
2994 * in the LOGPALETTE structure.
\r
2996 hPal = CreatePalette((LPLOGPALETTE) pLogPal);
\r
2998 lightSquareBrush = CreateSolidBrush(lightSquareColor);
\r
2999 blackSquareBrush = CreateSolidBrush(blackPieceColor);
\r
3000 darkSquareBrush = CreateSolidBrush(darkSquareColor);
\r
3001 whitePieceBrush = CreateSolidBrush(whitePieceColor);
\r
3002 blackPieceBrush = CreateSolidBrush(blackPieceColor);
\r
3003 iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
\r
3005 /* [AS] Force rendering of the font-based pieces */
\r
3006 if( fontBitmapSquareSize > 0 ) {
\r
3007 fontBitmapSquareSize = 0;
\r
3013 BoardWidth(int boardSize, int n)
\r
3014 { /* [HGM] argument n added to allow different width and height */
\r
3015 int lineGap = sizeInfo[boardSize].lineGap;
\r
3017 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3018 lineGap = appData.overrideLineGap;
\r
3021 return (n + 1) * lineGap +
\r
3022 n * sizeInfo[boardSize].squareSize;
\r
3025 /* Respond to board resize by dragging edge */
\r
3027 ResizeBoard(int newSizeX, int newSizeY, int flags)
\r
3029 BoardSize newSize = NUM_SIZES - 1;
\r
3030 static int recurse = 0;
\r
3031 if (IsIconic(hwndMain)) return;
\r
3032 if (recurse > 0) return;
\r
3034 while (newSize > 0) {
\r
3035 InitDrawingSizes(newSize+1000, 0); // [HGM] kludge to update sizeInfo without visible effects
\r
3036 if(newSizeX >= sizeInfo[newSize].cliWidth &&
\r
3037 newSizeY >= sizeInfo[newSize].cliHeight) break;
\r
3040 boardSize = newSize;
\r
3041 InitDrawingSizes(boardSize, flags);
\r
3048 InitDrawingSizes(BoardSize boardSize, int flags)
\r
3050 int i, boardWidth, boardHeight; /* [HGM] height treated separately */
\r
3051 ChessSquare piece;
\r
3052 static int oldBoardSize = -1, oldTinyLayout = 0;
\r
3054 SIZE clockSize, messageSize;
\r
3056 char buf[MSG_SIZ];
\r
3058 HMENU hmenu = GetMenu(hwndMain);
\r
3059 RECT crect, wrect;
\r
3061 LOGBRUSH logbrush;
\r
3063 int suppressVisibleEffects = 0; // [HGM] kludge to request updating sizeInfo only
\r
3064 if((int)boardSize >= 1000 ) { boardSize -= 1000; suppressVisibleEffects = 1; }
\r
3066 /* [HGM] call with -2 uses old size (for if nr of files, ranks changes) */
\r
3067 if(boardSize == (BoardSize)(-2) ) boardSize = oldBoardSize;
\r
3069 tinyLayout = sizeInfo[boardSize].tinyLayout;
\r
3070 smallLayout = sizeInfo[boardSize].smallLayout;
\r
3071 squareSize = sizeInfo[boardSize].squareSize;
\r
3072 lineGap = sizeInfo[boardSize].lineGap;
\r
3073 minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted */
\r
3075 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3076 lineGap = appData.overrideLineGap;
\r
3079 if (tinyLayout != oldTinyLayout) {
\r
3080 long style = GetWindowLong(hwndMain, GWL_STYLE);
\r
3082 style &= ~WS_SYSMENU;
\r
3083 InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize,
\r
3084 "&Minimize\tCtrl+F4");
\r
3086 style |= WS_SYSMENU;
\r
3087 RemoveMenu(hmenu, IDM_Minimize, MF_BYCOMMAND);
\r
3089 SetWindowLong(hwndMain, GWL_STYLE, style);
\r
3091 for (i=0; menuBarText[tinyLayout][i]; i++) {
\r
3092 ModifyMenu(hmenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP,
\r
3093 (UINT)GetSubMenu(hmenu, i), menuBarText[tinyLayout][i]);
\r
3095 DrawMenuBar(hwndMain);
\r
3098 boardWidth = BoardWidth(boardSize, BOARD_WIDTH);
\r
3099 boardHeight = BoardWidth(boardSize, BOARD_HEIGHT);
\r
3101 /* Get text area sizes */
\r
3102 hdc = GetDC(hwndMain);
\r
3103 if (appData.clockMode) {
\r
3104 sprintf(buf, "White: %s", TimeString(23*60*60*1000L));
\r
3106 sprintf(buf, "White");
\r
3108 oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);
\r
3109 GetTextExtentPoint(hdc, buf, strlen(buf), &clockSize);
\r
3110 SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);
\r
3111 str = "We only care about the height here";
\r
3112 GetTextExtentPoint(hdc, str, strlen(str), &messageSize);
\r
3113 SelectObject(hdc, oldFont);
\r
3114 ReleaseDC(hwndMain, hdc);
\r
3116 /* Compute where everything goes */
\r
3117 if(first.programLogo || second.programLogo) {
\r
3118 /* [HGM] logo: if either logo is on, reserve space for it */
\r
3119 logoHeight = 2*clockSize.cy;
\r
3120 leftLogoRect.left = OUTER_MARGIN;
\r
3121 leftLogoRect.right = leftLogoRect.left + 4*clockSize.cy;
\r
3122 leftLogoRect.top = OUTER_MARGIN;
\r
3123 leftLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3125 rightLogoRect.right = OUTER_MARGIN + boardWidth;
\r
3126 rightLogoRect.left = rightLogoRect.right - 4*clockSize.cy;
\r
3127 rightLogoRect.top = OUTER_MARGIN;
\r
3128 rightLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3131 blackRect.left = leftLogoRect.right;
\r
3132 blackRect.right = rightLogoRect.left;
\r
3133 blackRect.top = OUTER_MARGIN;
\r
3134 blackRect.bottom = blackRect.top + clockSize.cy;
\r
3136 whiteRect.left = blackRect.left ;
\r
3137 whiteRect.right = blackRect.right;
\r
3138 whiteRect.top = blackRect.bottom;
\r
3139 whiteRect.bottom = leftLogoRect.bottom;
\r
3141 whiteRect.left = OUTER_MARGIN;
\r
3142 whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2;
\r
3143 whiteRect.top = OUTER_MARGIN + logoHeight;
\r
3144 whiteRect.bottom = whiteRect.top + clockSize.cy;
\r
3146 blackRect.left = whiteRect.right + INNER_MARGIN;
\r
3147 blackRect.right = blackRect.left + boardWidth/2 - 1;
\r
3148 blackRect.top = whiteRect.top;
\r
3149 blackRect.bottom = whiteRect.bottom;
\r
3152 messageRect.left = OUTER_MARGIN + MESSAGE_LINE_LEFTMARGIN;
\r
3153 if (appData.showButtonBar) {
\r
3154 messageRect.right = OUTER_MARGIN + boardWidth // [HGM] logo: expressed independent of clock placement
\r
3155 - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN;
\r
3157 messageRect.right = OUTER_MARGIN + boardWidth;
\r
3159 messageRect.top = whiteRect.bottom + INNER_MARGIN;
\r
3160 messageRect.bottom = messageRect.top + messageSize.cy;
\r
3162 boardRect.left = OUTER_MARGIN;
\r
3163 boardRect.right = boardRect.left + boardWidth;
\r
3164 boardRect.top = messageRect.bottom + INNER_MARGIN;
\r
3165 boardRect.bottom = boardRect.top + boardHeight;
\r
3167 sizeInfo[boardSize].cliWidth = boardRect.right + OUTER_MARGIN;
\r
3168 sizeInfo[boardSize].cliHeight = boardRect.bottom + OUTER_MARGIN;
\r
3169 if(suppressVisibleEffects) return; // [HGM] when called for filling sizeInfo only
\r
3170 winWidth = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN;
\r
3171 winHeight = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) +
\r
3172 GetSystemMetrics(SM_CYCAPTION) + boardRect.bottom + OUTER_MARGIN;
\r
3173 GetWindowRect(hwndMain, &wrect);
\r
3174 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3175 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3176 /* compensate if menu bar wrapped */
\r
3177 GetClientRect(hwndMain, &crect);
\r
3178 offby = boardRect.bottom + OUTER_MARGIN - crect.bottom;
\r
3179 winHeight += offby;
\r
3181 case WMSZ_TOPLEFT:
\r
3182 SetWindowPos(hwndMain, NULL,
\r
3183 wrect.right - winWidth, wrect.bottom - winHeight,
\r
3184 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3187 case WMSZ_TOPRIGHT:
\r
3189 SetWindowPos(hwndMain, NULL,
\r
3190 wrect.left, wrect.bottom - winHeight,
\r
3191 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3194 case WMSZ_BOTTOMLEFT:
\r
3196 SetWindowPos(hwndMain, NULL,
\r
3197 wrect.right - winWidth, wrect.top,
\r
3198 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3201 case WMSZ_BOTTOMRIGHT:
\r
3205 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3206 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);