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
65 #include <sys/stat.h>
\r
68 #include <commdlg.h>
\r
70 #include <richedit.h>
\r
71 #include <mmsystem.h>
\r
79 #include "winboard.h"
\r
80 #include "frontend.h"
\r
81 #include "backend.h"
\r
83 #include "wclipbrd.h"
\r
84 #include "wgamelist.h"
\r
85 #include "wedittags.h"
\r
86 #include "woptions.h"
\r
87 #include "wsockerr.h"
\r
88 #include "defaults.h"
\r
92 //void InitEngineUCI( const char * iniDir, ChessProgramState * cps );
\r
95 void mysrandom(unsigned int seed);
\r
97 extern int whiteFlag, blackFlag;
\r
98 Boolean flipClock = FALSE;
\r
100 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);
\r
103 ChessSquare piece;
\r
104 POINT pos; /* window coordinates of current pos */
\r
105 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
106 POINT from; /* board coordinates of the piece's orig pos */
\r
107 POINT to; /* board coordinates of the piece's new pos */
\r
110 static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };
\r
113 POINT start; /* window coordinates of start pos */
\r
114 POINT pos; /* window coordinates of current pos */
\r
115 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
116 POINT from; /* board coordinates of the piece's orig pos */
\r
119 static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} };
\r
122 POINT sq[2]; /* board coordinates of from, to squares */
\r
125 static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} };
\r
126 static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };
\r
128 /* Window class names */
\r
129 char szAppName[] = "WinBoard";
\r
130 char szConsoleName[] = "WBConsole";
\r
132 /* Title bar text */
\r
133 char szTitle[] = "WinBoard";
\r
134 char szConsoleTitle[] = "ICS Interaction";
\r
137 char *settingsFileName;
\r
138 BOOLEAN saveSettingsOnExit;
\r
139 char installDir[MSG_SIZ];
\r
141 BoardSize boardSize;
\r
142 BOOLEAN chessProgram;
\r
143 static int boardX, boardY, consoleX, consoleY, consoleW, consoleH;
\r
144 static int squareSize, lineGap, minorSize;
\r
145 static int winWidth, winHeight;
\r
146 static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo
\r
147 static int logoHeight = 0;
\r
148 static char messageText[MESSAGE_TEXT_MAX];
\r
149 static int clockTimerEvent = 0;
\r
150 static int loadGameTimerEvent = 0;
\r
151 static int analysisTimerEvent = 0;
\r
152 static DelayedEventCallback delayedTimerCallback;
\r
153 static int delayedTimerEvent = 0;
\r
154 static int buttonCount = 2;
\r
155 char *icsTextMenuString;
\r
157 char *firstChessProgramNames;
\r
158 char *secondChessProgramNames;
\r
160 #define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */
\r
162 #define PALETTESIZE 256
\r
164 HINSTANCE hInst; /* current instance */
\r
165 HWND hwndMain = NULL; /* root window*/
\r
166 HWND hwndConsole = NULL;
\r
167 BOOLEAN alwaysOnTop = FALSE;
\r
169 COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
\r
170 blackPieceColor, highlightSquareColor, premoveHighlightColor;
\r
172 ColorClass currentColorClass;
\r
174 HWND hCommPort = NULL; /* currently open comm port */
\r
175 static HWND hwndPause; /* pause button */
\r
176 static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */
\r
177 static HBRUSH lightSquareBrush, darkSquareBrush,
\r
178 blackSquareBrush, /* [HGM] for band between board and holdings */
\r
179 whitePieceBrush, blackPieceBrush, iconBkgndBrush, outlineBrush;
\r
180 static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];
\r
181 static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];
\r
182 static HPEN gridPen = NULL;
\r
183 static HPEN highlightPen = NULL;
\r
184 static HPEN premovePen = NULL;
\r
185 static NPLOGPALETTE pLogPal;
\r
186 static BOOL paletteChanged = FALSE;
\r
187 static HICON iconWhite, iconBlack, iconCurrent;
\r
188 static int doingSizing = FALSE;
\r
189 static int lastSizing = 0;
\r
190 static int prevStderrPort;
\r
192 /* [AS] Support for background textures */
\r
193 #define BACK_TEXTURE_MODE_DISABLED 0
\r
194 #define BACK_TEXTURE_MODE_PLAIN 1
\r
195 #define BACK_TEXTURE_MODE_FULL_RANDOM 2
\r
197 static HBITMAP liteBackTexture = NULL;
\r
198 static HBITMAP darkBackTexture = NULL;
\r
199 static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
200 static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
201 static int backTextureSquareSize = 0;
\r
202 static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_SIZE][BOARD_SIZE];
\r
204 #if __GNUC__ && !defined(_winmajor)
\r
205 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */
\r
207 #define oldDialog (_winmajor < 4)
\r
210 char *defaultTextAttribs[] =
\r
212 COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,
\r
213 COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,
\r
223 int cliWidth, cliHeight;
\r
226 SizeInfo sizeInfo[] =
\r
228 { "tiny", 21, 0, 1, 1, 0, 0 },
\r
229 { "teeny", 25, 1, 1, 1, 0, 0 },
\r
230 { "dinky", 29, 1, 1, 1, 0, 0 },
\r
231 { "petite", 33, 1, 1, 1, 0, 0 },
\r
232 { "slim", 37, 2, 1, 0, 0, 0 },
\r
233 { "small", 40, 2, 1, 0, 0, 0 },
\r
234 { "mediocre", 45, 2, 1, 0, 0, 0 },
\r
235 { "middling", 49, 2, 0, 0, 0, 0 },
\r
236 { "average", 54, 2, 0, 0, 0, 0 },
\r
237 { "moderate", 58, 3, 0, 0, 0, 0 },
\r
238 { "medium", 64, 3, 0, 0, 0, 0 },
\r
239 { "bulky", 72, 3, 0, 0, 0, 0 },
\r
240 { "large", 80, 3, 0, 0, 0, 0 },
\r
241 { "big", 87, 3, 0, 0, 0, 0 },
\r
242 { "huge", 95, 3, 0, 0, 0, 0 },
\r
243 { "giant", 108, 3, 0, 0, 0, 0 },
\r
244 { "colossal", 116, 4, 0, 0, 0, 0 },
\r
245 { "titanic", 129, 4, 0, 0, 0, 0 },
\r
246 { NULL, 0, 0, 0, 0, 0, 0 }
\r
249 #define MF(x) {x, {0, }, {0, }, 0}
\r
250 MyFont fontRec[NUM_SIZES][NUM_FONTS] =
\r
252 { 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
253 { 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
254 { 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
255 { 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
256 { 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
257 { 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
258 { 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
259 { 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
260 { 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
261 { 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
262 { 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
263 { 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
264 { 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
265 { 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
266 { 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
267 { 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
268 { 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
269 { 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
272 MyFont *font[NUM_SIZES][NUM_FONTS];
\r
281 #define BUTTON_WIDTH (tinyLayout ? 16 : 32)
\r
282 #define N_BUTTONS 5
\r
284 MyButtonDesc buttonDesc[N_BUTTONS] =
\r
286 {"<<", IDM_ToStart, NULL, NULL},
\r
287 {"<", IDM_Backward, NULL, NULL},
\r
288 {"P", IDM_Pause, NULL, NULL},
\r
289 {">", IDM_Forward, NULL, NULL},
\r
290 {">>", IDM_ToEnd, NULL, NULL},
\r
293 int tinyLayout = 0, smallLayout = 0;
\r
294 #define MENU_BAR_ITEMS 6
\r
295 char *menuBarText[2][MENU_BAR_ITEMS+1] = {
\r
296 { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },
\r
297 { "&F", "&M", "&A", "&S", "&O", "&H", NULL },
\r
301 MySound sounds[(int)NSoundClasses];
\r
302 MyTextAttribs textAttribs[(int)NColorClasses];
\r
304 MyColorizeAttribs colorizeAttribs[] = {
\r
305 { (COLORREF)0, 0, "Shout Text" },
\r
306 { (COLORREF)0, 0, "SShout/CShout" },
\r
307 { (COLORREF)0, 0, "Channel 1 Text" },
\r
308 { (COLORREF)0, 0, "Channel Text" },
\r
309 { (COLORREF)0, 0, "Kibitz Text" },
\r
310 { (COLORREF)0, 0, "Tell Text" },
\r
311 { (COLORREF)0, 0, "Challenge Text" },
\r
312 { (COLORREF)0, 0, "Request Text" },
\r
313 { (COLORREF)0, 0, "Seek Text" },
\r
314 { (COLORREF)0, 0, "Normal Text" },
\r
315 { (COLORREF)0, 0, "None" }
\r
320 static char *commentTitle;
\r
321 static char *commentText;
\r
322 static int commentIndex;
\r
323 static Boolean editComment = FALSE;
\r
324 HWND commentDialog = NULL;
\r
325 BOOLEAN commentDialogUp = FALSE;
\r
326 static int commentX, commentY, commentH, commentW;
\r
328 static char *analysisTitle;
\r
329 static char *analysisText;
\r
330 HWND analysisDialog = NULL;
\r
331 BOOLEAN analysisDialogUp = FALSE;
\r
332 static int analysisX, analysisY, analysisH, analysisW;
\r
334 char errorTitle[MSG_SIZ];
\r
335 char errorMessage[2*MSG_SIZ];
\r
336 HWND errorDialog = NULL;
\r
337 BOOLEAN moveErrorMessageUp = FALSE;
\r
338 BOOLEAN consoleEcho = TRUE;
\r
339 CHARFORMAT consoleCF;
\r
340 COLORREF consoleBackgroundColor;
\r
342 char *programVersion;
\r
348 typedef int CPKind;
\r
357 SOCKET sock2; /* stderr socket for OpenRcmd */
\r
360 #define INPUT_SOURCE_BUF_SIZE 4096
\r
362 typedef struct _InputSource {
\r
369 char buf[INPUT_SOURCE_BUF_SIZE];
\r
373 InputCallback func;
\r
374 struct _InputSource *second; /* for stderr thread on CPRcmd */
\r
378 InputSource *consoleInputSource;
\r
383 VOID ConsoleOutput(char* data, int length, int forceVisible);
\r
384 VOID ConsoleCreate();
\r
386 ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
387 VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
\r
388 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
\r
389 VOID ParseCommSettings(char *arg, DCB *dcb);
\r
391 StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
392 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
\r
393 void ParseIcsTextMenu(char *icsTextMenuString);
\r
394 VOID PopUpMoveDialog(char firstchar);
\r
395 VOID PopUpNameDialog(char firstchar);
\r
396 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
\r
400 int GameListOptions();
\r
402 HWND moveHistoryDialog = NULL;
\r
403 BOOLEAN moveHistoryDialogUp = FALSE;
\r
405 WindowPlacement wpMoveHistory;
\r
407 HWND evalGraphDialog = NULL;
\r
408 BOOLEAN evalGraphDialogUp = FALSE;
\r
410 WindowPlacement wpEvalGraph;
\r
412 HWND engineOutputDialog = NULL;
\r
413 BOOLEAN engineOutputDialogUp = FALSE;
\r
415 WindowPlacement wpEngineOutput;
\r
417 VOID MoveHistoryPopUp();
\r
418 VOID MoveHistoryPopDown();
\r
419 VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
420 BOOL MoveHistoryIsUp();
\r
422 VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
423 VOID EvalGraphPopUp();
\r
424 VOID EvalGraphPopDown();
\r
425 BOOL EvalGraphIsUp();
\r
427 VOID EngineOutputPopUp();
\r
428 VOID EngineOutputPopDown();
\r
429 BOOL EngineOutputIsUp();
\r
430 VOID EngineOutputUpdate( FrontEndProgramStats * stats );
\r
432 VOID GothicPopUp(char *title, VariantClass variant);
\r
434 * Setting "frozen" should disable all user input other than deleting
\r
435 * the window. We do this while engines are initializing themselves.
\r
437 static int frozen = 0;
\r
438 static int oldMenuItemState[MENU_BAR_ITEMS];
\r
444 if (frozen) return;
\r
446 hmenu = GetMenu(hwndMain);
\r
447 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
448 oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
\r
450 DrawMenuBar(hwndMain);
\r
453 /* Undo a FreezeUI */
\r
459 if (!frozen) return;
\r
461 hmenu = GetMenu(hwndMain);
\r
462 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
463 EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
\r
465 DrawMenuBar(hwndMain);
\r
468 /*---------------------------------------------------------------------------*\
\r
472 \*---------------------------------------------------------------------------*/
\r
475 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
\r
476 LPSTR lpCmdLine, int nCmdShow)
\r
479 HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
\r
483 LoadLibrary("RICHED32.DLL");
\r
484 consoleCF.cbSize = sizeof(CHARFORMAT);
\r
486 if (!InitApplication(hInstance)) {
\r
489 if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
\r
493 hAccelMain = LoadAccelerators (hInstance, szAppName);
\r
494 hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
\r
495 hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
\r
497 /* Acquire and dispatch messages until a WM_QUIT message is received. */
\r
499 while (GetMessage(&msg, /* message structure */
\r
500 NULL, /* handle of window receiving the message */
\r
501 0, /* lowest message to examine */
\r
502 0)) /* highest message to examine */
\r
504 if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
\r
505 !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
\r
506 !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
\r
507 !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
\r
508 !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
\r
509 !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
\r
510 !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
\r
511 !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) &&
\r
512 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
\r
513 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
\r
514 TranslateMessage(&msg); /* Translates virtual key codes */
\r
515 DispatchMessage(&msg); /* Dispatches message to window */
\r
520 return (msg.wParam); /* Returns the value from PostQuitMessage */
\r
523 /*---------------------------------------------------------------------------*\
\r
525 * Initialization functions
\r
527 \*---------------------------------------------------------------------------*/
\r
530 InitApplication(HINSTANCE hInstance)
\r
534 /* Fill in window class structure with parameters that describe the */
\r
537 wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
\r
538 wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
\r
539 wc.cbClsExtra = 0; /* No per-class extra data. */
\r
540 wc.cbWndExtra = 0; /* No per-window extra data. */
\r
541 wc.hInstance = hInstance; /* Owner of this class */
\r
542 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
543 wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
\r
544 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
\r
545 wc.lpszMenuName = szAppName; /* Menu name from .RC */
\r
546 wc.lpszClassName = szAppName; /* Name to register as */
\r
548 /* Register the window class and return success/failure code. */
\r
549 if (!RegisterClass(&wc)) return FALSE;
\r
551 wc.style = CS_HREDRAW | CS_VREDRAW;
\r
552 wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
\r
554 wc.cbWndExtra = DLGWINDOWEXTRA;
\r
555 wc.hInstance = hInstance;
\r
556 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
557 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
\r
558 wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
\r
559 wc.lpszMenuName = NULL;
\r
560 wc.lpszClassName = szConsoleName;
\r
562 if (!RegisterClass(&wc)) return FALSE;
\r
567 /* Set by InitInstance, used by EnsureOnScreen */
\r
568 int screenHeight, screenWidth;
\r
571 EnsureOnScreen(int *x, int *y)
\r
573 // int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
\r
574 /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
\r
575 if (*x > screenWidth - 32) *x = 0;
\r
576 if (*y > screenHeight - 32) *y = 0;
\r
577 if (*x < 0) *x = 0;
\r
578 if (*y < 0) *y = 0;
\r
579 // if (*x < 10) *x = 10;
\r
580 // if (*y < gap) *y = gap;
\r
584 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
\r
586 HWND hwnd; /* Main window handle. */
\r
588 WINDOWPLACEMENT wp;
\r
591 hInst = hInstance; /* Store instance handle in our global variable */
\r
593 if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
\r
594 *filepart = NULLCHAR;
\r
596 GetCurrentDirectory(MSG_SIZ, installDir);
\r
598 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise
\r
599 InitAppData(lpCmdLine); /* Get run-time parameters */
\r
600 if (appData.debugMode) {
\r
601 debugFP = fopen(appData.nameOfDebugFile, "w");
\r
602 setbuf(debugFP, NULL);
\r
607 // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()
\r
608 // InitEngineUCI( installDir, &second );
\r
610 /* Create a main window for this application instance. */
\r
611 hwnd = CreateWindow(szAppName, szTitle,
\r
612 (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
\r
613 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
\r
614 NULL, NULL, hInstance, NULL);
\r
617 /* If window could not be created, return "failure" */
\r
622 /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */
\r
623 if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {
\r
624 first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
626 if (first.programLogo == NULL && appData.debugMode) {
\r
627 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );
\r
629 } else if(appData.autoLogo) {
\r
630 if(appData.firstDirectory && appData.firstDirectory[0]) {
\r
632 sprintf(buf, "%s/logo.bmp", appData.firstDirectory);
\r
633 first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
637 if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {
\r
638 second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
640 if (second.programLogo == NULL && appData.debugMode) {
\r
641 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );
\r
643 } else if(appData.autoLogo) {
\r
644 if(appData.secondDirectory && appData.secondDirectory[0]) {
\r
646 sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);
\r
647 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
651 iconWhite = LoadIcon(hInstance, "icon_white");
\r
652 iconBlack = LoadIcon(hInstance, "icon_black");
\r
653 iconCurrent = iconWhite;
\r
654 InitDrawingColors();
\r
655 screenHeight = GetSystemMetrics(SM_CYSCREEN);
\r
656 screenWidth = GetSystemMetrics(SM_CXSCREEN);
\r
657 for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
\r
658 /* Compute window size for each board size, and use the largest
\r
659 size that fits on this screen as the default. */
\r
660 InitDrawingSizes((BoardSize)ibs, 0);
\r
661 if (boardSize == (BoardSize)-1 &&
\r
662 winHeight <= screenHeight
\r
663 - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10
\r
664 && winWidth <= screenWidth) {
\r
665 boardSize = (BoardSize)ibs;
\r
669 InitDrawingSizes(boardSize, 0);
\r
671 buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
\r
673 /* [AS] Load textures if specified */
\r
674 ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );
\r
676 if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {
\r
677 liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
678 liteBackTextureMode = appData.liteBackTextureMode;
\r
680 if (liteBackTexture == NULL && appData.debugMode) {
\r
681 fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );
\r
685 if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {
\r
686 darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
687 darkBackTextureMode = appData.darkBackTextureMode;
\r
689 if (darkBackTexture == NULL && appData.debugMode) {
\r
690 fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );
\r
694 mysrandom( (unsigned) time(NULL) );
\r
696 /* [AS] Restore layout */
\r
697 if( wpMoveHistory.visible ) {
\r
698 MoveHistoryPopUp();
\r
701 if( wpEvalGraph.visible ) {
\r
705 if( wpEngineOutput.visible ) {
\r
706 EngineOutputPopUp();
\r
711 /* Make the window visible; update its client area; and return "success" */
\r
712 EnsureOnScreen(&boardX, &boardY);
\r
713 wp.length = sizeof(WINDOWPLACEMENT);
\r
715 wp.showCmd = nCmdShow;
\r
716 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
\r
717 wp.rcNormalPosition.left = boardX;
\r
718 wp.rcNormalPosition.right = boardX + winWidth;
\r
719 wp.rcNormalPosition.top = boardY;
\r
720 wp.rcNormalPosition.bottom = boardY + winHeight;
\r
721 SetWindowPlacement(hwndMain, &wp);
\r
723 SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
724 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
727 /* [AS] Disable the FRC stuff if not playing the proper variant */
\r
728 if( gameInfo.variant != VariantFischeRandom ) {
\r
729 EnableMenuItem( GetMenu(hwndMain), IDM_NewGameFRC, MF_GRAYED );
\r
734 SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
735 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
737 ShowWindow(hwndConsole, nCmdShow);
\r
739 UpdateWindow(hwnd);
\r
747 ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
\r
748 ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
\r
749 ArgSettingsFilename
\r
757 String *pString; // ArgString
\r
758 int *pInt; // ArgInt
\r
759 float *pFloat; // ArgFloat
\r
760 Boolean *pBoolean; // ArgBoolean
\r
761 COLORREF *pColor; // ArgColor
\r
762 ColorClass cc; // ArgAttribs
\r
763 String *pFilename; // ArgFilename
\r
764 BoardSize *pBoardSize; // ArgBoardSize
\r
765 int whichFont; // ArgFont
\r
766 DCB *pDCB; // ArgCommSettings
\r
767 String *pFilename; // ArgSettingsFilename
\r
775 ArgDescriptor argDescriptors[] = {
\r
776 /* positional arguments */
\r
777 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
778 { "", ArgNone, NULL },
\r
779 /* keyword arguments */
\r
780 { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },
\r
781 { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },
\r
782 { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },
\r
783 { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },
\r
784 { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },
\r
785 { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },
\r
786 { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },
\r
787 { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },
\r
788 { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },
\r
789 { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },
\r
790 { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },
\r
791 { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },
\r
792 { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },
\r
793 { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },
\r
794 { "initString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
795 { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
796 { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },
\r
797 { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,
\r
799 { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,
\r
801 { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,
\r
803 { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },
\r
804 { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,
\r
806 { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },
\r
807 { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
808 { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
809 { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
810 { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
811 { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },
\r
812 { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },
\r
813 { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
814 { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
815 { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
816 { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
817 { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
818 { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
819 { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
820 { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
821 { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
822 { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
823 /*!!bitmapDirectory?*/
\r
824 { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
825 { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
826 { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
827 { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
828 { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },
\r
829 { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },
\r
830 { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },
\r
831 { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },
\r
832 { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },
\r
833 { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },
\r
834 { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },
\r
835 { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },
\r
836 { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
837 { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
838 { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
839 { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
840 { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
841 { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
842 { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
843 { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
844 { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
845 { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
846 { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
847 { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
848 { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },
\r
849 { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },
\r
850 { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
851 { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
852 { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },
\r
853 { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },
\r
854 { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },
\r
855 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
856 { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
857 { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
858 { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
859 { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },
\r
860 { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },
\r
861 { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },
\r
862 { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },
\r
863 { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
864 { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
865 { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
866 { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
867 { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
868 { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
869 { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
870 { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
871 { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },
\r
872 { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },
\r
873 { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
874 { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
875 { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
876 { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
877 { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },
\r
878 { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },
\r
879 { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
880 { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
881 { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },
\r
882 { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },
\r
883 { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
884 { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
885 { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },
\r
886 { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },
\r
887 { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
888 { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
889 { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
890 { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
891 { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
892 { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
893 { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },
\r
894 { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },
\r
895 { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
896 { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
897 { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },
\r
898 { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },
\r
899 { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
900 { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
901 { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },
\r
902 { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },
\r
903 { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
904 { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
905 { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },
\r
906 { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },
\r
907 { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
908 { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
909 { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },
\r
910 { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },
\r
911 { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
912 { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
913 { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },
\r
914 { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
915 { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
916 { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
917 { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors,
\r
918 FALSE }, /* only so that old WinBoard.ini files from betas can be read */
\r
919 { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },
\r
920 { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },
\r
921 { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },
\r
922 { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },
\r
923 { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },
\r
924 { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },
\r
925 { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE }, /* [AS] */
\r
926 { "boardSize", ArgBoardSize, (LPVOID) &boardSize,
\r
927 TRUE }, /* must come after all fonts */
\r
928 { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },
\r
929 { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,
\r
930 FALSE }, /* historical; kept only so old winboard.ini files will parse */
\r
931 { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },
\r
932 { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },
\r
933 { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
934 { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
935 { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },
\r
936 { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },
\r
937 { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
938 { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
939 { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },
\r
940 { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },
\r
941 { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
942 { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
943 { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },
\r
944 { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },
\r
945 { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
946 { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
947 { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },
\r
948 { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },
\r
949 { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
950 { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
951 { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },
\r
952 { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },
\r
953 { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
954 { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
955 { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },
\r
956 { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
957 { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
958 { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
960 { "cmailGameName", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
961 { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
963 { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },
\r
964 { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
965 { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
966 { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
967 { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },
\r
968 { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
969 { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
970 { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
971 { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },
\r
972 { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },
\r
973 { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
974 { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
975 { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },
\r
976 { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },
\r
977 { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
978 { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
979 { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },
\r
980 { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },
\r
981 { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
982 { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
983 { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },
\r
984 { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },
\r
985 { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
986 { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
987 { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },
\r
988 { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },
\r
989 { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
990 { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
991 { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },
\r
992 { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },
\r
993 { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },
\r
994 { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
995 { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
996 { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },
\r
997 { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},
\r
998 { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},
\r
999 { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1000 { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1001 { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},
\r
1002 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1003 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1004 { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },
\r
1005 { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1006 { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1007 { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },
\r
1008 { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },
\r
1009 { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1010 { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1011 { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },
\r
1012 { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },
\r
1013 { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },
\r
1014 { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1015 { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1016 { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },
\r
1017 { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },
\r
1018 { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1019 { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1020 { "highlightLastMove", ArgBoolean,
\r
1021 (LPVOID) &appData.highlightLastMove, TRUE },
\r
1022 { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1023 { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1024 { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1025 { "highlightDragging", ArgBoolean,
\r
1026 (LPVOID) &appData.highlightDragging, TRUE },
\r
1027 { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },
\r
1028 { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1029 { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1030 { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },
\r
1031 { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },
\r
1032 { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1033 { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1034 { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },
\r
1035 { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },
\r
1036 { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },
\r
1037 { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },
\r
1038 { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },
\r
1039 { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },
\r
1040 { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },
\r
1041 { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },
\r
1042 { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },
\r
1043 { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },
\r
1044 { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },
\r
1045 { "soundShout", ArgFilename,
\r
1046 (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },
\r
1047 { "soundSShout", ArgFilename,
\r
1048 (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },
\r
1049 { "soundChannel1", ArgFilename,
\r
1050 (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },
\r
1051 { "soundChannel", ArgFilename,
\r
1052 (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },
\r
1053 { "soundKibitz", ArgFilename,
\r
1054 (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },
\r
1055 { "soundTell", ArgFilename,
\r
1056 (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },
\r
1057 { "soundChallenge", ArgFilename,
\r
1058 (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },
\r
1059 { "soundRequest", ArgFilename,
\r
1060 (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },
\r
1061 { "soundSeek", ArgFilename,
\r
1062 (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },
\r
1063 { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },
\r
1064 { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },
\r
1065 { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },
\r
1066 { "soundIcsLoss", ArgFilename,
\r
1067 (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },
\r
1068 { "soundIcsDraw", ArgFilename,
\r
1069 (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },
\r
1070 { "soundIcsUnfinished", ArgFilename,
\r
1071 (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},
\r
1072 { "soundIcsAlarm", ArgFilename,
\r
1073 (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },
\r
1074 { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },
\r
1075 { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },
\r
1076 { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1077 { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1078 { "reuseChessPrograms", ArgBoolean,
\r
1079 (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */
\r
1080 { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },
\r
1081 { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },
\r
1082 { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1083 { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1084 { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },
\r
1085 { "x", ArgInt, (LPVOID) &boardX, TRUE },
\r
1086 { "y", ArgInt, (LPVOID) &boardY, TRUE },
\r
1087 { "icsX", ArgInt, (LPVOID) &consoleX, TRUE },
\r
1088 { "icsY", ArgInt, (LPVOID) &consoleY, TRUE },
\r
1089 { "icsW", ArgInt, (LPVOID) &consoleW, TRUE },
\r
1090 { "icsH", ArgInt, (LPVOID) &consoleH, TRUE },
\r
1091 { "analysisX", ArgInt, (LPVOID) &analysisX, TRUE },
\r
1092 { "analysisY", ArgInt, (LPVOID) &analysisY, TRUE },
\r
1093 { "analysisW", ArgInt, (LPVOID) &analysisW, TRUE },
\r
1094 { "analysisH", ArgInt, (LPVOID) &analysisH, TRUE },
\r
1095 { "commentX", ArgInt, (LPVOID) &commentX, TRUE },
\r
1096 { "commentY", ArgInt, (LPVOID) &commentY, TRUE },
\r
1097 { "commentW", ArgInt, (LPVOID) &commentW, TRUE },
\r
1098 { "commentH", ArgInt, (LPVOID) &commentH, TRUE },
\r
1099 { "tagsX", ArgInt, (LPVOID) &editTagsX, TRUE },
\r
1100 { "tagsY", ArgInt, (LPVOID) &editTagsY, TRUE },
\r
1101 { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },
\r
1102 { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },
\r
1103 { "gameListX", ArgInt, (LPVOID) &gameListX, TRUE },
\r
1104 { "gameListY", ArgInt, (LPVOID) &gameListY, TRUE },
\r
1105 { "gameListW", ArgInt, (LPVOID) &gameListW, TRUE },
\r
1106 { "gameListH", ArgInt, (LPVOID) &gameListH, TRUE },
\r
1107 { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1108 { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1109 { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },
\r
1110 { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },
\r
1111 { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },
\r
1112 { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1113 { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1114 { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },
\r
1115 { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },
\r
1116 { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,
\r
1118 { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,
\r
1120 { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1121 { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1122 { "variant", ArgString, (LPVOID) &appData.variant, FALSE },
\r
1123 { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion, FALSE },
\r
1124 { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,FALSE },
\r
1125 { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },
\r
1126 { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },
\r
1127 { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1128 { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1129 /* [AS] New features */
\r
1130 { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE },
\r
1131 { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE },
\r
1132 { "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE },
\r
1133 { "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE },
\r
1134 { "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE },
\r
1135 { "darkBackTextureFile", ArgString, (LPVOID) &appData.darkBackTextureFile, TRUE },
\r
1136 { "liteBackTextureMode", ArgInt, (LPVOID) &appData.liteBackTextureMode, TRUE },
\r
1137 { "darkBackTextureMode", ArgInt, (LPVOID) &appData.darkBackTextureMode, TRUE },
\r
1138 { "renderPiecesWithFont", ArgString, (LPVOID) &appData.renderPiecesWithFont, TRUE },
\r
1139 { "fontPieceToCharTable", ArgString, (LPVOID) &appData.fontToPieceTable, TRUE },
\r
1140 { "fontPieceBackColorWhite", ArgColor, (LPVOID) &appData.fontBackColorWhite, TRUE },
\r
1141 { "fontPieceForeColorWhite", ArgColor, (LPVOID) &appData.fontForeColorWhite, TRUE },
\r
1142 { "fontPieceBackColorBlack", ArgColor, (LPVOID) &appData.fontBackColorBlack, TRUE },
\r
1143 { "fontPieceForeColorBlack", ArgColor, (LPVOID) &appData.fontForeColorBlack, TRUE },
\r
1144 { "fontPieceSize", ArgInt, (LPVOID) &appData.fontPieceSize, TRUE },
\r
1145 { "overrideLineGap", ArgInt, (LPVOID) &appData.overrideLineGap, TRUE },
\r
1146 { "adjudicateLossThreshold", ArgInt, (LPVOID) &appData.adjudicateLossThreshold, TRUE },
\r
1147 { "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE },
\r
1148 { "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE },
\r
1149 { "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1150 { "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1151 { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },
\r
1152 { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE },
\r
1153 { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE },
\r
1154 { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE },
\r
1155 { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE },
\r
1156 { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE },
\r
1157 { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE },
\r
1158 { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE },
\r
1159 { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE },
\r
1160 { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE },
\r
1161 { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE },
\r
1162 { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE },
\r
1163 { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE },
\r
1164 { "firstIsUCI", ArgBoolean, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1165 { "fUCI", ArgTrue, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1166 { "secondIsUCI", ArgBoolean, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1167 { "sUCI", ArgTrue, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1168 { "firstHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1169 { "fNoOwnBookUCI", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1170 { "firstXBook", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1171 { "secondHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1172 { "sNoOwnBookUCI", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1173 { "secondXBook", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1174 { "polyglotDir", ArgFilename, (LPVOID) &appData.polyglotDir, TRUE },
\r
1175 { "usePolyglotBook", ArgBoolean, (LPVOID) &appData.usePolyglotBook, TRUE },
\r
1176 { "polyglotBook", ArgFilename, (LPVOID) &appData.polyglotBook, TRUE },
\r
1177 { "defaultHashSize", ArgInt, (LPVOID) &appData.defaultHashSize, TRUE },
\r
1178 { "defaultCacheSizeEGTB", ArgInt, (LPVOID) &appData.defaultCacheSizeEGTB, TRUE },
\r
1179 { "defaultPathEGTB", ArgFilename, (LPVOID) &appData.defaultPathEGTB, TRUE },
\r
1181 /* [AS] Layout stuff */
\r
1182 { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },
\r
1183 { "moveHistoryX", ArgInt, (LPVOID) &wpMoveHistory.x, TRUE },
\r
1184 { "moveHistoryY", ArgInt, (LPVOID) &wpMoveHistory.y, TRUE },
\r
1185 { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },
\r
1186 { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },
\r
1188 { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },
\r
1189 { "evalGraphX", ArgInt, (LPVOID) &wpEvalGraph.x, TRUE },
\r
1190 { "evalGraphY", ArgInt, (LPVOID) &wpEvalGraph.y, TRUE },
\r
1191 { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },
\r
1192 { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },
\r
1194 { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },
\r
1195 { "engineOutputX", ArgInt, (LPVOID) &wpEngineOutput.x, TRUE },
\r
1196 { "engineOutputY", ArgInt, (LPVOID) &wpEngineOutput.y, TRUE },
\r
1197 { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },
\r
1198 { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },
\r
1200 /* [HGM] board-size, adjudication and misc. options */
\r
1201 { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE },
\r
1202 { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE },
\r
1203 { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE },
\r
1204 { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE },
\r
1205 { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE },
\r
1206 { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE },
\r
1207 { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE },
\r
1208 { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE },
\r
1209 { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE },
\r
1210 { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE },
\r
1211 { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE },
\r
1212 { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE },
\r
1213 { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE },
\r
1214 { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE },
\r
1215 { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE },
\r
1216 { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE },
\r
1217 { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE },
\r
1218 { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE },
\r
1219 { "userName", ArgString, (LPVOID) &appData.userName, FALSE },
\r
1220 { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE },
\r
1221 { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE },
\r
1222 { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE },
\r
1223 { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE },
\r
1224 { "niceEngines", ArgInt, (LPVOID) &appData.niceEngines, TRUE },
\r
1225 { "firstLogo", ArgFilename, (LPVOID) &appData.firstLogo, FALSE },
\r
1226 { "secondLogo", ArgFilename, (LPVOID) &appData.secondLogo, FALSE },
\r
1227 { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE },
\r
1228 { "firstOptions", ArgString, (LPVOID) &appData.firstOptions, FALSE },
\r
1229 { "secondOptions", ArgString, (LPVOID) &appData.secondOptions, FALSE },
\r
1232 { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },
\r
1233 { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },
\r
1234 { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1235 { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1236 { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },
\r
1237 { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },
\r
1238 { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1239 { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1240 { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },
\r
1241 { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },
\r
1242 { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },
\r
1243 { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE },
\r
1244 { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,
\r
1246 { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE },
\r
1247 { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE },
\r
1248 { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE },
\r
1249 { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1250 { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1251 { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE },
\r
1252 { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,
\r
1254 { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1255 { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1256 { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1257 { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE },
\r
1258 { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE },
\r
1259 { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1260 { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1261 { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1262 { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1263 { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE },
\r
1264 { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE },
\r
1265 { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1266 { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1267 { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },
\r
1268 { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },
\r
1269 { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },
\r
1270 /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */
\r
1271 { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },
\r
1273 /* [HGM] options for broadcasting and time odds */
\r
1274 { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },
\r
1275 { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },
\r
1276 { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },
\r
1277 { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },
\r
1278 { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },
\r
1279 { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },
\r
1280 { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },
\r
1281 { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },
\r
1282 { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },
\r
1283 { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },
\r
1284 { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE },
\r
1285 { NULL, ArgNone, NULL, FALSE }
\r
1289 /* Kludge for indirection files on command line */
\r
1290 char* lastIndirectionFilename;
\r
1291 ArgDescriptor argDescriptorIndirection =
\r
1292 { "", ArgSettingsFilename, (LPVOID) NULL, FALSE };
\r
1296 ExitArgError(char *msg, char *badArg)
\r
1298 char buf[MSG_SIZ];
\r
1300 sprintf(buf, "%s %s", msg, badArg);
\r
1301 DisplayFatalError(buf, 0, 2);
\r
1305 /* Command line font name parser. NULL name means do nothing.
\r
1306 Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"
\r
1307 For backward compatibility, syntax without the colon is also
\r
1308 accepted, but font names with digits in them won't work in that case.
\r
1311 ParseFontName(char *name, MyFontParams *mfp)
\r
1314 if (name == NULL) return;
\r
1316 q = strchr(p, ':');
\r
1318 if (q - p >= sizeof(mfp->faceName))
\r
1319 ExitArgError("Font name too long:", name);
\r
1320 memcpy(mfp->faceName, p, q - p);
\r
1321 mfp->faceName[q - p] = NULLCHAR;
\r
1324 q = mfp->faceName;
\r
1325 while (*p && !isdigit(*p)) {
\r
1327 if (q - mfp->faceName >= sizeof(mfp->faceName))
\r
1328 ExitArgError("Font name too long:", name);
\r
1330 while (q > mfp->faceName && q[-1] == ' ') q--;
\r
1333 if (!*p) ExitArgError("Font point size missing:", name);
\r
1334 mfp->pointSize = (float) atof(p);
\r
1335 mfp->bold = (strchr(p, 'b') != NULL);
\r
1336 mfp->italic = (strchr(p, 'i') != NULL);
\r
1337 mfp->underline = (strchr(p, 'u') != NULL);
\r
1338 mfp->strikeout = (strchr(p, 's') != NULL);
\r
1341 /* Color name parser.
\r
1342 X version accepts X color names, but this one
\r
1343 handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */
\r
1345 ParseColorName(char *name)
\r
1347 int red, green, blue, count;
\r
1348 char buf[MSG_SIZ];
\r
1350 count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);
\r
1352 count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d",
\r
1353 &red, &green, &blue);
\r
1356 sprintf(buf, "Can't parse color name %s", name);
\r
1357 DisplayError(buf, 0);
\r
1358 return RGB(0, 0, 0);
\r
1360 return PALETTERGB(red, green, blue);
\r
1364 void ParseAttribs(COLORREF *color, int *effects, char* argValue)
\r
1366 char *e = argValue;
\r
1370 if (*e == 'b') eff |= CFE_BOLD;
\r
1371 else if (*e == 'i') eff |= CFE_ITALIC;
\r
1372 else if (*e == 'u') eff |= CFE_UNDERLINE;
\r
1373 else if (*e == 's') eff |= CFE_STRIKEOUT;
\r
1374 else if (*e == '#' || isdigit(*e)) break;
\r
1378 *color = ParseColorName(e);
\r
1383 ParseBoardSize(char *name)
\r
1385 BoardSize bs = SizeTiny;
\r
1386 while (sizeInfo[bs].name != NULL) {
\r
1387 if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;
\r
1390 ExitArgError("Unrecognized board size value", name);
\r
1391 return bs; /* not reached */
\r
1396 StringGet(void *getClosure)
\r
1398 char **p = (char **) getClosure;
\r
1403 FileGet(void *getClosure)
\r
1406 FILE* f = (FILE*) getClosure;
\r
1415 /* Parse settings file named "name". If file found, return the
\r
1416 full name in fullname and return TRUE; else return FALSE */
\r
1418 ParseSettingsFile(char *name, char fullname[MSG_SIZ])
\r
1423 if (SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy)) {
\r
1424 f = fopen(fullname, "r");
\r
1426 ParseArgs(FileGet, f);
\r
1435 ParseArgs(GetFunc get, void *cl)
\r
1437 char argName[ARG_MAX];
\r
1438 char argValue[ARG_MAX];
\r
1439 ArgDescriptor *ad;
\r
1448 while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);
\r
1449 if (ch == NULLCHAR) break;
\r
1451 /* Comment to end of line */
\r
1453 while (ch != '\n' && ch != NULLCHAR) ch = get(cl);
\r
1455 } else if (ch == '/' || ch == '-') {
\r
1458 while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&
\r
1459 ch != '\n' && ch != '\t') {
\r
1465 for (ad = argDescriptors; ad->argName != NULL; ad++)
\r
1466 if (strcmp(ad->argName, argName + 1) == 0) break;
\r
1468 if (ad->argName == NULL)
\r
1469 ExitArgError("Unrecognized argument", argName);
\r
1471 } else if (ch == '@') {
\r
1472 /* Indirection file */
\r
1473 ad = &argDescriptorIndirection;
\r
1476 /* Positional argument */
\r
1477 ad = &argDescriptors[posarg++];
\r
1478 strcpy(argName, ad->argName);
\r
1481 if (ad->argType == ArgTrue) {
\r
1482 *(Boolean *) ad->argLoc = TRUE;
\r
1485 if (ad->argType == ArgFalse) {
\r
1486 *(Boolean *) ad->argLoc = FALSE;
\r
1490 while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
\r
1491 if (ch == NULLCHAR || ch == '\n') {
\r
1492 ExitArgError("No value provided for argument", argName);
\r
1496 // Quoting with { }. No characters have to (or can) be escaped.
\r
1497 // Thus the string cannot contain a '}' character.
\r
1517 } else if (ch == '\'' || ch == '"') {
\r
1518 // Quoting with ' ' or " ", with \ as escape character.
\r
1519 // Inconvenient for long strings that may contain Windows filenames.
\r
1536 if (ch == start) {
\r
1545 if (ad->argType == ArgFilename
\r
1546 || ad->argType == ArgSettingsFilename) {
\r
1552 ExitArgError("Incomplete \\ escape in value for", argName);
\r
1576 for (i = 0; i < 3; i++) {
\r
1577 if (ch >= '0' && ch <= '7') {
\r
1578 octval = octval*8 + (ch - '0');
\r
1585 *q++ = (char) octval;
\r
1596 while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {
\r
1603 switch (ad->argType) {
\r
1605 *(int *) ad->argLoc = atoi(argValue);
\r
1609 *(float *) ad->argLoc = (float) atof(argValue);
\r
1614 *(char **) ad->argLoc = strdup(argValue);
\r
1617 case ArgSettingsFilename:
\r
1619 char fullname[MSG_SIZ];
\r
1620 if (ParseSettingsFile(argValue, fullname)) {
\r
1621 if (ad->argLoc != NULL) {
\r
1622 *(char **) ad->argLoc = strdup(fullname);
\r
1625 if (ad->argLoc != NULL) {
\r
1627 ExitArgError("Failed to open indirection file", argValue);
\r
1634 switch (argValue[0]) {
\r
1637 *(Boolean *) ad->argLoc = TRUE;
\r
1641 *(Boolean *) ad->argLoc = FALSE;
\r
1644 ExitArgError("Unrecognized boolean argument value", argValue);
\r
1650 *(COLORREF *)ad->argLoc = ParseColorName(argValue);
\r
1653 case ArgAttribs: {
\r
1654 ColorClass cc = (ColorClass)ad->argLoc;
\r
1655 ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);
\r
1659 case ArgBoardSize:
\r
1660 *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);
\r
1664 ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);
\r
1667 case ArgCommSettings:
\r
1668 ParseCommSettings(argValue, &dcb);
\r
1672 ExitArgError("Unrecognized argument", argValue);
\r
1679 LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
\r
1681 HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
\r
1682 lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);
\r
1685 lf->lfEscapement = 0;
\r
1686 lf->lfOrientation = 0;
\r
1687 lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;
\r
1688 lf->lfItalic = mfp->italic;
\r
1689 lf->lfUnderline = mfp->underline;
\r
1690 lf->lfStrikeOut = mfp->strikeout;
\r
1691 lf->lfCharSet = DEFAULT_CHARSET;
\r
1692 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
1693 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
1694 lf->lfQuality = DEFAULT_QUALITY;
\r
1695 lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
\r
1696 strcpy(lf->lfFaceName, mfp->faceName);
\r
1700 CreateFontInMF(MyFont *mf)
\r
1702 LFfromMFP(&mf->lf, &mf->mfp);
\r
1703 if (mf->hf) DeleteObject(mf->hf);
\r
1704 mf->hf = CreateFontIndirect(&mf->lf);
\r
1708 SetDefaultTextAttribs()
\r
1711 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1712 ParseAttribs(&textAttribs[cc].color,
\r
1713 &textAttribs[cc].effects,
\r
1714 defaultTextAttribs[cc]);
\r
1719 SetDefaultSounds()
\r
1723 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1724 textAttribs[cc].sound.name = strdup("");
\r
1725 textAttribs[cc].sound.data = NULL;
\r
1727 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1728 sounds[sc].name = strdup("");
\r
1729 sounds[sc].data = NULL;
\r
1731 sounds[(int)SoundBell].name = strdup(SOUND_BELL);
\r
1739 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1740 MyLoadSound(&textAttribs[cc].sound);
\r
1742 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1743 MyLoadSound(&sounds[sc]);
\r
1748 InitAppData(LPSTR lpCmdLine)
\r
1751 char buf[ARG_MAX], currDir[MSG_SIZ];
\r
1754 programName = szAppName;
\r
1756 /* Initialize to defaults */
\r
1757 lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);
\r
1758 darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);
\r
1759 whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);
\r
1760 blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);
\r
1761 highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);
\r
1762 premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);
\r
1763 consoleBackgroundColor = ParseColorName(COLOR_BKGD);
\r
1764 SetDefaultTextAttribs();
\r
1765 SetDefaultSounds();
\r
1766 appData.movesPerSession = MOVES_PER_SESSION;
\r
1767 appData.initString = INIT_STRING;
\r
1768 appData.secondInitString = INIT_STRING;
\r
1769 appData.firstComputerString = COMPUTER_STRING;
\r
1770 appData.secondComputerString = COMPUTER_STRING;
\r
1771 appData.firstChessProgram = FIRST_CHESS_PROGRAM;
\r
1772 appData.secondChessProgram = SECOND_CHESS_PROGRAM;
\r
1773 appData.firstPlaysBlack = FALSE;
\r
1774 appData.noChessProgram = FALSE;
\r
1775 chessProgram = FALSE;
\r
1776 appData.firstHost = FIRST_HOST;
\r
1777 appData.secondHost = SECOND_HOST;
\r
1778 appData.firstDirectory = FIRST_DIRECTORY;
\r
1779 appData.secondDirectory = SECOND_DIRECTORY;
\r
1780 appData.bitmapDirectory = "";
\r
1781 appData.remoteShell = REMOTE_SHELL;
\r
1782 appData.remoteUser = "";
\r
1783 appData.timeDelay = TIME_DELAY;
\r
1784 appData.timeControl = TIME_CONTROL;
\r
1785 appData.timeIncrement = TIME_INCREMENT;
\r
1786 appData.icsActive = FALSE;
\r
1787 appData.icsHost = "";
\r
1788 appData.icsPort = ICS_PORT;
\r
1789 appData.icsCommPort = ICS_COMM_PORT;
\r
1790 appData.icsLogon = ICS_LOGON;
\r
1791 appData.icsHelper = "";
\r
1792 appData.useTelnet = FALSE;
\r
1793 appData.telnetProgram = TELNET_PROGRAM;
\r
1794 appData.gateway = "";
\r
1795 appData.loadGameFile = "";
\r
1796 appData.loadGameIndex = 0;
\r
1797 appData.saveGameFile = "";
\r
1798 appData.autoSaveGames = FALSE;
\r
1799 appData.loadPositionFile = "";
\r
1800 appData.loadPositionIndex = 1;
\r
1801 appData.savePositionFile = "";
\r
1802 appData.matchMode = FALSE;
\r
1803 appData.matchGames = 0;
\r
1804 appData.monoMode = FALSE;
\r
1805 appData.debugMode = FALSE;
\r
1806 appData.clockMode = TRUE;
\r
1807 boardSize = (BoardSize) -1; /* determine by screen size */
\r
1808 appData.Iconic = FALSE; /*unused*/
\r
1809 appData.searchTime = "";
\r
1810 appData.searchDepth = 0;
\r
1811 appData.showCoords = FALSE;
\r
1812 appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/
\r
1813 appData.autoCallFlag = FALSE;
\r
1814 appData.flipView = FALSE;
\r
1815 appData.autoFlipView = TRUE;
\r
1816 appData.cmailGameName = "";
\r
1817 appData.alwaysPromoteToQueen = FALSE;
\r
1818 appData.oldSaveStyle = FALSE;
\r
1819 appData.quietPlay = FALSE;
\r
1820 appData.showThinking = FALSE;
\r
1821 appData.ponderNextMove = TRUE;
\r
1822 appData.periodicUpdates = TRUE;
\r
1823 appData.popupExitMessage = TRUE;
\r
1824 appData.popupMoveErrors = FALSE;
\r
1825 appData.autoObserve = FALSE;
\r
1826 appData.autoComment = FALSE;
\r
1827 appData.animate = TRUE;
\r
1828 appData.animSpeed = 10;
\r
1829 appData.animateDragging = TRUE;
\r
1830 appData.highlightLastMove = TRUE;
\r
1831 appData.getMoveList = TRUE;
\r
1832 appData.testLegality = TRUE;
\r
1833 appData.premove = TRUE;
\r
1834 appData.premoveWhite = FALSE;
\r
1835 appData.premoveWhiteText = "";
\r
1836 appData.premoveBlack = FALSE;
\r
1837 appData.premoveBlackText = "";
\r
1838 appData.icsAlarm = TRUE;
\r
1839 appData.icsAlarmTime = 5000;
\r
1840 appData.autoRaiseBoard = TRUE;
\r
1841 appData.localLineEditing = TRUE;
\r
1842 appData.colorize = TRUE;
\r
1843 appData.reuseFirst = TRUE;
\r
1844 appData.reuseSecond = TRUE;
\r
1845 appData.blindfold = FALSE;
\r
1846 appData.icsEngineAnalyze = FALSE;
\r
1847 dcb.DCBlength = sizeof(DCB);
\r
1848 dcb.BaudRate = 9600;
\r
1849 dcb.fBinary = TRUE;
\r
1850 dcb.fParity = FALSE;
\r
1851 dcb.fOutxCtsFlow = FALSE;
\r
1852 dcb.fOutxDsrFlow = FALSE;
\r
1853 dcb.fDtrControl = DTR_CONTROL_ENABLE;
\r
1854 dcb.fDsrSensitivity = FALSE;
\r
1855 dcb.fTXContinueOnXoff = TRUE;
\r
1856 dcb.fOutX = FALSE;
\r
1858 dcb.fNull = FALSE;
\r
1859 dcb.fRtsControl = RTS_CONTROL_ENABLE;
\r
1860 dcb.fAbortOnError = FALSE;
\r
1861 /* Microsoft SDK >= Feb. 2003 (MS VS >= 2002) */
\r
1862 #if (defined(_MSC_VER) && _MSC_VER <= 1200)
\r
1863 //dcb.wReserved = 0;
\r
1865 dcb.wReserved = 0;
\r
1868 dcb.Parity = SPACEPARITY;
\r
1869 dcb.StopBits = ONESTOPBIT;
\r
1870 settingsFileName = SETTINGS_FILE;
\r
1871 saveSettingsOnExit = TRUE;
\r
1872 boardX = CW_USEDEFAULT;
\r
1873 boardY = CW_USEDEFAULT;
\r
1874 consoleX = CW_USEDEFAULT;
\r
1875 consoleY = CW_USEDEFAULT;
\r
1876 consoleW = CW_USEDEFAULT;
\r
1877 consoleH = CW_USEDEFAULT;
\r
1878 analysisX = CW_USEDEFAULT;
\r
1879 analysisY = CW_USEDEFAULT;
\r
1880 analysisW = CW_USEDEFAULT;
\r
1881 analysisH = CW_USEDEFAULT;
\r
1882 commentX = CW_USEDEFAULT;
\r
1883 commentY = CW_USEDEFAULT;
\r
1884 commentW = CW_USEDEFAULT;
\r
1885 commentH = CW_USEDEFAULT;
\r
1886 editTagsX = CW_USEDEFAULT;
\r
1887 editTagsY = CW_USEDEFAULT;
\r
1888 editTagsW = CW_USEDEFAULT;
\r
1889 editTagsH = CW_USEDEFAULT;
\r
1890 gameListX = CW_USEDEFAULT;
\r
1891 gameListY = CW_USEDEFAULT;
\r
1892 gameListW = CW_USEDEFAULT;
\r
1893 gameListH = CW_USEDEFAULT;
\r
1894 icsTextMenuString = ICS_TEXT_MENU_DEFAULT;
\r
1895 icsNames = ICS_NAMES;
\r
1896 firstChessProgramNames = FCP_NAMES;
\r
1897 secondChessProgramNames = SCP_NAMES;
\r
1898 appData.initialMode = "";
\r
1899 appData.variant = "normal";
\r
1900 appData.firstProtocolVersion = PROTOVER;
\r
1901 appData.secondProtocolVersion = PROTOVER;
\r
1902 appData.showButtonBar = TRUE;
\r
1904 /* [AS] New properties (see comments in header file) */
\r
1905 appData.firstScoreIsAbsolute = FALSE;
\r
1906 appData.secondScoreIsAbsolute = FALSE;
\r
1907 appData.saveExtendedInfoInPGN = FALSE;
\r
1908 appData.hideThinkingFromHuman = FALSE;
\r
1909 appData.liteBackTextureFile = "";
\r
1910 appData.liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
1911 appData.darkBackTextureFile = "";
\r
1912 appData.darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
1913 appData.renderPiecesWithFont = "";
\r
1914 appData.fontToPieceTable = "";
\r
1915 appData.fontBackColorWhite = 0;
\r
1916 appData.fontForeColorWhite = 0;
\r
1917 appData.fontBackColorBlack = 0;
\r
1918 appData.fontForeColorBlack = 0;
\r
1919 appData.fontPieceSize = 80;
\r
1920 appData.overrideLineGap = 1;
\r
1921 appData.adjudicateLossThreshold = 0;
\r
1922 appData.delayBeforeQuit = 0;
\r
1923 appData.delayAfterQuit = 0;
\r
1924 appData.nameOfDebugFile = "winboard.debug";
\r
1925 appData.pgnEventHeader = "Computer Chess Game";
\r
1926 appData.defaultFrcPosition = -1;
\r
1927 appData.gameListTags = GLT_DEFAULT_TAGS;
\r
1928 appData.saveOutOfBookInfo = TRUE;
\r
1929 appData.showEvalInMoveHistory = TRUE;
\r
1930 appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );
\r
1931 appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );
\r
1932 appData.highlightMoveWithArrow = FALSE;
\r
1933 appData.highlightArrowColor = ParseColorName( "#FFFF80" );
\r
1934 appData.useStickyWindows = TRUE;
\r
1935 appData.adjudicateDrawMoves = 0;
\r
1936 appData.autoDisplayComment = TRUE;
\r
1937 appData.autoDisplayTags = TRUE;
\r
1938 appData.firstIsUCI = FALSE;
\r
1939 appData.secondIsUCI = FALSE;
\r
1940 appData.firstHasOwnBookUCI = TRUE;
\r
1941 appData.secondHasOwnBookUCI = TRUE;
\r
1942 appData.polyglotDir = "";
\r
1943 appData.usePolyglotBook = FALSE;
\r
1944 appData.polyglotBook = "";
\r
1945 appData.defaultHashSize = 64;
\r
1946 appData.defaultCacheSizeEGTB = 4;
\r
1947 appData.defaultPathEGTB = "c:\\egtb";
\r
1948 appData.firstOptions = "";
\r
1949 appData.secondOptions = "";
\r
1951 InitWindowPlacement( &wpMoveHistory );
\r
1952 InitWindowPlacement( &wpEvalGraph );
\r
1953 InitWindowPlacement( &wpEngineOutput );
\r
1955 /* [HGM] User-selectable board size, adjudication control, miscellaneous */
\r
1956 appData.NrFiles = -1;
\r
1957 appData.NrRanks = -1;
\r
1958 appData.holdingsSize = -1;
\r
1959 appData.testClaims = FALSE;
\r
1960 appData.checkMates = FALSE;
\r
1961 appData.materialDraws= FALSE;
\r
1962 appData.trivialDraws = FALSE;
\r
1963 appData.ruleMoves = 51;
\r
1964 appData.drawRepeats = 6;
\r
1965 appData.matchPause = 10000;
\r
1966 appData.alphaRank = FALSE;
\r
1967 appData.allWhite = FALSE;
\r
1968 appData.upsideDown = FALSE;
\r
1969 appData.serverPause = 15;
\r
1970 appData.serverMovesName = NULL;
\r
1971 appData.suppressLoadMoves = FALSE;
\r
1972 appData.firstTimeOdds = 1;
\r
1973 appData.secondTimeOdds = 1;
\r
1974 appData.firstAccumulateTC = 1; // combine previous and current sessions
\r
1975 appData.secondAccumulateTC = 1;
\r
1976 appData.firstNPS = -1; // [HGM] nps: use wall-clock time
\r
1977 appData.secondNPS = -1;
\r
1978 appData.engineComments = 1;
\r
1979 appData.smpCores = 1; // [HGM] SMP: max nr of cores
\r
1980 appData.egtFormats = "";
\r
1983 appData.zippyTalk = ZIPPY_TALK;
\r
1984 appData.zippyPlay = ZIPPY_PLAY;
\r
1985 appData.zippyLines = ZIPPY_LINES;
\r
1986 appData.zippyPinhead = ZIPPY_PINHEAD;
\r
1987 appData.zippyPassword = ZIPPY_PASSWORD;
\r
1988 appData.zippyPassword2 = ZIPPY_PASSWORD2;
\r
1989 appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;
\r
1990 appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;
\r
1991 appData.zippyUseI = ZIPPY_USE_I;
\r
1992 appData.zippyBughouse = ZIPPY_BUGHOUSE;
\r
1993 appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;
\r
1994 appData.zippyGameEnd = ZIPPY_GAME_END;
\r
1995 appData.zippyGameStart = ZIPPY_GAME_START;
\r
1996 appData.zippyAdjourn = ZIPPY_ADJOURN;
\r
1997 appData.zippyAbort = ZIPPY_ABORT;
\r
1998 appData.zippyVariants = ZIPPY_VARIANTS;
\r
1999 appData.zippyMaxGames = ZIPPY_MAX_GAMES;
\r
2000 appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;
\r
2003 /* Point font array elements to structures and
\r
2004 parse default font names */
\r
2005 for (i=0; i<NUM_FONTS; i++) {
\r
2006 for (j=0; j<NUM_SIZES; j++) {
\r
2007 font[j][i] = &fontRec[j][i];
\r
2008 ParseFontName(font[j][i]->def, &font[j][i]->mfp);
\r
2012 /* Parse default settings file if any */
\r
2013 if (ParseSettingsFile(settingsFileName, buf)) {
\r
2014 settingsFileName = strdup(buf);
\r
2017 /* Parse command line */
\r
2018 ParseArgs(StringGet, &lpCmdLine);
\r
2020 /* [HGM] make sure board size is acceptable */
\r
2021 if(appData.NrFiles > BOARD_SIZE ||
\r
2022 appData.NrRanks > BOARD_SIZE )
\r
2023 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
2025 /* [HGM] After parsing the options from the .ini file, and overruling them
\r
2026 * with options from the command line, we now make an even higher priority
\r
2027 * overrule by WB options attached to the engine command line. This so that
\r
2028 * tournament managers can use WB options (such as /timeOdds) that follow
\r
2031 if(appData.firstChessProgram != NULL) {
\r
2032 char *p = StrStr(appData.firstChessProgram, "WBopt");
\r
2033 static char *f = "first";
\r
2034 char buf[MSG_SIZ], *q = buf;
\r
2035 if(p != NULL) { // engine command line contains WinBoard options
\r
2036 sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"
\r
2037 ParseArgs(StringGet, &q);
\r
2038 p[-1] = 0; // cut them offengine command line
\r
2041 // now do same for second chess program
\r
2042 if(appData.secondChessProgram != NULL) {
\r
2043 char *p = StrStr(appData.secondChessProgram, "WBopt");
\r
2044 static char *s = "second";
\r
2045 char buf[MSG_SIZ], *q = buf;
\r
2046 if(p != NULL) { // engine command line contains WinBoard options
\r
2047 sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"
\r
2048 ParseArgs(StringGet, &q);
\r
2049 p[-1] = 0; // cut them offengine command line
\r
2054 /* Propagate options that affect others */
\r
2055 if (appData.matchMode || appData.matchGames) chessProgram = TRUE;
\r
2056 if (appData.icsActive || appData.noChessProgram) {
\r
2057 chessProgram = FALSE; /* not local chess program mode */
\r
2060 /* Open startup dialog if needed */
\r
2061 if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||
\r
2062 (appData.icsActive && *appData.icsHost == NULLCHAR) ||
\r
2063 (chessProgram && (*appData.firstChessProgram == NULLCHAR ||
\r
2064 *appData.secondChessProgram == NULLCHAR))) {
\r
2067 lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);
\r
2068 DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);
\r
2069 FreeProcInstance(lpProc);
\r
2072 /* Make sure save files land in the right (?) directory */
\r
2073 if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {
\r
2074 appData.saveGameFile = strdup(buf);
\r
2076 if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {
\r
2077 appData.savePositionFile = strdup(buf);
\r
2080 /* Finish initialization for fonts and sounds */
\r
2081 for (i=0; i<NUM_FONTS; i++) {
\r
2082 for (j=0; j<NUM_SIZES; j++) {
\r
2083 CreateFontInMF(font[j][i]);
\r
2086 /* xboard, and older WinBoards, controlled the move sound with the
\r
2087 appData.ringBellAfterMoves option. In the current WinBoard, we
\r
2088 always turn the option on (so that the backend will call us),
\r
2089 then let the user turn the sound off by setting it to silence if
\r
2090 desired. To accommodate old winboard.ini files saved by old
\r
2091 versions of WinBoard, we also turn off the sound if the option
\r
2092 was initially set to false. */
\r
2093 if (!appData.ringBellAfterMoves) {
\r
2094 sounds[(int)SoundMove].name = strdup("");
\r
2095 appData.ringBellAfterMoves = TRUE;
\r
2097 GetCurrentDirectory(MSG_SIZ, currDir);
\r
2098 SetCurrentDirectory(installDir);
\r
2100 SetCurrentDirectory(currDir);
\r
2102 p = icsTextMenuString;
\r
2103 if (p[0] == '@') {
\r
2104 FILE* f = fopen(p + 1, "r");
\r
2106 DisplayFatalError(p + 1, errno, 2);
\r
2109 i = fread(buf, 1, sizeof(buf)-1, f);
\r
2111 buf[i] = NULLCHAR;
\r
2114 ParseIcsTextMenu(strdup(p));
\r
2121 HMENU hmenu = GetMenu(hwndMain);
\r
2123 (void) EnableMenuItem(hmenu, IDM_CommPort,
\r
2124 MF_BYCOMMAND|((appData.icsActive &&
\r
2125 *appData.icsCommPort != NULLCHAR) ?
\r
2126 MF_ENABLED : MF_GRAYED));
\r
2127 (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,
\r
2128 MF_BYCOMMAND|(saveSettingsOnExit ?
\r
2129 MF_CHECKED : MF_UNCHECKED));
\r
2134 SaveSettings(char* name)
\r
2137 ArgDescriptor *ad;
\r
2138 WINDOWPLACEMENT wp;
\r
2139 char dir[MSG_SIZ];
\r
2141 if (!hwndMain) return;
\r
2143 GetCurrentDirectory(MSG_SIZ, dir);
\r
2144 SetCurrentDirectory(installDir);
\r
2145 f = fopen(name, "w");
\r
2146 SetCurrentDirectory(dir);
\r
2148 DisplayError(name, errno);
\r
2151 fprintf(f, ";\n");
\r
2152 fprintf(f, "; %s %s.%s Save Settings file\n", PRODUCT, VERSION, PATCHLEVEL);
\r
2153 fprintf(f, ";\n");
\r
2154 fprintf(f, "; You can edit the values of options that are already set in this file,\n");
\r
2155 fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");
\r
2156 fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");
\r
2157 fprintf(f, ";\n");
\r
2159 wp.length = sizeof(WINDOWPLACEMENT);
\r
2160 GetWindowPlacement(hwndMain, &wp);
\r
2161 boardX = wp.rcNormalPosition.left;
\r
2162 boardY = wp.rcNormalPosition.top;
\r
2164 if (hwndConsole) {
\r
2165 GetWindowPlacement(hwndConsole, &wp);
\r
2166 consoleX = wp.rcNormalPosition.left;
\r
2167 consoleY = wp.rcNormalPosition.top;
\r
2168 consoleW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2169 consoleH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2172 if (analysisDialog) {
\r
2173 GetWindowPlacement(analysisDialog, &wp);
\r
2174 analysisX = wp.rcNormalPosition.left;
\r
2175 analysisY = wp.rcNormalPosition.top;
\r
2176 analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2177 analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2180 if (commentDialog) {
\r
2181 GetWindowPlacement(commentDialog, &wp);
\r
2182 commentX = wp.rcNormalPosition.left;
\r
2183 commentY = wp.rcNormalPosition.top;
\r
2184 commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2185 commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2188 if (editTagsDialog) {
\r
2189 GetWindowPlacement(editTagsDialog, &wp);
\r
2190 editTagsX = wp.rcNormalPosition.left;
\r
2191 editTagsY = wp.rcNormalPosition.top;
\r
2192 editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2193 editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2196 if (gameListDialog) {
\r
2197 GetWindowPlacement(gameListDialog, &wp);
\r
2198 gameListX = wp.rcNormalPosition.left;
\r
2199 gameListY = wp.rcNormalPosition.top;
\r
2200 gameListW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2201 gameListH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2204 /* [AS] Move history */
\r
2205 wpMoveHistory.visible = MoveHistoryIsUp();
\r
2207 if( moveHistoryDialog ) {
\r
2208 GetWindowPlacement(moveHistoryDialog, &wp);
\r
2209 wpMoveHistory.x = wp.rcNormalPosition.left;
\r
2210 wpMoveHistory.y = wp.rcNormalPosition.top;
\r
2211 wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2212 wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2215 /* [AS] Eval graph */
\r
2216 wpEvalGraph.visible = EvalGraphIsUp();
\r
2218 if( evalGraphDialog ) {
\r
2219 GetWindowPlacement(evalGraphDialog, &wp);
\r
2220 wpEvalGraph.x = wp.rcNormalPosition.left;
\r
2221 wpEvalGraph.y = wp.rcNormalPosition.top;
\r
2222 wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2223 wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2226 /* [AS] Engine output */
\r
2227 wpEngineOutput.visible = EngineOutputIsUp();
\r
2229 if( engineOutputDialog ) {
\r
2230 GetWindowPlacement(engineOutputDialog, &wp);
\r
2231 wpEngineOutput.x = wp.rcNormalPosition.left;
\r
2232 wpEngineOutput.y = wp.rcNormalPosition.top;
\r
2233 wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2234 wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2237 for (ad = argDescriptors; ad->argName != NULL; ad++) {
\r
2238 if (!ad->save) continue;
\r
2239 switch (ad->argType) {
\r
2242 char *p = *(char **)ad->argLoc;
\r
2243 if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {
\r
2244 /* Quote multiline values or \-containing values
\r
2245 with { } if possible */
\r
2246 fprintf(f, "/%s={%s}\n", ad->argName, p);
\r
2248 /* Else quote with " " */
\r
2249 fprintf(f, "/%s=\"", ad->argName);
\r
2251 if (*p == '\n') fprintf(f, "\n");
\r
2252 else if (*p == '\r') fprintf(f, "\\r");
\r
2253 else if (*p == '\t') fprintf(f, "\\t");
\r
2254 else if (*p == '\b') fprintf(f, "\\b");
\r
2255 else if (*p == '\f') fprintf(f, "\\f");
\r
2256 else if (*p < ' ') fprintf(f, "\\%03o", *p);
\r
2257 else if (*p == '\"') fprintf(f, "\\\"");
\r
2258 else if (*p == '\\') fprintf(f, "\\\\");
\r
2262 fprintf(f, "\"\n");
\r
2267 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);
\r
2270 fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);
\r
2273 fprintf(f, "/%s=%s\n", ad->argName,
\r
2274 (*(Boolean *)ad->argLoc) ? "true" : "false");
\r
2277 if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2280 if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2284 COLORREF color = *(COLORREF *)ad->argLoc;
\r
2285 fprintf(f, "/%s=#%02x%02x%02x\n", ad->argName,
\r
2286 color&0xff, (color>>8)&0xff, (color>>16)&0xff);
\r
2291 MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];
\r
2292 fprintf(f, "/%s=\"%s%s%s%s%s#%02x%02x%02x\"\n", ad->argName,
\r
2293 (ta->effects & CFE_BOLD) ? "b" : "",
\r
2294 (ta->effects & CFE_ITALIC) ? "i" : "",
\r
2295 (ta->effects & CFE_UNDERLINE) ? "u" : "",
\r
2296 (ta->effects & CFE_STRIKEOUT) ? "s" : "",
\r
2297 (ta->effects) ? " " : "",
\r
2298 ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);
\r
2302 if (strchr(*(char **)ad->argLoc, '\"')) {
\r
2303 fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);
\r
2305 fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);
\r
2308 case ArgBoardSize:
\r
2309 fprintf(f, "/%s=%s\n", ad->argName,
\r
2310 sizeInfo[*(BoardSize *)ad->argLoc].name);
\r
2315 for (bs=0; bs<NUM_SIZES; bs++) {
\r
2316 MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;
\r
2317 fprintf(f, "/size=%s ", sizeInfo[bs].name);
\r
2318 fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n",
\r
2319 ad->argName, mfp->faceName, mfp->pointSize,
\r
2320 mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",
\r
2321 mfp->bold ? "b" : "",
\r
2322 mfp->italic ? "i" : "",
\r
2323 mfp->underline ? "u" : "",
\r
2324 mfp->strikeout ? "s" : "");
\r
2328 case ArgCommSettings:
\r
2329 PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);
\r
2337 /*---------------------------------------------------------------------------*\
\r
2339 * GDI board drawing routines
\r
2341 \*---------------------------------------------------------------------------*/
\r
2343 /* [AS] Draw square using background texture */
\r
2344 static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )
\r
2349 return; /* Should never happen! */
\r
2352 SetGraphicsMode( dst, GM_ADVANCED );
\r
2359 /* X reflection */
\r
2364 x.eDx = (FLOAT) dw + dx - 1;
\r
2367 SetWorldTransform( dst, &x );
\r
2370 /* Y reflection */
\r
2376 x.eDy = (FLOAT) dh + dy - 1;
\r
2378 SetWorldTransform( dst, &x );
\r
2386 x.eDx = (FLOAT) dx;
\r
2387 x.eDy = (FLOAT) dy;
\r
2390 SetWorldTransform( dst, &x );
\r
2394 BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );
\r
2402 SetWorldTransform( dst, &x );
\r
2404 ModifyWorldTransform( dst, 0, MWT_IDENTITY );
\r
2407 /* [AS] [HGM] Make room for more piece types, so all pieces can be different */
\r
2409 PM_WP = (int) WhitePawn,
\r
2410 PM_WN = (int) WhiteKnight,
\r
2411 PM_WB = (int) WhiteBishop,
\r
2412 PM_WR = (int) WhiteRook,
\r
2413 PM_WQ = (int) WhiteQueen,
\r
2414 PM_WF = (int) WhiteFerz,
\r
2415 PM_WW = (int) WhiteWazir,
\r
2416 PM_WE = (int) WhiteAlfil,
\r
2417 PM_WM = (int) WhiteMan,
\r
2418 PM_WO = (int) WhiteCannon,
\r
2419 PM_WU = (int) WhiteUnicorn,
\r
2420 PM_WH = (int) WhiteNightrider,
\r
2421 PM_WA = (int) WhiteAngel,
\r
2422 PM_WC = (int) WhiteMarshall,
\r
2423 PM_WAB = (int) WhiteCardinal,
\r
2424 PM_WD = (int) WhiteDragon,
\r
2425 PM_WL = (int) WhiteLance,
\r
2426 PM_WS = (int) WhiteCobra,
\r
2427 PM_WV = (int) WhiteFalcon,
\r
2428 PM_WSG = (int) WhiteSilver,
\r
2429 PM_WG = (int) WhiteGrasshopper,
\r
2430 PM_WK = (int) WhiteKing,
\r
2431 PM_BP = (int) BlackPawn,
\r
2432 PM_BN = (int) BlackKnight,
\r
2433 PM_BB = (int) BlackBishop,
\r
2434 PM_BR = (int) BlackRook,
\r
2435 PM_BQ = (int) BlackQueen,
\r
2436 PM_BF = (int) BlackFerz,
\r
2437 PM_BW = (int) BlackWazir,
\r
2438 PM_BE = (int) BlackAlfil,
\r
2439 PM_BM = (int) BlackMan,
\r
2440 PM_BO = (int) BlackCannon,
\r
2441 PM_BU = (int) BlackUnicorn,
\r
2442 PM_BH = (int) BlackNightrider,
\r
2443 PM_BA = (int) BlackAngel,
\r
2444 PM_BC = (int) BlackMarshall,
\r
2445 PM_BG = (int) BlackGrasshopper,
\r
2446 PM_BAB = (int) BlackCardinal,
\r
2447 PM_BD = (int) BlackDragon,
\r
2448 PM_BL = (int) BlackLance,
\r
2449 PM_BS = (int) BlackCobra,
\r
2450 PM_BV = (int) BlackFalcon,
\r
2451 PM_BSG = (int) BlackSilver,
\r
2452 PM_BK = (int) BlackKing
\r
2455 static HFONT hPieceFont = NULL;
\r
2456 static HBITMAP hPieceMask[(int) EmptySquare];
\r
2457 static HBITMAP hPieceFace[(int) EmptySquare];
\r
2458 static int fontBitmapSquareSize = 0;
\r
2459 static char pieceToFontChar[(int) EmptySquare] =
\r
2460 { 'p', 'n', 'b', 'r', 'q',
\r
2461 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',
\r
2462 'k', 'o', 'm', 'v', 't', 'w',
\r
2463 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',
\r
2466 extern BOOL SetCharTable( char *table, const char * map );
\r
2467 /* [HGM] moved to backend.c */
\r
2469 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )
\r
2472 BYTE r1 = GetRValue( color );
\r
2473 BYTE g1 = GetGValue( color );
\r
2474 BYTE b1 = GetBValue( color );
\r
2480 /* Create a uniform background first */
\r
2481 hbrush = CreateSolidBrush( color );
\r
2482 SetRect( &rc, 0, 0, squareSize, squareSize );
\r
2483 FillRect( hdc, &rc, hbrush );
\r
2484 DeleteObject( hbrush );
\r
2487 /* Vertical gradient, good for pawn, knight and rook, less for queen and king */
\r
2488 int steps = squareSize / 2;
\r
2491 for( i=0; i<steps; i++ ) {
\r
2492 BYTE r = r1 - (r1-r2) * i / steps;
\r
2493 BYTE g = g1 - (g1-g2) * i / steps;
\r
2494 BYTE b = b1 - (b1-b2) * i / steps;
\r
2496 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2497 SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );
\r
2498 FillRect( hdc, &rc, hbrush );
\r
2499 DeleteObject(hbrush);
\r
2502 else if( mode == 2 ) {
\r
2503 /* Diagonal gradient, good more or less for every piece */
\r
2504 POINT triangle[3];
\r
2505 HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );
\r
2506 HBRUSH hbrush_old;
\r
2507 int steps = squareSize;
\r
2510 triangle[0].x = squareSize - steps;
\r
2511 triangle[0].y = squareSize;
\r
2512 triangle[1].x = squareSize;
\r
2513 triangle[1].y = squareSize;
\r
2514 triangle[2].x = squareSize;
\r
2515 triangle[2].y = squareSize - steps;
\r
2517 for( i=0; i<steps; i++ ) {
\r
2518 BYTE r = r1 - (r1-r2) * i / steps;
\r
2519 BYTE g = g1 - (g1-g2) * i / steps;
\r
2520 BYTE b = b1 - (b1-b2) * i / steps;
\r
2522 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2523 hbrush_old = SelectObject( hdc, hbrush );
\r
2524 Polygon( hdc, triangle, 3 );
\r
2525 SelectObject( hdc, hbrush_old );
\r
2526 DeleteObject(hbrush);
\r
2531 SelectObject( hdc, hpen );
\r
2536 [AS] The method I use to create the bitmaps it a bit tricky, but it
\r
2537 seems to work ok. The main problem here is to find the "inside" of a chess
\r
2538 piece: follow the steps as explained below.
\r
2540 static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
\r
2544 COLORREF chroma = RGB(0xFF,0x00,0xFF);
\r
2548 int backColor = whitePieceColor;
\r
2549 int foreColor = blackPieceColor;
\r
2551 if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {
\r
2552 backColor = appData.fontBackColorWhite;
\r
2553 foreColor = appData.fontForeColorWhite;
\r
2555 else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {
\r
2556 backColor = appData.fontBackColorBlack;
\r
2557 foreColor = appData.fontForeColorBlack;
\r
2561 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2563 hbm_old = SelectObject( hdc, hbm );
\r
2567 rc.right = squareSize;
\r
2568 rc.bottom = squareSize;
\r
2570 /* Step 1: background is now black */
\r
2571 FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );
\r
2573 GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );
\r
2575 pt.x = (squareSize - sz.cx) / 2;
\r
2576 pt.y = (squareSize - sz.cy) / 2;
\r
2578 SetBkMode( hdc, TRANSPARENT );
\r
2579 SetTextColor( hdc, chroma );
\r
2580 /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */
\r
2581 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2583 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
\r
2584 /* Step 3: the area outside the piece is filled with white */
\r
2585 // FloodFill( hdc, 0, 0, chroma );
\r
2586 ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );
\r
2587 ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big
\r
2588 ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );
\r
2589 ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );
\r
2590 SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
\r
2592 Step 4: this is the tricky part, the area inside the piece is filled with black,
\r
2593 but if the start point is not inside the piece we're lost!
\r
2594 There should be a better way to do this... if we could create a region or path
\r
2595 from the fill operation we would be fine for example.
\r
2597 // FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );
\r
2598 ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );
\r
2600 { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */
\r
2601 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2602 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2604 SelectObject( dc2, bm2 );
\r
2605 BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy
\r
2606 BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2607 BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2608 BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2609 BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2612 DeleteObject( bm2 );
\r
2615 SetTextColor( hdc, 0 );
\r
2617 Step 5: some fonts have "disconnected" areas that are skipped by the fill:
\r
2618 draw the piece again in black for safety.
\r
2620 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2622 SelectObject( hdc, hbm_old );
\r
2624 if( hPieceMask[index] != NULL ) {
\r
2625 DeleteObject( hPieceMask[index] );
\r
2628 hPieceMask[index] = hbm;
\r
2631 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2633 SelectObject( hdc, hbm );
\r
2636 HDC dc1 = CreateCompatibleDC( hdc_window );
\r
2637 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2638 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2640 SelectObject( dc1, hPieceMask[index] );
\r
2641 SelectObject( dc2, bm2 );
\r
2642 FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );
\r
2643 BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );
\r
2646 Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves
\r
2647 the piece background and deletes (makes transparent) the rest.
\r
2648 Thanks to that mask, we are free to paint the background with the greates
\r
2649 freedom, as we'll be able to mask off the unwanted parts when finished.
\r
2650 We use this, to make gradients and give the pieces a "roundish" look.
\r
2652 SetPieceBackground( hdc, backColor, 2 );
\r
2653 BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );
\r
2657 DeleteObject( bm2 );
\r
2660 SetTextColor( hdc, foreColor );
\r
2661 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2663 SelectObject( hdc, hbm_old );
\r
2665 if( hPieceFace[index] != NULL ) {
\r
2666 DeleteObject( hPieceFace[index] );
\r
2669 hPieceFace[index] = hbm;
\r
2672 static int TranslatePieceToFontPiece( int piece )
\r
2702 case BlackMarshall:
\r
2706 case BlackNightrider:
\r
2712 case BlackUnicorn:
\r
2716 case BlackGrasshopper:
\r
2728 case BlackCardinal:
\r
2735 case WhiteMarshall:
\r
2739 case WhiteNightrider:
\r
2745 case WhiteUnicorn:
\r
2749 case WhiteGrasshopper:
\r
2761 case WhiteCardinal:
\r
2770 void CreatePiecesFromFont()
\r
2773 HDC hdc_window = NULL;
\r
2779 if( fontBitmapSquareSize < 0 ) {
\r
2780 /* Something went seriously wrong in the past: do not try to recreate fonts! */
\r
2784 if( appData.renderPiecesWithFont == NULL || appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {
\r
2785 fontBitmapSquareSize = -1;
\r
2789 if( fontBitmapSquareSize != squareSize ) {
\r
2790 hdc_window = GetDC( hwndMain );
\r
2791 hdc = CreateCompatibleDC( hdc_window );
\r
2793 if( hPieceFont != NULL ) {
\r
2794 DeleteObject( hPieceFont );
\r
2797 for( i=0; i<=(int)BlackKing; i++ ) {
\r
2798 hPieceMask[i] = NULL;
\r
2799 hPieceFace[i] = NULL;
\r
2805 if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {
\r
2806 fontHeight = appData.fontPieceSize;
\r
2809 fontHeight = (fontHeight * squareSize) / 100;
\r
2811 lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
\r
2813 lf.lfEscapement = 0;
\r
2814 lf.lfOrientation = 0;
\r
2815 lf.lfWeight = FW_NORMAL;
\r
2817 lf.lfUnderline = 0;
\r
2818 lf.lfStrikeOut = 0;
\r
2819 lf.lfCharSet = DEFAULT_CHARSET;
\r
2820 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
2821 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
2822 lf.lfQuality = PROOF_QUALITY;
\r
2823 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
\r
2824 strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );
\r
2825 lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';
\r
2827 hPieceFont = CreateFontIndirect( &lf );
\r
2829 if( hPieceFont == NULL ) {
\r
2830 fontBitmapSquareSize = -2;
\r
2833 /* Setup font-to-piece character table */
\r
2834 if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {
\r
2835 /* No (or wrong) global settings, try to detect the font */
\r
2836 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {
\r
2838 SetCharTable(pieceToFontChar, "phbrqkojntwl");
\r
2840 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {
\r
2841 /* DiagramTT* family */
\r
2842 SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");
\r
2844 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {
\r
2845 /* Fairy symbols */
\r
2846 SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
\r
2848 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {
\r
2849 /* Good Companion (Some characters get warped as literal :-( */
\r
2850 char s[] = "1cmWG0ñueOS¯®oYI23wgQU";
\r
2851 s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;
\r
2852 SetCharTable(pieceToFontChar, s);
\r
2855 /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */
\r
2856 SetCharTable(pieceToFontChar, "pnbrqkomvtwl");
\r
2860 /* Create bitmaps */
\r
2861 hfont_old = SelectObject( hdc, hPieceFont );
\r
2863 CreatePieceMaskFromFont( hdc_window, hdc, PM_WP );
\r
2864 CreatePieceMaskFromFont( hdc_window, hdc, PM_WN );
\r
2865 CreatePieceMaskFromFont( hdc_window, hdc, PM_WB );
\r
2866 CreatePieceMaskFromFont( hdc_window, hdc, PM_WR );
\r
2867 CreatePieceMaskFromFont( hdc_window, hdc, PM_WQ );
\r
2868 CreatePieceMaskFromFont( hdc_window, hdc, PM_WK );
\r
2869 CreatePieceMaskFromFont( hdc_window, hdc, PM_BP );
\r
2870 CreatePieceMaskFromFont( hdc_window, hdc, PM_BN );
\r
2871 CreatePieceMaskFromFont( hdc_window, hdc, PM_BB );
\r
2872 CreatePieceMaskFromFont( hdc_window, hdc, PM_BR );
\r
2873 CreatePieceMaskFromFont( hdc_window, hdc, PM_BQ );
\r
2874 CreatePieceMaskFromFont( hdc_window, hdc, PM_BK );
\r
2876 CreatePieceMaskFromFont( hdc_window, hdc, PM_WA );
\r
2877 CreatePieceMaskFromFont( hdc_window, hdc, PM_WC );
\r
2878 CreatePieceMaskFromFont( hdc_window, hdc, PM_WF );
\r
2879 CreatePieceMaskFromFont( hdc_window, hdc, PM_WH );
\r
2880 CreatePieceMaskFromFont( hdc_window, hdc, PM_WE );
\r
2881 CreatePieceMaskFromFont( hdc_window, hdc, PM_WW );
\r
2882 CreatePieceMaskFromFont( hdc_window, hdc, PM_WU );
\r
2883 CreatePieceMaskFromFont( hdc_window, hdc, PM_WO );
\r
2884 CreatePieceMaskFromFont( hdc_window, hdc, PM_WG );
\r
2885 CreatePieceMaskFromFont( hdc_window, hdc, PM_WM );
\r
2886 CreatePieceMaskFromFont( hdc_window, hdc, PM_WSG );
\r
2887 CreatePieceMaskFromFont( hdc_window, hdc, PM_WV );
\r
2888 CreatePieceMaskFromFont( hdc_window, hdc, PM_WAB );
\r
2889 CreatePieceMaskFromFont( hdc_window, hdc, PM_WD );
\r
2890 CreatePieceMaskFromFont( hdc_window, hdc, PM_WL );
\r
2891 CreatePieceMaskFromFont( hdc_window, hdc, PM_WS );
\r
2892 CreatePieceMaskFromFont( hdc_window, hdc, PM_BA );
\r
2893 CreatePieceMaskFromFont( hdc_window, hdc, PM_BC );
\r
2894 CreatePieceMaskFromFont( hdc_window, hdc, PM_BF );
\r
2895 CreatePieceMaskFromFont( hdc_window, hdc, PM_BH );
\r
2896 CreatePieceMaskFromFont( hdc_window, hdc, PM_BE );
\r
2897 CreatePieceMaskFromFont( hdc_window, hdc, PM_BW );
\r
2898 CreatePieceMaskFromFont( hdc_window, hdc, PM_BU );
\r
2899 CreatePieceMaskFromFont( hdc_window, hdc, PM_BO );
\r
2900 CreatePieceMaskFromFont( hdc_window, hdc, PM_BG );
\r
2901 CreatePieceMaskFromFont( hdc_window, hdc, PM_BM );
\r
2902 CreatePieceMaskFromFont( hdc_window, hdc, PM_BSG );
\r
2903 CreatePieceMaskFromFont( hdc_window, hdc, PM_BV );
\r
2904 CreatePieceMaskFromFont( hdc_window, hdc, PM_BAB );
\r
2905 CreatePieceMaskFromFont( hdc_window, hdc, PM_BD );
\r
2906 CreatePieceMaskFromFont( hdc_window, hdc, PM_BL );
\r
2907 CreatePieceMaskFromFont( hdc_window, hdc, PM_BS );
\r
2909 for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */
\r
2910 if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */
\r
2911 CreatePieceMaskFromFont( hdc_window, hdc, i );
\r
2913 SelectObject( hdc, hfont_old );
\r
2915 fontBitmapSquareSize = squareSize;
\r
2919 if( hdc != NULL ) {
\r
2923 if( hdc_window != NULL ) {
\r
2924 ReleaseDC( hwndMain, hdc_window );
\r
2929 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)
\r
2933 sprintf(name, "%s%d%s", piece, squareSize, suffix);
\r
2934 if (gameInfo.event &&
\r
2935 strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&
\r
2936 strcmp(name, "k80s") == 0) {
\r
2937 strcpy(name, "tim");
\r
2939 return LoadBitmap(hinst, name);
\r
2943 /* Insert a color into the program's logical palette
\r
2944 structure. This code assumes the given color is
\r
2945 the result of the RGB or PALETTERGB macro, and it
\r
2946 knows how those macros work (which is documented).
\r
2949 InsertInPalette(COLORREF color)
\r
2951 LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);
\r
2953 if (pLogPal->palNumEntries++ >= PALETTESIZE) {
\r
2954 DisplayFatalError("Too many colors", 0, 1);
\r
2955 pLogPal->palNumEntries--;
\r
2959 pe->peFlags = (char) 0;
\r
2960 pe->peRed = (char) (0xFF & color);
\r
2961 pe->peGreen = (char) (0xFF & (color >> 8));
\r
2962 pe->peBlue = (char) (0xFF & (color >> 16));
\r
2968 InitDrawingColors()
\r
2970 if (pLogPal == NULL) {
\r
2971 /* Allocate enough memory for a logical palette with
\r
2972 * PALETTESIZE entries and set the size and version fields
\r
2973 * of the logical palette structure.
\r
2975 pLogPal = (NPLOGPALETTE)
\r
2976 LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +
\r
2977 (sizeof(PALETTEENTRY) * (PALETTESIZE))));
\r
2978 pLogPal->palVersion = 0x300;
\r
2980 pLogPal->palNumEntries = 0;
\r
2982 InsertInPalette(lightSquareColor);
\r
2983 InsertInPalette(darkSquareColor);
\r
2984 InsertInPalette(whitePieceColor);
\r
2985 InsertInPalette(blackPieceColor);
\r
2986 InsertInPalette(highlightSquareColor);
\r
2987 InsertInPalette(premoveHighlightColor);
\r
2989 /* create a logical color palette according the information
\r
2990 * in the LOGPALETTE structure.
\r
2992 hPal = CreatePalette((LPLOGPALETTE) pLogPal);
\r
2994 lightSquareBrush = CreateSolidBrush(lightSquareColor);
\r
2995 blackSquareBrush = CreateSolidBrush(blackPieceColor);
\r
2996 darkSquareBrush = CreateSolidBrush(darkSquareColor);
\r
2997 whitePieceBrush = CreateSolidBrush(whitePieceColor);
\r
2998 blackPieceBrush = CreateSolidBrush(blackPieceColor);
\r
2999 iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
\r
3001 /* [AS] Force rendering of the font-based pieces */
\r
3002 if( fontBitmapSquareSize > 0 ) {
\r
3003 fontBitmapSquareSize = 0;
\r
3009 BoardWidth(int boardSize, int n)
\r
3010 { /* [HGM] argument n added to allow different width and height */
\r
3011 int lineGap = sizeInfo[boardSize].lineGap;
\r
3013 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3014 lineGap = appData.overrideLineGap;
\r
3017 return (n + 1) * lineGap +
\r
3018 n * sizeInfo[boardSize].squareSize;
\r
3021 /* Respond to board resize by dragging edge */
\r
3023 ResizeBoard(int newSizeX, int newSizeY, int flags)
\r
3025 BoardSize newSize = NUM_SIZES - 1;
\r
3026 static int recurse = 0;
\r
3027 if (IsIconic(hwndMain)) return;
\r
3028 if (recurse > 0) return;
\r
3030 while (newSize > 0) {
\r
3031 InitDrawingSizes(newSize+1000, 0); // [HGM] kludge to update sizeInfo without visible effects
\r
3032 if(newSizeX >= sizeInfo[newSize].cliWidth &&
\r
3033 newSizeY >= sizeInfo[newSize].cliHeight) break;
\r
3036 boardSize = newSize;
\r
3037 InitDrawingSizes(boardSize, flags);
\r
3044 InitDrawingSizes(BoardSize boardSize, int flags)
\r
3046 int i, boardWidth, boardHeight; /* [HGM] height treated separately */
\r
3047 ChessSquare piece;
\r
3048 static int oldBoardSize = -1, oldTinyLayout = 0;
\r
3050 SIZE clockSize, messageSize;
\r
3052 char buf[MSG_SIZ];
\r
3054 HMENU hmenu = GetMenu(hwndMain);
\r
3055 RECT crect, wrect;
\r
3057 LOGBRUSH logbrush;
\r
3059 int suppressVisibleEffects = 0; // [HGM] kludge to request updating sizeInfo only
\r
3060 if((int)boardSize >= 1000 ) { boardSize -= 1000; suppressVisibleEffects = 1; }
\r
3062 /* [HGM] call with -2 uses old size (for if nr of files, ranks changes) */
\r
3063 if(boardSize == (BoardSize)(-2) ) boardSize = oldBoardSize;
\r
3065 tinyLayout = sizeInfo[boardSize].tinyLayout;
\r
3066 smallLayout = sizeInfo[boardSize].smallLayout;
\r
3067 squareSize = sizeInfo[boardSize].squareSize;
\r
3068 lineGap = sizeInfo[boardSize].lineGap;
\r
3069 minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted */
\r
3071 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3072 lineGap = appData.overrideLineGap;
\r
3075 if (tinyLayout != oldTinyLayout) {
\r
3076 long style = GetWindowLong(hwndMain, GWL_STYLE);
\r
3078 style &= ~WS_SYSMENU;
\r
3079 InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize,
\r
3080 "&Minimize\tCtrl+F4");
\r
3082 style |= WS_SYSMENU;
\r
3083 RemoveMenu(hmenu, IDM_Minimize, MF_BYCOMMAND);
\r
3085 SetWindowLong(hwndMain, GWL_STYLE, style);
\r
3087 for (i=0; menuBarText[tinyLayout][i]; i++) {
\r
3088 ModifyMenu(hmenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP,
\r
3089 (UINT)GetSubMenu(hmenu, i), menuBarText[tinyLayout][i]);
\r
3091 DrawMenuBar(hwndMain);
\r
3094 boardWidth = BoardWidth(boardSize, BOARD_WIDTH);
\r
3095 boardHeight = BoardWidth(boardSize, BOARD_HEIGHT);
\r
3097 /* Get text area sizes */
\r
3098 hdc = GetDC(hwndMain);
\r
3099 if (appData.clockMode) {
\r
3100 sprintf(buf, "White: %s", TimeString(23*60*60*1000L));
\r
3102 sprintf(buf, "White");
\r
3104 oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);
\r
3105 GetTextExtentPoint(hdc, buf, strlen(buf), &clockSize);
\r
3106 SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);
\r
3107 str = "We only care about the height here";
\r
3108 GetTextExtentPoint(hdc, str, strlen(str), &messageSize);
\r
3109 SelectObject(hdc, oldFont);
\r
3110 ReleaseDC(hwndMain, hdc);
\r
3112 /* Compute where everything goes */
\r
3113 if(first.programLogo || second.programLogo) {
\r
3114 /* [HGM] logo: if either logo is on, reserve space for it */
\r
3115 logoHeight = 2*clockSize.cy;
\r
3116 leftLogoRect.left = OUTER_MARGIN;
\r
3117 leftLogoRect.right = leftLogoRect.left + 4*clockSize.cy;
\r
3118 leftLogoRect.top = OUTER_MARGIN;
\r
3119 leftLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3121 rightLogoRect.right = OUTER_MARGIN + boardWidth;
\r
3122 rightLogoRect.left = rightLogoRect.right - 4*clockSize.cy;
\r
3123 rightLogoRect.top = OUTER_MARGIN;
\r
3124 rightLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3127 blackRect.left = leftLogoRect.right;
\r
3128 blackRect.right = rightLogoRect.left;
\r
3129 blackRect.top = OUTER_MARGIN;
\r
3130 blackRect.bottom = blackRect.top + clockSize.cy;
\r
3132 whiteRect.left = blackRect.left ;
\r
3133 whiteRect.right = blackRect.right;
\r
3134 whiteRect.top = blackRect.bottom;
\r
3135 whiteRect.bottom = leftLogoRect.bottom;
\r
3137 whiteRect.left = OUTER_MARGIN;
\r
3138 whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2;
\r
3139 whiteRect.top = OUTER_MARGIN + logoHeight;
\r
3140 whiteRect.bottom = whiteRect.top + clockSize.cy;
\r
3142 blackRect.left = whiteRect.right + INNER_MARGIN;
\r
3143 blackRect.right = blackRect.left + boardWidth/2 - 1;
\r
3144 blackRect.top = whiteRect.top;
\r
3145 blackRect.bottom = whiteRect.bottom;
\r
3148 messageRect.left = OUTER_MARGIN + MESSAGE_LINE_LEFTMARGIN;
\r
3149 if (appData.showButtonBar) {
\r
3150 messageRect.right = OUTER_MARGIN + boardWidth // [HGM] logo: expressed independent of clock placement
\r
3151 - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN;
\r
3153 messageRect.right = OUTER_MARGIN + boardWidth;
\r
3155 messageRect.top = whiteRect.bottom + INNER_MARGIN;
\r
3156 messageRect.bottom = messageRect.top + messageSize.cy;
\r
3158 boardRect.left = OUTER_MARGIN;
\r
3159 boardRect.right = boardRect.left + boardWidth;
\r
3160 boardRect.top = messageRect.bottom + INNER_MARGIN;
\r
3161 boardRect.bottom = boardRect.top + boardHeight;
\r
3163 sizeInfo[boardSize].cliWidth = boardRect.right + OUTER_MARGIN;
\r
3164 sizeInfo[boardSize].cliHeight = boardRect.bottom + OUTER_MARGIN;
\r
3165 if(suppressVisibleEffects) return; // [HGM] when called for filling sizeInfo only
\r
3166 winWidth = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN;
\r
3167 winHeight = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) +
\r
3168 GetSystemMetrics(SM_CYCAPTION) + boardRect.bottom + OUTER_MARGIN;
\r
3169 GetWindowRect(hwndMain, &wrect);
\r
3170 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3171 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3172 /* compensate if menu bar wrapped */
\r
3173 GetClientRect(hwndMain, &crect);
\r
3174 offby = boardRect.bottom + OUTER_MARGIN - crect.bottom;
\r
3175 winHeight += offby;
\r
3177 case WMSZ_TOPLEFT:
\r
3178 SetWindowPos(hwndMain, NULL,
\r
3179 wrect.right - winWidth, wrect.bottom - winHeight,
\r
3180 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3183 case WMSZ_TOPRIGHT:
\r
3185 SetWindowPos(hwndMain, NULL,
\r
3186 wrect.left, wrect.bottom - winHeight,
\r
3187 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3190 case WMSZ_BOTTOMLEFT:
\r
3192 SetWindowPos(hwndMain, NULL,
\r
3193 wrect.right - winWidth, wrect.top,
\r
3194 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3197 case WMSZ_BOTTOMRIGHT:
\r
3201 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3202 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r