2 * WinBoard.c -- Windows NT front end to XBoard
\r
3 * $Id: winboard.c,v 2.3 2003/11/25 05:25:20 mann Exp $
\r
5 * Copyright 1991 by Digital Equipment Corporation, Maynard,
\r
6 * Massachusetts. Enhancements Copyright
\r
7 * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software
\r
10 * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,
\r
11 * which was written and is copyrighted by Wayne Christopher.
\r
13 * The following terms apply to Digital Equipment Corporation's copyright
\r
14 * interest in XBoard:
\r
15 * ------------------------------------------------------------------------
\r
16 * All Rights Reserved
\r
18 * Permission to use, copy, modify, and distribute this software and its
\r
19 * documentation for any purpose and without fee is hereby granted,
\r
20 * provided that the above copyright notice appear in all copies and that
\r
21 * both that copyright notice and this permission notice appear in
\r
22 * supporting documentation, and that the name of Digital not be
\r
23 * used in advertising or publicity pertaining to distribution of the
\r
24 * software without specific, written prior permission.
\r
26 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
\r
27 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
\r
28 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
\r
29 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
\r
30 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
\r
31 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
\r
33 * ------------------------------------------------------------------------
\r
35 * The following terms apply to the enhanced version of XBoard
\r
36 * distributed by the Free Software Foundation:
\r
37 * ------------------------------------------------------------------------
\r
39 * GNU XBoard is free software: you can redistribute it and/or modify
\r
40 * it under the terms of the GNU General Public License as published by
\r
41 * the Free Software Foundation, either version 3 of the License, or (at
\r
42 * your option) any later version.
\r
44 * GNU XBoard is distributed in the hope that it will be useful, but
\r
45 * WITHOUT ANY WARRANTY; without even the implied warranty of
\r
46 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
47 * General Public License for more details.
\r
49 * You should have received a copy of the GNU General Public License
\r
50 * along with this program. If not, see http://www.gnu.org/licenses/. *
\r
52 *------------------------------------------------------------------------
\r
53 ** See the file ChangeLog for a revision history. */
\r
57 #include <windows.h>
\r
58 #include <winuser.h>
\r
59 #include <winsock.h>
\r
60 #include <commctrl.h>
\r
66 #include <sys/stat.h>
\r
69 #include <commdlg.h>
\r
71 #include <richedit.h>
\r
72 #include <mmsystem.h>
\r
81 #include "winboard.h"
\r
82 #include "frontend.h"
\r
83 #include "backend.h"
\r
85 #include "wclipbrd.h"
\r
86 #include "wgamelist.h"
\r
87 #include "wedittags.h"
\r
88 #include "woptions.h"
\r
89 #include "wsockerr.h"
\r
90 #include "defaults.h"
\r
94 //void InitEngineUCI( const char * iniDir, ChessProgramState * cps );
\r
97 void mysrandom(unsigned int seed);
\r
99 extern int whiteFlag, blackFlag;
\r
100 Boolean flipClock = FALSE;
\r
102 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);
\r
103 VOID NewVariantPopup(HWND hwnd);
\r
104 int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,
\r
105 /*char*/int promoChar));
\r
106 void AnimateAtomicCapture(int fromX, int fromY, int toX, int toY, int nFrames);
\r
109 ChessSquare piece;
\r
110 POINT pos; /* window coordinates of current pos */
\r
111 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
112 POINT from; /* board coordinates of the piece's orig pos */
\r
113 POINT to; /* board coordinates of the piece's new pos */
\r
116 static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };
\r
119 POINT start; /* window coordinates of start pos */
\r
120 POINT pos; /* window coordinates of current pos */
\r
121 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
122 POINT from; /* board coordinates of the piece's orig pos */
\r
125 static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} };
\r
128 POINT sq[2]; /* board coordinates of from, to squares */
\r
131 static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} };
\r
132 static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };
\r
134 typedef struct { // [HGM] atomic
\r
135 int fromX, fromY, toX, toY, radius;
\r
138 static ExplodeInfo explodeInfo;
\r
140 /* Window class names */
\r
141 char szAppName[] = "WinBoard";
\r
142 char szConsoleName[] = "WBConsole";
\r
144 /* Title bar text */
\r
145 char szTitle[] = "WinBoard";
\r
146 char szConsoleTitle[] = "ICS Interaction";
\r
149 char *settingsFileName;
\r
150 BOOLEAN saveSettingsOnExit;
\r
151 char installDir[MSG_SIZ];
\r
153 BoardSize boardSize;
\r
154 BOOLEAN chessProgram;
\r
155 static int boardX, boardY;
\r
156 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
\r
157 static int squareSize, lineGap, minorSize;
\r
158 static int winWidth, winHeight;
\r
159 static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo
\r
160 static int logoHeight = 0;
\r
161 static char messageText[MESSAGE_TEXT_MAX];
\r
162 static int clockTimerEvent = 0;
\r
163 static int loadGameTimerEvent = 0;
\r
164 static int analysisTimerEvent = 0;
\r
165 static DelayedEventCallback delayedTimerCallback;
\r
166 static int delayedTimerEvent = 0;
\r
167 static int buttonCount = 2;
\r
168 char *icsTextMenuString;
\r
170 char *firstChessProgramNames;
\r
171 char *secondChessProgramNames;
\r
173 #define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */
\r
175 #define PALETTESIZE 256
\r
177 HINSTANCE hInst; /* current instance */
\r
178 HWND hwndMain = NULL; /* root window*/
\r
179 HWND hwndConsole = NULL;
\r
180 BOOLEAN alwaysOnTop = FALSE;
\r
182 COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
\r
183 blackPieceColor, highlightSquareColor, premoveHighlightColor;
\r
185 ColorClass currentColorClass;
\r
187 HWND hCommPort = NULL; /* currently open comm port */
\r
188 static HWND hwndPause; /* pause button */
\r
189 static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */
\r
190 static HBRUSH lightSquareBrush, darkSquareBrush,
\r
191 blackSquareBrush, /* [HGM] for band between board and holdings */
\r
192 explodeBrush, /* [HGM] atomic */
\r
193 whitePieceBrush, blackPieceBrush, iconBkgndBrush /*, outlineBrush*/;
\r
194 static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];
\r
195 static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];
\r
196 static HPEN gridPen = NULL;
\r
197 static HPEN highlightPen = NULL;
\r
198 static HPEN premovePen = NULL;
\r
199 static NPLOGPALETTE pLogPal;
\r
200 static BOOL paletteChanged = FALSE;
\r
201 static HICON iconWhite, iconBlack, iconCurrent;
\r
202 static int doingSizing = FALSE;
\r
203 static int lastSizing = 0;
\r
204 static int prevStderrPort;
\r
205 static HBITMAP userLogo;
\r
207 /* [AS] Support for background textures */
\r
208 #define BACK_TEXTURE_MODE_DISABLED 0
\r
209 #define BACK_TEXTURE_MODE_PLAIN 1
\r
210 #define BACK_TEXTURE_MODE_FULL_RANDOM 2
\r
212 static HBITMAP liteBackTexture = NULL;
\r
213 static HBITMAP darkBackTexture = NULL;
\r
214 static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
215 static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
216 static int backTextureSquareSize = 0;
\r
217 static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_SIZE][BOARD_SIZE];
\r
219 #if __GNUC__ && !defined(_winmajor)
\r
220 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */
\r
222 #define oldDialog (_winmajor < 4)
\r
225 char *defaultTextAttribs[] =
\r
227 COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,
\r
228 COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,
\r
238 int cliWidth, cliHeight;
\r
241 SizeInfo sizeInfo[] =
\r
243 { "tiny", 21, 0, 1, 1, 0, 0 },
\r
244 { "teeny", 25, 1, 1, 1, 0, 0 },
\r
245 { "dinky", 29, 1, 1, 1, 0, 0 },
\r
246 { "petite", 33, 1, 1, 1, 0, 0 },
\r
247 { "slim", 37, 2, 1, 0, 0, 0 },
\r
248 { "small", 40, 2, 1, 0, 0, 0 },
\r
249 { "mediocre", 45, 2, 1, 0, 0, 0 },
\r
250 { "middling", 49, 2, 0, 0, 0, 0 },
\r
251 { "average", 54, 2, 0, 0, 0, 0 },
\r
252 { "moderate", 58, 3, 0, 0, 0, 0 },
\r
253 { "medium", 64, 3, 0, 0, 0, 0 },
\r
254 { "bulky", 72, 3, 0, 0, 0, 0 },
\r
255 { "large", 80, 3, 0, 0, 0, 0 },
\r
256 { "big", 87, 3, 0, 0, 0, 0 },
\r
257 { "huge", 95, 3, 0, 0, 0, 0 },
\r
258 { "giant", 108, 3, 0, 0, 0, 0 },
\r
259 { "colossal", 116, 4, 0, 0, 0, 0 },
\r
260 { "titanic", 129, 4, 0, 0, 0, 0 },
\r
261 { NULL, 0, 0, 0, 0, 0, 0 }
\r
264 #define MF(x) {x, {{0,}, 0. }, {0, }, 0}
\r
265 MyFont fontRec[NUM_SIZES][NUM_FONTS] =
\r
267 { 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
268 { 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
269 { 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
270 { 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
271 { 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
272 { 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
273 { 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
274 { 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
275 { 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
276 { 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
277 { 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
278 { 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
279 { 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
280 { 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
281 { 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
282 { 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
283 { 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
284 { 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
287 MyFont *font[NUM_SIZES][NUM_FONTS];
\r
296 #define BUTTON_WIDTH (tinyLayout ? 16 : 32)
\r
297 #define N_BUTTONS 5
\r
299 MyButtonDesc buttonDesc[N_BUTTONS] =
\r
301 {"<<", IDM_ToStart, NULL, NULL},
\r
302 {"<", IDM_Backward, NULL, NULL},
\r
303 {"P", IDM_Pause, NULL, NULL},
\r
304 {">", IDM_Forward, NULL, NULL},
\r
305 {">>", IDM_ToEnd, NULL, NULL},
\r
308 int tinyLayout = 0, smallLayout = 0;
\r
309 #define MENU_BAR_ITEMS 6
\r
310 char *menuBarText[2][MENU_BAR_ITEMS+1] = {
\r
311 { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },
\r
312 { "&F", "&M", "&A", "&S", "&O", "&H", NULL },
\r
316 MySound sounds[(int)NSoundClasses];
\r
317 MyTextAttribs textAttribs[(int)NColorClasses];
\r
319 MyColorizeAttribs colorizeAttribs[] = {
\r
320 { (COLORREF)0, 0, "Shout Text" },
\r
321 { (COLORREF)0, 0, "SShout/CShout" },
\r
322 { (COLORREF)0, 0, "Channel 1 Text" },
\r
323 { (COLORREF)0, 0, "Channel Text" },
\r
324 { (COLORREF)0, 0, "Kibitz Text" },
\r
325 { (COLORREF)0, 0, "Tell Text" },
\r
326 { (COLORREF)0, 0, "Challenge Text" },
\r
327 { (COLORREF)0, 0, "Request Text" },
\r
328 { (COLORREF)0, 0, "Seek Text" },
\r
329 { (COLORREF)0, 0, "Normal Text" },
\r
330 { (COLORREF)0, 0, "None" }
\r
335 static char *commentTitle;
\r
336 static char *commentText;
\r
337 static int commentIndex;
\r
338 static Boolean editComment = FALSE;
\r
339 HWND commentDialog = NULL;
\r
340 BOOLEAN commentDialogUp = FALSE;
\r
341 static int commentX, commentY, commentH, commentW;
\r
343 static char *analysisTitle;
\r
344 static char *analysisText;
\r
345 HWND analysisDialog = NULL;
\r
346 BOOLEAN analysisDialogUp = FALSE;
\r
347 static int analysisX, analysisY, analysisH, analysisW;
\r
349 char errorTitle[MSG_SIZ];
\r
350 char errorMessage[2*MSG_SIZ];
\r
351 HWND errorDialog = NULL;
\r
352 BOOLEAN moveErrorMessageUp = FALSE;
\r
353 BOOLEAN consoleEcho = TRUE;
\r
354 CHARFORMAT consoleCF;
\r
355 COLORREF consoleBackgroundColor;
\r
357 char *programVersion;
\r
363 typedef int CPKind;
\r
372 SOCKET sock2; /* stderr socket for OpenRcmd */
\r
375 #define INPUT_SOURCE_BUF_SIZE 4096
\r
377 typedef struct _InputSource {
\r
384 char buf[INPUT_SOURCE_BUF_SIZE];
\r
388 InputCallback func;
\r
389 struct _InputSource *second; /* for stderr thread on CPRcmd */
\r
393 InputSource *consoleInputSource;
\r
398 VOID ConsoleOutput(char* data, int length, int forceVisible);
\r
399 VOID ConsoleCreate();
\r
401 ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
402 VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
\r
403 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
\r
404 VOID ParseCommSettings(char *arg, DCB *dcb);
\r
406 StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
407 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
\r
408 void ParseIcsTextMenu(char *icsTextMenuString);
\r
409 VOID PopUpMoveDialog(char firstchar);
\r
410 VOID PopUpNameDialog(char firstchar);
\r
411 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
\r
415 int GameListOptions();
\r
417 HWND moveHistoryDialog = NULL;
\r
418 BOOLEAN moveHistoryDialogUp = FALSE;
\r
420 WindowPlacement wpMoveHistory;
\r
422 HWND evalGraphDialog = NULL;
\r
423 BOOLEAN evalGraphDialogUp = FALSE;
\r
425 WindowPlacement wpEvalGraph;
\r
427 HWND engineOutputDialog = NULL;
\r
428 BOOLEAN engineOutputDialogUp = FALSE;
\r
430 WindowPlacement wpEngineOutput;
\r
431 WindowPlacement wpGameList;
\r
432 WindowPlacement wpConsole;
\r
434 VOID MoveHistoryPopUp();
\r
435 VOID MoveHistoryPopDown();
\r
436 VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
437 BOOL MoveHistoryIsUp();
\r
439 VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
440 VOID EvalGraphPopUp();
\r
441 VOID EvalGraphPopDown();
\r
442 BOOL EvalGraphIsUp();
\r
444 VOID EngineOutputPopUp();
\r
445 VOID EngineOutputPopDown();
\r
446 BOOL EngineOutputIsUp();
\r
447 VOID EngineOutputUpdate( FrontEndProgramStats * stats );
\r
449 VOID GothicPopUp(char *title, VariantClass variant);
\r
451 * Setting "frozen" should disable all user input other than deleting
\r
452 * the window. We do this while engines are initializing themselves.
\r
454 static int frozen = 0;
\r
455 static int oldMenuItemState[MENU_BAR_ITEMS];
\r
461 if (frozen) return;
\r
463 hmenu = GetMenu(hwndMain);
\r
464 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
465 oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
\r
467 DrawMenuBar(hwndMain);
\r
470 /* Undo a FreezeUI */
\r
476 if (!frozen) return;
\r
478 hmenu = GetMenu(hwndMain);
\r
479 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
480 EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
\r
482 DrawMenuBar(hwndMain);
\r
485 /*---------------------------------------------------------------------------*\
\r
489 \*---------------------------------------------------------------------------*/
\r
492 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
\r
493 LPSTR lpCmdLine, int nCmdShow)
\r
496 HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
\r
497 // INITCOMMONCONTROLSEX ex;
\r
501 LoadLibrary("RICHED32.DLL");
\r
502 consoleCF.cbSize = sizeof(CHARFORMAT);
\r
504 if (!InitApplication(hInstance)) {
\r
507 if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
\r
511 // InitCommonControlsEx(&ex);
\r
512 InitCommonControls();
\r
514 hAccelMain = LoadAccelerators (hInstance, szAppName);
\r
515 hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
\r
516 hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
\r
518 /* Acquire and dispatch messages until a WM_QUIT message is received. */
\r
520 while (GetMessage(&msg, /* message structure */
\r
521 NULL, /* handle of window receiving the message */
\r
522 0, /* lowest message to examine */
\r
523 0)) /* highest message to examine */
\r
525 if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
\r
526 !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
\r
527 !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
\r
528 !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
\r
529 !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
\r
530 !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
\r
531 !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
\r
532 !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) &&
\r
533 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
\r
534 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
\r
535 TranslateMessage(&msg); /* Translates virtual key codes */
\r
536 DispatchMessage(&msg); /* Dispatches message to window */
\r
541 return (msg.wParam); /* Returns the value from PostQuitMessage */
\r
544 /*---------------------------------------------------------------------------*\
\r
546 * Initialization functions
\r
548 \*---------------------------------------------------------------------------*/
\r
552 { // update user logo if necessary
\r
553 static char oldUserName[MSG_SIZ], *curName;
\r
555 if(appData.autoLogo) {
\r
556 curName = UserName();
\r
557 if(strcmp(curName, oldUserName)) {
\r
558 sprintf(oldUserName, "logos\\%s.bmp", curName);
\r
559 userLogo = LoadImage( 0, oldUserName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
560 strcpy(oldUserName, curName);
\r
566 InitApplication(HINSTANCE hInstance)
\r
570 /* Fill in window class structure with parameters that describe the */
\r
573 wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
\r
574 wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
\r
575 wc.cbClsExtra = 0; /* No per-class extra data. */
\r
576 wc.cbWndExtra = 0; /* No per-window extra data. */
\r
577 wc.hInstance = hInstance; /* Owner of this class */
\r
578 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
579 wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
\r
580 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
\r
581 wc.lpszMenuName = szAppName; /* Menu name from .RC */
\r
582 wc.lpszClassName = szAppName; /* Name to register as */
\r
584 /* Register the window class and return success/failure code. */
\r
585 if (!RegisterClass(&wc)) return FALSE;
\r
587 wc.style = CS_HREDRAW | CS_VREDRAW;
\r
588 wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
\r
590 wc.cbWndExtra = DLGWINDOWEXTRA;
\r
591 wc.hInstance = hInstance;
\r
592 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
593 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
\r
594 wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
\r
595 wc.lpszMenuName = NULL;
\r
596 wc.lpszClassName = szConsoleName;
\r
598 if (!RegisterClass(&wc)) return FALSE;
\r
603 /* Set by InitInstance, used by EnsureOnScreen */
\r
604 int screenHeight, screenWidth;
\r
607 EnsureOnScreen(int *x, int *y, int minX, int minY)
\r
609 // int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
\r
610 /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
\r
611 if (*x > screenWidth - 32) *x = 0;
\r
612 if (*y > screenHeight - 32) *y = 0;
\r
613 if (*x < minX) *x = minX;
\r
614 if (*y < minY) *y = minY;
\r
618 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
\r
620 HWND hwnd; /* Main window handle. */
\r
622 WINDOWPLACEMENT wp;
\r
625 hInst = hInstance; /* Store instance handle in our global variable */
\r
627 if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
\r
628 *filepart = NULLCHAR;
\r
630 GetCurrentDirectory(MSG_SIZ, installDir);
\r
632 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise
\r
633 screenWidth = screenHeight = 1000; // [HGM] placement: kludge to allow calling EnsureOnScreen from InitAppData
\r
634 InitAppData(lpCmdLine); /* Get run-time parameters */
\r
635 if (appData.debugMode) {
\r
636 debugFP = fopen(appData.nameOfDebugFile, "w");
\r
637 setbuf(debugFP, NULL);
\r
642 // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()
\r
643 // InitEngineUCI( installDir, &second );
\r
645 /* Create a main window for this application instance. */
\r
646 hwnd = CreateWindow(szAppName, szTitle,
\r
647 (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
\r
648 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
\r
649 NULL, NULL, hInstance, NULL);
\r
652 /* If window could not be created, return "failure" */
\r
657 /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */
\r
658 if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {
\r
659 first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
661 if (first.programLogo == NULL && appData.debugMode) {
\r
662 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );
\r
664 } else if(appData.autoLogo) {
\r
665 if(appData.firstDirectory && appData.firstDirectory[0]) {
\r
667 sprintf(buf, "%s/logo.bmp", appData.firstDirectory);
\r
668 first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
672 if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {
\r
673 second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
675 if (second.programLogo == NULL && appData.debugMode) {
\r
676 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );
\r
678 } else if(appData.autoLogo) {
\r
680 if(appData.icsActive) { // [HGM] logo: in ICS mode second can be used for ICS
\r
681 sprintf(buf, "logos\\%s.bmp", appData.icsHost);
\r
682 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
684 if(appData.secondDirectory && appData.secondDirectory[0]) {
\r
685 sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);
\r
686 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
692 iconWhite = LoadIcon(hInstance, "icon_white");
\r
693 iconBlack = LoadIcon(hInstance, "icon_black");
\r
694 iconCurrent = iconWhite;
\r
695 InitDrawingColors();
\r
696 screenHeight = GetSystemMetrics(SM_CYSCREEN);
\r
697 screenWidth = GetSystemMetrics(SM_CXSCREEN);
\r
698 for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
\r
699 /* Compute window size for each board size, and use the largest
\r
700 size that fits on this screen as the default. */
\r
701 InitDrawingSizes((BoardSize)(ibs+1000), 0);
\r
702 if (boardSize == (BoardSize)-1 &&
\r
703 winHeight <= screenHeight
\r
704 - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10
\r
705 && winWidth <= screenWidth) {
\r
706 boardSize = (BoardSize)ibs;
\r
710 InitDrawingSizes(boardSize, 0);
\r
712 buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
\r
714 /* [AS] Load textures if specified */
\r
715 ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );
\r
717 if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {
\r
718 liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
719 liteBackTextureMode = appData.liteBackTextureMode;
\r
721 if (liteBackTexture == NULL && appData.debugMode) {
\r
722 fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );
\r
726 if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {
\r
727 darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
728 darkBackTextureMode = appData.darkBackTextureMode;
\r
730 if (darkBackTexture == NULL && appData.debugMode) {
\r
731 fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );
\r
735 mysrandom( (unsigned) time(NULL) );
\r
737 /* [AS] Restore layout */
\r
738 if( wpMoveHistory.visible ) {
\r
739 MoveHistoryPopUp();
\r
742 if( wpEvalGraph.visible ) {
\r
746 if( wpEngineOutput.visible ) {
\r
747 EngineOutputPopUp();
\r
752 /* Make the window visible; update its client area; and return "success" */
\r
753 EnsureOnScreen(&boardX, &boardY, minX, minY);
\r
754 wp.length = sizeof(WINDOWPLACEMENT);
\r
756 wp.showCmd = nCmdShow;
\r
757 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
\r
758 wp.rcNormalPosition.left = boardX;
\r
759 wp.rcNormalPosition.right = boardX + winWidth;
\r
760 wp.rcNormalPosition.top = boardY;
\r
761 wp.rcNormalPosition.bottom = boardY + winHeight;
\r
762 SetWindowPlacement(hwndMain, &wp);
\r
764 SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
765 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
769 SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
770 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
772 ShowWindow(hwndConsole, nCmdShow);
\r
774 UpdateWindow(hwnd);
\r
782 ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
\r
783 ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
\r
784 ArgSettingsFilename,
\r
785 ArgX, ArgY, ArgZ // [HGM] placement: for window-placement options stored relative to main window
\r
793 String *pString; // ArgString
\r
794 int *pInt; // ArgInt
\r
795 float *pFloat; // ArgFloat
\r
796 Boolean *pBoolean; // ArgBoolean
\r
797 COLORREF *pColor; // ArgColor
\r
798 ColorClass cc; // ArgAttribs
\r
799 String *pFilename; // ArgFilename
\r
800 BoardSize *pBoardSize; // ArgBoardSize
\r
801 int whichFont; // ArgFont
\r
802 DCB *pDCB; // ArgCommSettings
\r
803 String *pFilename; // ArgSettingsFilename
\r
811 ArgDescriptor argDescriptors[] = {
\r
812 /* positional arguments */
\r
813 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
814 { "", ArgNone, NULL },
\r
815 /* keyword arguments */
\r
816 { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },
\r
817 { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },
\r
818 { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },
\r
819 { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },
\r
820 { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },
\r
821 { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },
\r
822 { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },
\r
823 { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },
\r
824 { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },
\r
825 { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },
\r
826 { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },
\r
827 { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },
\r
828 { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },
\r
829 { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },
\r
830 { "initString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
831 { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
832 { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },
\r
833 { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,
\r
835 { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,
\r
837 { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,
\r
839 { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },
\r
840 { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,
\r
842 { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },
\r
843 { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
844 { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
845 { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
846 { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
847 { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },
\r
848 { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },
\r
849 { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
850 { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
851 { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
852 { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
853 { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
854 { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
855 { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
856 { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
857 { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
858 { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
859 /*!!bitmapDirectory?*/
\r
860 { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
861 { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
862 { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
863 { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
864 { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },
\r
865 { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },
\r
866 { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },
\r
867 { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },
\r
868 { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },
\r
869 { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },
\r
870 { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },
\r
871 { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },
\r
872 { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
873 { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
874 { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
875 { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
876 { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
877 { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
878 { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
879 { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
880 { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
881 { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
882 { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
883 { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
884 { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },
\r
885 { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },
\r
886 { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
887 { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
888 { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },
\r
889 { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },
\r
890 { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },
\r
891 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
892 { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
893 { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
894 { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
895 { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },
\r
896 { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },
\r
897 { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },
\r
898 { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },
\r
899 { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
900 { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
901 { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
902 { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
903 { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
904 { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
905 { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
906 { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
907 { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },
\r
908 { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },
\r
909 { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
910 { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
911 { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
912 { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
913 { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },
\r
914 { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },
\r
915 { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
916 { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
917 { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },
\r
918 { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },
\r
919 { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
920 { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
921 { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },
\r
922 { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },
\r
923 { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
924 { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
925 { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
926 { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
927 { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
928 { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
929 { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },
\r
930 { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },
\r
931 { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
932 { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
933 { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },
\r
934 { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },
\r
935 { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
936 { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
937 { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },
\r
938 { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },
\r
939 { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
940 { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
941 { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },
\r
942 { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },
\r
943 { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
944 { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
945 { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },
\r
946 { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },
\r
947 { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
948 { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
949 { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },
\r
950 { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
951 { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
952 { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
953 { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors,
\r
954 FALSE }, /* only so that old WinBoard.ini files from betas can be read */
\r
955 { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },
\r
956 { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },
\r
957 { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },
\r
958 { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },
\r
959 { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },
\r
960 { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },
\r
961 { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE }, /* [AS] */
\r
962 { "boardSize", ArgBoardSize, (LPVOID) &boardSize,
\r
963 TRUE }, /* must come after all fonts */
\r
964 { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },
\r
965 { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,
\r
966 FALSE }, /* historical; kept only so old winboard.ini files will parse */
\r
967 { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },
\r
968 { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },
\r
969 { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
970 { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
971 { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },
\r
972 { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },
\r
973 { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
974 { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
975 { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },
\r
976 { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },
\r
977 { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
978 { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
979 { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },
\r
980 { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },
\r
981 { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
982 { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
983 { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },
\r
984 { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },
\r
985 { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
986 { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
987 { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },
\r
988 { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },
\r
989 { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
990 { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
991 { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },
\r
992 { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
993 { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
994 { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
996 { "cmailGameName", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
997 { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
999 { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },
\r
1000 { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1001 { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1002 { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1003 { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },
\r
1004 { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1005 { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1006 { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1007 { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },
\r
1008 { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },
\r
1009 { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
1010 { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
1011 { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },
\r
1012 { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },
\r
1013 { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
1014 { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
1015 { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },
\r
1016 { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },
\r
1017 { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
1018 { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
1019 { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },
\r
1020 { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },
\r
1021 { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
1022 { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
1023 { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },
\r
1024 { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },
\r
1025 { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
1026 { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
1027 { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },
\r
1028 { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },
\r
1029 { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },
\r
1030 { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1031 { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1032 { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },
\r
1033 { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},
\r
1034 { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},
\r
1035 { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1036 { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1037 { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},
\r
1038 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1039 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1040 { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },
\r
1041 { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1042 { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1043 { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },
\r
1044 { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },
\r
1045 { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1046 { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1047 { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },
\r
1048 { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },
\r
1049 { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },
\r
1050 { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1051 { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1052 { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },
\r
1053 { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },
\r
1054 { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1055 { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1056 { "highlightLastMove", ArgBoolean,
\r
1057 (LPVOID) &appData.highlightLastMove, TRUE },
\r
1058 { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1059 { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1060 { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1061 { "highlightDragging", ArgBoolean,
\r
1062 (LPVOID) &appData.highlightDragging, TRUE },
\r
1063 { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },
\r
1064 { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1065 { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1066 { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },
\r
1067 { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },
\r
1068 { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1069 { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1070 { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },
\r
1071 { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },
\r
1072 { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },
\r
1073 { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },
\r
1074 { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },
\r
1075 { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },
\r
1076 { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },
\r
1077 { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },
\r
1078 { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },
\r
1079 { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },
\r
1080 { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },
\r
1081 { "soundShout", ArgFilename,
\r
1082 (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },
\r
1083 { "soundSShout", ArgFilename,
\r
1084 (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },
\r
1085 { "soundChannel1", ArgFilename,
\r
1086 (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },
\r
1087 { "soundChannel", ArgFilename,
\r
1088 (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },
\r
1089 { "soundKibitz", ArgFilename,
\r
1090 (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },
\r
1091 { "soundTell", ArgFilename,
\r
1092 (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },
\r
1093 { "soundChallenge", ArgFilename,
\r
1094 (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },
\r
1095 { "soundRequest", ArgFilename,
\r
1096 (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },
\r
1097 { "soundSeek", ArgFilename,
\r
1098 (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },
\r
1099 { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },
\r
1100 { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },
\r
1101 { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },
\r
1102 { "soundIcsLoss", ArgFilename,
\r
1103 (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },
\r
1104 { "soundIcsDraw", ArgFilename,
\r
1105 (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },
\r
1106 { "soundIcsUnfinished", ArgFilename,
\r
1107 (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},
\r
1108 { "soundIcsAlarm", ArgFilename,
\r
1109 (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },
\r
1110 { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },
\r
1111 { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },
\r
1112 { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1113 { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1114 { "reuseChessPrograms", ArgBoolean,
\r
1115 (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */
\r
1116 { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },
\r
1117 { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },
\r
1118 { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1119 { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1120 { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },
\r
1121 { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1122 { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1123 { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },
\r
1124 { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },
\r
1125 { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },
\r
1126 { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1127 { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1128 { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },
\r
1129 { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },
\r
1130 { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,
\r
1132 { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,
\r
1134 { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1135 { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1136 { "variant", ArgString, (LPVOID) &appData.variant, FALSE },
\r
1137 { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion, FALSE },
\r
1138 { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,FALSE },
\r
1139 { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },
\r
1140 { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },
\r
1141 { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1142 { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1143 /* [AS] New features */
\r
1144 { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE },
\r
1145 { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE },
\r
1146 { "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE },
\r
1147 { "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE },
\r
1148 { "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE },
\r
1149 { "darkBackTextureFile", ArgString, (LPVOID) &appData.darkBackTextureFile, TRUE },
\r
1150 { "liteBackTextureMode", ArgInt, (LPVOID) &appData.liteBackTextureMode, TRUE },
\r
1151 { "darkBackTextureMode", ArgInt, (LPVOID) &appData.darkBackTextureMode, TRUE },
\r
1152 { "renderPiecesWithFont", ArgString, (LPVOID) &appData.renderPiecesWithFont, TRUE },
\r
1153 { "fontPieceToCharTable", ArgString, (LPVOID) &appData.fontToPieceTable, TRUE },
\r
1154 { "fontPieceBackColorWhite", ArgColor, (LPVOID) &appData.fontBackColorWhite, TRUE },
\r
1155 { "fontPieceForeColorWhite", ArgColor, (LPVOID) &appData.fontForeColorWhite, TRUE },
\r
1156 { "fontPieceBackColorBlack", ArgColor, (LPVOID) &appData.fontBackColorBlack, TRUE },
\r
1157 { "fontPieceForeColorBlack", ArgColor, (LPVOID) &appData.fontForeColorBlack, TRUE },
\r
1158 { "fontPieceSize", ArgInt, (LPVOID) &appData.fontPieceSize, TRUE },
\r
1159 { "overrideLineGap", ArgInt, (LPVOID) &appData.overrideLineGap, TRUE },
\r
1160 { "adjudicateLossThreshold", ArgInt, (LPVOID) &appData.adjudicateLossThreshold, TRUE },
\r
1161 { "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE },
\r
1162 { "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE },
\r
1163 { "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1164 { "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1165 { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },
\r
1166 { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE },
\r
1167 { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE },
\r
1168 { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE },
\r
1169 { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE },
\r
1170 { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE },
\r
1171 { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE },
\r
1172 { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE },
\r
1173 { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE },
\r
1174 { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE },
\r
1175 { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE },
\r
1176 { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE },
\r
1177 { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE },
\r
1178 { "firstIsUCI", ArgBoolean, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1179 { "fUCI", ArgTrue, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1180 { "secondIsUCI", ArgBoolean, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1181 { "sUCI", ArgTrue, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1182 { "firstHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1183 { "fNoOwnBookUCI", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1184 { "firstXBook", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1185 { "secondHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1186 { "sNoOwnBookUCI", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1187 { "secondXBook", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1188 { "polyglotDir", ArgFilename, (LPVOID) &appData.polyglotDir, TRUE },
\r
1189 { "usePolyglotBook", ArgBoolean, (LPVOID) &appData.usePolyglotBook, TRUE },
\r
1190 { "polyglotBook", ArgFilename, (LPVOID) &appData.polyglotBook, TRUE },
\r
1191 { "defaultHashSize", ArgInt, (LPVOID) &appData.defaultHashSize, TRUE },
\r
1192 { "defaultCacheSizeEGTB", ArgInt, (LPVOID) &appData.defaultCacheSizeEGTB, TRUE },
\r
1193 { "defaultPathEGTB", ArgFilename, (LPVOID) &appData.defaultPathEGTB, TRUE },
\r
1195 /* [HGM] board-size, adjudication and misc. options */
\r
1196 { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE },
\r
1197 { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE },
\r
1198 { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE },
\r
1199 { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE },
\r
1200 { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE },
\r
1201 { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE },
\r
1202 { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE },
\r
1203 { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE },
\r
1204 { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE },
\r
1205 { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE },
\r
1206 { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE },
\r
1207 { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE },
\r
1208 { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE },
\r
1209 { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE },
\r
1210 { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE },
\r
1211 { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE },
\r
1212 { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE },
\r
1213 { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE },
\r
1214 { "userName", ArgString, (LPVOID) &appData.userName, FALSE },
\r
1215 { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE },
\r
1216 { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE },
\r
1217 { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE },
\r
1218 { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE },
\r
1219 { "niceEngines", ArgInt, (LPVOID) &appData.niceEngines, TRUE },
\r
1220 { "firstLogo", ArgFilename, (LPVOID) &appData.firstLogo, FALSE },
\r
1221 { "secondLogo", ArgFilename, (LPVOID) &appData.secondLogo, FALSE },
\r
1222 { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE },
\r
1223 { "firstOptions", ArgString, (LPVOID) &appData.firstOptions, FALSE },
\r
1224 { "secondOptions", ArgString, (LPVOID) &appData.secondOptions, FALSE },
\r
1225 { "firstNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride1, FALSE },
\r
1226 { "secondNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride2, FALSE },
\r
1229 { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },
\r
1230 { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },
\r
1231 { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1232 { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1233 { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },
\r
1234 { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },
\r
1235 { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1236 { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1237 { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },
\r
1238 { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },
\r
1239 { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },
\r
1240 { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE },
\r
1241 { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,
\r
1243 { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE },
\r
1244 { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE },
\r
1245 { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE },
\r
1246 { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1247 { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1248 { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE },
\r
1249 { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,
\r
1251 { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1252 { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1253 { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1254 { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE },
\r
1255 { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE },
\r
1256 { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1257 { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1258 { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1259 { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1260 { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE },
\r
1261 { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE },
\r
1262 { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1263 { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1264 { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },
\r
1265 { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },
\r
1266 { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },
\r
1267 { "zippyShortGame", ArgInt, (LPVOID)&appData.zippyShortGame, FALSE },
\r
1268 /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */
\r
1269 { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },
\r
1271 /* [HGM] options for broadcasting and time odds */
\r
1272 { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },
\r
1273 { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },
\r
1274 { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },
\r
1275 { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },
\r
1276 { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },
\r
1277 { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },
\r
1278 { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },
\r
1279 { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },
\r
1280 { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },
\r
1281 { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },
\r
1282 { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE },
\r
1284 // [HGM] placement: put all window layouts last in ini file, but man X,Y before all others
\r
1285 { "minX", ArgZ, (LPVOID) &minX, FALSE }, // [HGM] placement: to make suer auxialary windows can be placed
\r
1286 { "minY", ArgZ, (LPVOID) &minY, FALSE },
\r
1287 { "winWidth", ArgInt, (LPVOID) &winWidth, TRUE }, // [HGM] placement: dummies to remember right & bottom
\r
1288 { "winHeight", ArgInt, (LPVOID) &winHeight, TRUE }, // for attaching auxiliary windows to them
\r
1289 { "x", ArgInt, (LPVOID) &boardX, TRUE },
\r
1290 { "y", ArgInt, (LPVOID) &boardY, TRUE },
\r
1291 { "icsX", ArgX, (LPVOID) &wpConsole.x, TRUE },
\r
1292 { "icsY", ArgY, (LPVOID) &wpConsole.y, TRUE },
\r
1293 { "icsW", ArgInt, (LPVOID) &wpConsole.width, TRUE },
\r
1294 { "icsH", ArgInt, (LPVOID) &wpConsole.height, TRUE },
\r
1295 { "analysisX", ArgX, (LPVOID) &analysisX, FALSE }, // [HGM] placement: analysis window no longer exists
\r
1296 { "analysisY", ArgY, (LPVOID) &analysisY, FALSE }, // provided for compatibility with old ini files
\r
1297 { "analysisW", ArgInt, (LPVOID) &analysisW, FALSE },
\r
1298 { "analysisH", ArgInt, (LPVOID) &analysisH, FALSE },
\r
1299 { "commentX", ArgX, (LPVOID) &commentX, TRUE },
\r
1300 { "commentY", ArgY, (LPVOID) &commentY, TRUE },
\r
1301 { "commentW", ArgInt, (LPVOID) &commentW, TRUE },
\r
1302 { "commentH", ArgInt, (LPVOID) &commentH, TRUE },
\r
1303 { "tagsX", ArgX, (LPVOID) &editTagsX, TRUE },
\r
1304 { "tagsY", ArgY, (LPVOID) &editTagsY, TRUE },
\r
1305 { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },
\r
1306 { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },
\r
1307 { "gameListX", ArgX, (LPVOID) &wpGameList.x, TRUE },
\r
1308 { "gameListY", ArgY, (LPVOID) &wpGameList.y, TRUE },
\r
1309 { "gameListW", ArgInt, (LPVOID) &wpGameList.width, TRUE },
\r
1310 { "gameListH", ArgInt, (LPVOID) &wpGameList.height, TRUE },
\r
1311 /* [AS] Layout stuff */
\r
1312 { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },
\r
1313 { "moveHistoryX", ArgX, (LPVOID) &wpMoveHistory.x, TRUE },
\r
1314 { "moveHistoryY", ArgY, (LPVOID) &wpMoveHistory.y, TRUE },
\r
1315 { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },
\r
1316 { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },
\r
1318 { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },
\r
1319 { "evalGraphX", ArgX, (LPVOID) &wpEvalGraph.x, TRUE },
\r
1320 { "evalGraphY", ArgY, (LPVOID) &wpEvalGraph.y, TRUE },
\r
1321 { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },
\r
1322 { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },
\r
1324 { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },
\r
1325 { "engineOutputX", ArgX, (LPVOID) &wpEngineOutput.x, TRUE },
\r
1326 { "engineOutputY", ArgY, (LPVOID) &wpEngineOutput.y, TRUE },
\r
1327 { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },
\r
1328 { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },
\r
1330 { NULL, ArgNone, NULL, FALSE }
\r
1334 /* Kludge for indirection files on command line */
\r
1335 char* lastIndirectionFilename;
\r
1336 ArgDescriptor argDescriptorIndirection =
\r
1337 { "", ArgSettingsFilename, (LPVOID) NULL, FALSE };
\r
1341 ExitArgError(char *msg, char *badArg)
\r
1343 char buf[MSG_SIZ];
\r
1345 sprintf(buf, "%s %s", msg, badArg);
\r
1346 DisplayFatalError(buf, 0, 2);
\r
1350 /* Command line font name parser. NULL name means do nothing.
\r
1351 Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"
\r
1352 For backward compatibility, syntax without the colon is also
\r
1353 accepted, but font names with digits in them won't work in that case.
\r
1356 ParseFontName(char *name, MyFontParams *mfp)
\r
1359 if (name == NULL) return;
\r
1361 q = strchr(p, ':');
\r
1363 if (q - p >= sizeof(mfp->faceName))
\r
1364 ExitArgError("Font name too long:", name);
\r
1365 memcpy(mfp->faceName, p, q - p);
\r
1366 mfp->faceName[q - p] = NULLCHAR;
\r
1369 q = mfp->faceName;
\r
1370 while (*p && !isdigit(*p)) {
\r
1372 if (q - mfp->faceName >= sizeof(mfp->faceName))
\r
1373 ExitArgError("Font name too long:", name);
\r
1375 while (q > mfp->faceName && q[-1] == ' ') q--;
\r
1378 if (!*p) ExitArgError("Font point size missing:", name);
\r
1379 mfp->pointSize = (float) atof(p);
\r
1380 mfp->bold = (strchr(p, 'b') != NULL);
\r
1381 mfp->italic = (strchr(p, 'i') != NULL);
\r
1382 mfp->underline = (strchr(p, 'u') != NULL);
\r
1383 mfp->strikeout = (strchr(p, 's') != NULL);
\r
1386 /* Color name parser.
\r
1387 X version accepts X color names, but this one
\r
1388 handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */
\r
1390 ParseColorName(char *name)
\r
1392 int red, green, blue, count;
\r
1393 char buf[MSG_SIZ];
\r
1395 count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);
\r
1397 count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d",
\r
1398 &red, &green, &blue);
\r
1401 sprintf(buf, "Can't parse color name %s", name);
\r
1402 DisplayError(buf, 0);
\r
1403 return RGB(0, 0, 0);
\r
1405 return PALETTERGB(red, green, blue);
\r
1409 void ParseAttribs(COLORREF *color, int *effects, char* argValue)
\r
1411 char *e = argValue;
\r
1415 if (*e == 'b') eff |= CFE_BOLD;
\r
1416 else if (*e == 'i') eff |= CFE_ITALIC;
\r
1417 else if (*e == 'u') eff |= CFE_UNDERLINE;
\r
1418 else if (*e == 's') eff |= CFE_STRIKEOUT;
\r
1419 else if (*e == '#' || isdigit(*e)) break;
\r
1423 *color = ParseColorName(e);
\r
1428 ParseBoardSize(char *name)
\r
1430 BoardSize bs = SizeTiny;
\r
1431 while (sizeInfo[bs].name != NULL) {
\r
1432 if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;
\r
1435 ExitArgError("Unrecognized board size value", name);
\r
1436 return bs; /* not reached */
\r
1441 StringGet(void *getClosure)
\r
1443 char **p = (char **) getClosure;
\r
1448 FileGet(void *getClosure)
\r
1451 FILE* f = (FILE*) getClosure;
\r
1454 if (c == '\r') c = getc(f); // work around DOS format files by bypassing the '\r' completely
\r
1461 /* Parse settings file named "name". If file found, return the
\r
1462 full name in fullname and return TRUE; else return FALSE */
\r
1464 ParseSettingsFile(char *name, char fullname[MSG_SIZ])
\r
1468 int ok; char buf[MSG_SIZ];
\r
1470 ok = SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy);
\r
1471 if(!ok && strchr(name, '.') == NULL) { // [HGM] append default file-name extension '.ini' when needed
\r
1472 sprintf(buf, "%s.ini", name);
\r
1473 ok = SearchPath(installDir, buf, NULL, MSG_SIZ, fullname, &dummy);
\r
1476 f = fopen(fullname, "r");
\r
1478 ParseArgs(FileGet, f);
\r
1487 ParseArgs(GetFunc get, void *cl)
\r
1489 char argName[ARG_MAX];
\r
1490 char argValue[ARG_MAX];
\r
1491 ArgDescriptor *ad;
\r
1500 while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);
\r
1501 if (ch == NULLCHAR) break;
\r
1503 /* Comment to end of line */
\r
1505 while (ch != '\n' && ch != NULLCHAR) ch = get(cl);
\r
1507 } else if (ch == '/' || ch == '-') {
\r
1510 while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&
\r
1511 ch != '\n' && ch != '\t') {
\r
1517 for (ad = argDescriptors; ad->argName != NULL; ad++)
\r
1518 if (strcmp(ad->argName, argName + 1) == 0) break;
\r
1520 if (ad->argName == NULL)
\r
1521 ExitArgError("Unrecognized argument", argName);
\r
1523 } else if (ch == '@') {
\r
1524 /* Indirection file */
\r
1525 ad = &argDescriptorIndirection;
\r
1528 /* Positional argument */
\r
1529 ad = &argDescriptors[posarg++];
\r
1530 strcpy(argName, ad->argName);
\r
1533 if (ad->argType == ArgTrue) {
\r
1534 *(Boolean *) ad->argLoc = TRUE;
\r
1537 if (ad->argType == ArgFalse) {
\r
1538 *(Boolean *) ad->argLoc = FALSE;
\r
1542 while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
\r
1543 if (ch == NULLCHAR || ch == '\n') {
\r
1544 ExitArgError("No value provided for argument", argName);
\r
1548 // Quoting with { }. No characters have to (or can) be escaped.
\r
1549 // Thus the string cannot contain a '}' character.
\r
1569 } else if (ch == '\'' || ch == '"') {
\r
1570 // Quoting with ' ' or " ", with \ as escape character.
\r
1571 // Inconvenient for long strings that may contain Windows filenames.
\r
1588 if (ch == start) {
\r
1597 if (ad->argType == ArgFilename
\r
1598 || ad->argType == ArgSettingsFilename) {
\r
1604 ExitArgError("Incomplete \\ escape in value for", argName);
\r
1628 for (i = 0; i < 3; i++) {
\r
1629 if (ch >= '0' && ch <= '7') {
\r
1630 octval = octval*8 + (ch - '0');
\r
1637 *q++ = (char) octval;
\r
1648 while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {
\r
1655 switch (ad->argType) {
\r
1657 *(int *) ad->argLoc = atoi(argValue);
\r
1661 *(int *) ad->argLoc = atoi(argValue) + boardX; // [HGM] placement: translate stored relative to absolute
\r
1665 *(int *) ad->argLoc = atoi(argValue) + boardY; // (this is really kludgey, it should be done where used...)
\r
1669 *(int *) ad->argLoc = atoi(argValue);
\r
1670 EnsureOnScreen(&boardX, &boardY, minX, minY);
\r
1674 *(float *) ad->argLoc = (float) atof(argValue);
\r
1679 *(char **) ad->argLoc = strdup(argValue);
\r
1682 case ArgSettingsFilename:
\r
1684 char fullname[MSG_SIZ];
\r
1685 if (ParseSettingsFile(argValue, fullname)) {
\r
1686 if (ad->argLoc != NULL) {
\r
1687 *(char **) ad->argLoc = strdup(fullname);
\r
1690 if (ad->argLoc != NULL) {
\r
1692 ExitArgError("Failed to open indirection file", argValue);
\r
1699 switch (argValue[0]) {
\r
1702 *(Boolean *) ad->argLoc = TRUE;
\r
1706 *(Boolean *) ad->argLoc = FALSE;
\r
1709 ExitArgError("Unrecognized boolean argument value", argValue);
\r
1715 *(COLORREF *)ad->argLoc = ParseColorName(argValue);
\r
1718 case ArgAttribs: {
\r
1719 ColorClass cc = (ColorClass)ad->argLoc;
\r
1720 ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);
\r
1724 case ArgBoardSize:
\r
1725 *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);
\r
1729 ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);
\r
1732 case ArgCommSettings:
\r
1733 ParseCommSettings(argValue, &dcb);
\r
1737 ExitArgError("Unrecognized argument", argValue);
\r
1746 LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
\r
1748 HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
\r
1749 lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);
\r
1752 lf->lfEscapement = 0;
\r
1753 lf->lfOrientation = 0;
\r
1754 lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;
\r
1755 lf->lfItalic = mfp->italic;
\r
1756 lf->lfUnderline = mfp->underline;
\r
1757 lf->lfStrikeOut = mfp->strikeout;
\r
1758 lf->lfCharSet = DEFAULT_CHARSET;
\r
1759 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
1760 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
1761 lf->lfQuality = DEFAULT_QUALITY;
\r
1762 lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
\r
1763 strcpy(lf->lfFaceName, mfp->faceName);
\r
1767 CreateFontInMF(MyFont *mf)
\r
1769 LFfromMFP(&mf->lf, &mf->mfp);
\r
1770 if (mf->hf) DeleteObject(mf->hf);
\r
1771 mf->hf = CreateFontIndirect(&mf->lf);
\r
1775 SetDefaultTextAttribs()
\r
1778 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1779 ParseAttribs(&textAttribs[cc].color,
\r
1780 &textAttribs[cc].effects,
\r
1781 defaultTextAttribs[cc]);
\r
1786 SetDefaultSounds()
\r
1790 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1791 textAttribs[cc].sound.name = strdup("");
\r
1792 textAttribs[cc].sound.data = NULL;
\r
1794 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1795 sounds[sc].name = strdup("");
\r
1796 sounds[sc].data = NULL;
\r
1798 sounds[(int)SoundBell].name = strdup(SOUND_BELL);
\r
1806 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1807 MyLoadSound(&textAttribs[cc].sound);
\r
1809 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1810 MyLoadSound(&sounds[sc]);
\r
1815 InitAppData(LPSTR lpCmdLine)
\r
1818 char buf[ARG_MAX], currDir[MSG_SIZ];
\r
1821 programName = szAppName;
\r
1823 /* Initialize to defaults */
\r
1824 lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);
\r
1825 darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);
\r
1826 whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);
\r
1827 blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);
\r
1828 highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);
\r
1829 premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);
\r
1830 consoleBackgroundColor = ParseColorName(COLOR_BKGD);
\r
1831 SetDefaultTextAttribs();
\r
1832 SetDefaultSounds();
\r
1833 appData.movesPerSession = MOVES_PER_SESSION;
\r
1834 appData.initString = INIT_STRING;
\r
1835 appData.secondInitString = INIT_STRING;
\r
1836 appData.firstComputerString = COMPUTER_STRING;
\r
1837 appData.secondComputerString = COMPUTER_STRING;
\r
1838 appData.firstChessProgram = FIRST_CHESS_PROGRAM;
\r
1839 appData.secondChessProgram = SECOND_CHESS_PROGRAM;
\r
1840 appData.firstPlaysBlack = FALSE;
\r
1841 appData.noChessProgram = FALSE;
\r
1842 chessProgram = FALSE;
\r
1843 appData.firstHost = FIRST_HOST;
\r
1844 appData.secondHost = SECOND_HOST;
\r
1845 appData.firstDirectory = FIRST_DIRECTORY;
\r
1846 appData.secondDirectory = SECOND_DIRECTORY;
\r
1847 appData.bitmapDirectory = "";
\r
1848 appData.remoteShell = REMOTE_SHELL;
\r
1849 appData.remoteUser = "";
\r
1850 appData.timeDelay = TIME_DELAY;
\r
1851 appData.timeControl = TIME_CONTROL;
\r
1852 appData.timeIncrement = TIME_INCREMENT;
\r
1853 appData.icsActive = FALSE;
\r
1854 appData.icsHost = "";
\r
1855 appData.icsPort = ICS_PORT;
\r
1856 appData.icsCommPort = ICS_COMM_PORT;
\r
1857 appData.icsLogon = ICS_LOGON;
\r
1858 appData.icsHelper = "";
\r
1859 appData.useTelnet = FALSE;
\r
1860 appData.telnetProgram = TELNET_PROGRAM;
\r
1861 appData.gateway = "";
\r
1862 appData.loadGameFile = "";
\r
1863 appData.loadGameIndex = 0;
\r
1864 appData.saveGameFile = "";
\r
1865 appData.autoSaveGames = FALSE;
\r
1866 appData.loadPositionFile = "";
\r
1867 appData.loadPositionIndex = 1;
\r
1868 appData.savePositionFile = "";
\r
1869 appData.matchMode = FALSE;
\r
1870 appData.matchGames = 0;
\r
1871 appData.monoMode = FALSE;
\r
1872 appData.debugMode = FALSE;
\r
1873 appData.clockMode = TRUE;
\r
1874 boardSize = (BoardSize) -1; /* determine by screen size */
\r
1875 appData.Iconic = FALSE; /*unused*/
\r
1876 appData.searchTime = "";
\r
1877 appData.searchDepth = 0;
\r
1878 appData.showCoords = FALSE;
\r
1879 appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/
\r
1880 appData.autoCallFlag = FALSE;
\r
1881 appData.flipView = FALSE;
\r
1882 appData.autoFlipView = TRUE;
\r
1883 appData.cmailGameName = "";
\r
1884 appData.alwaysPromoteToQueen = FALSE;
\r
1885 appData.oldSaveStyle = FALSE;
\r
1886 appData.quietPlay = FALSE;
\r
1887 appData.showThinking = FALSE;
\r
1888 appData.ponderNextMove = TRUE;
\r
1889 appData.periodicUpdates = TRUE;
\r
1890 appData.popupExitMessage = TRUE;
\r
1891 appData.popupMoveErrors = FALSE;
\r
1892 appData.autoObserve = FALSE;
\r
1893 appData.autoComment = FALSE;
\r
1894 appData.animate = TRUE;
\r
1895 appData.animSpeed = 10;
\r
1896 appData.animateDragging = TRUE;
\r
1897 appData.highlightLastMove = TRUE;
\r
1898 appData.getMoveList = TRUE;
\r
1899 appData.testLegality = TRUE;
\r
1900 appData.premove = TRUE;
\r
1901 appData.premoveWhite = FALSE;
\r
1902 appData.premoveWhiteText = "";
\r
1903 appData.premoveBlack = FALSE;
\r
1904 appData.premoveBlackText = "";
\r
1905 appData.icsAlarm = TRUE;
\r
1906 appData.icsAlarmTime = 5000;
\r
1907 appData.autoRaiseBoard = TRUE;
\r
1908 appData.localLineEditing = TRUE;
\r
1909 appData.colorize = TRUE;
\r
1910 appData.reuseFirst = TRUE;
\r
1911 appData.reuseSecond = TRUE;
\r
1912 appData.blindfold = FALSE;
\r
1913 appData.icsEngineAnalyze = FALSE;
\r
1914 memset(&dcb, 0, sizeof(DCB)); // required by VS 2002 +
\r
1915 dcb.DCBlength = sizeof(DCB);
\r
1916 dcb.BaudRate = 9600;
\r
1917 dcb.fBinary = TRUE;
\r
1918 dcb.fParity = FALSE;
\r
1919 dcb.fOutxCtsFlow = FALSE;
\r
1920 dcb.fOutxDsrFlow = FALSE;
\r
1921 dcb.fDtrControl = DTR_CONTROL_ENABLE;
\r
1922 dcb.fDsrSensitivity = FALSE;
\r
1923 dcb.fTXContinueOnXoff = TRUE;
\r
1924 dcb.fOutX = FALSE;
\r
1926 dcb.fNull = FALSE;
\r
1927 dcb.fRtsControl = RTS_CONTROL_ENABLE;
\r
1928 dcb.fAbortOnError = FALSE;
\r
1930 dcb.Parity = SPACEPARITY;
\r
1931 dcb.StopBits = ONESTOPBIT;
\r
1932 settingsFileName = SETTINGS_FILE;
\r
1933 saveSettingsOnExit = TRUE;
\r
1934 boardX = CW_USEDEFAULT;
\r
1935 boardY = CW_USEDEFAULT;
\r
1936 analysisX = CW_USEDEFAULT;
\r
1937 analysisY = CW_USEDEFAULT;
\r
1938 analysisW = CW_USEDEFAULT;
\r
1939 analysisH = CW_USEDEFAULT;
\r
1940 commentX = CW_USEDEFAULT;
\r
1941 commentY = CW_USEDEFAULT;
\r
1942 commentW = CW_USEDEFAULT;
\r
1943 commentH = CW_USEDEFAULT;
\r
1944 editTagsX = CW_USEDEFAULT;
\r
1945 editTagsY = CW_USEDEFAULT;
\r
1946 editTagsW = CW_USEDEFAULT;
\r
1947 editTagsH = CW_USEDEFAULT;
\r
1948 icsTextMenuString = ICS_TEXT_MENU_DEFAULT;
\r
1949 icsNames = ICS_NAMES;
\r
1950 firstChessProgramNames = FCP_NAMES;
\r
1951 secondChessProgramNames = SCP_NAMES;
\r
1952 appData.initialMode = "";
\r
1953 appData.variant = "normal";
\r
1954 appData.firstProtocolVersion = PROTOVER;
\r
1955 appData.secondProtocolVersion = PROTOVER;
\r
1956 appData.showButtonBar = TRUE;
\r
1958 /* [AS] New properties (see comments in header file) */
\r
1959 appData.firstScoreIsAbsolute = FALSE;
\r
1960 appData.secondScoreIsAbsolute = FALSE;
\r
1961 appData.saveExtendedInfoInPGN = FALSE;
\r
1962 appData.hideThinkingFromHuman = FALSE;
\r
1963 appData.liteBackTextureFile = "";
\r
1964 appData.liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
1965 appData.darkBackTextureFile = "";
\r
1966 appData.darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
1967 appData.renderPiecesWithFont = "";
\r
1968 appData.fontToPieceTable = "";
\r
1969 appData.fontBackColorWhite = 0;
\r
1970 appData.fontForeColorWhite = 0;
\r
1971 appData.fontBackColorBlack = 0;
\r
1972 appData.fontForeColorBlack = 0;
\r
1973 appData.fontPieceSize = 80;
\r
1974 appData.overrideLineGap = 1;
\r
1975 appData.adjudicateLossThreshold = 0;
\r
1976 appData.delayBeforeQuit = 0;
\r
1977 appData.delayAfterQuit = 0;
\r
1978 appData.nameOfDebugFile = "winboard.debug";
\r
1979 appData.pgnEventHeader = "Computer Chess Game";
\r
1980 appData.defaultFrcPosition = -1;
\r
1981 appData.gameListTags = GLT_DEFAULT_TAGS;
\r
1982 appData.saveOutOfBookInfo = TRUE;
\r
1983 appData.showEvalInMoveHistory = TRUE;
\r
1984 appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );
\r
1985 appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );
\r
1986 appData.highlightMoveWithArrow = FALSE;
\r
1987 appData.highlightArrowColor = ParseColorName( "#FFFF80" );
\r
1988 appData.useStickyWindows = TRUE;
\r
1989 appData.adjudicateDrawMoves = 0;
\r
1990 appData.autoDisplayComment = TRUE;
\r
1991 appData.autoDisplayTags = TRUE;
\r
1992 appData.firstIsUCI = FALSE;
\r
1993 appData.secondIsUCI = FALSE;
\r
1994 appData.firstHasOwnBookUCI = TRUE;
\r
1995 appData.secondHasOwnBookUCI = TRUE;
\r
1996 appData.polyglotDir = "";
\r
1997 appData.usePolyglotBook = FALSE;
\r
1998 appData.polyglotBook = "";
\r
1999 appData.defaultHashSize = 64;
\r
2000 appData.defaultCacheSizeEGTB = 4;
\r
2001 appData.defaultPathEGTB = "c:\\egtb";
\r
2002 appData.firstOptions = "";
\r
2003 appData.secondOptions = "";
\r
2005 InitWindowPlacement( &wpGameList );
\r
2006 InitWindowPlacement( &wpMoveHistory );
\r
2007 InitWindowPlacement( &wpEvalGraph );
\r
2008 InitWindowPlacement( &wpEngineOutput );
\r
2009 InitWindowPlacement( &wpConsole );
\r
2011 /* [HGM] User-selectable board size, adjudication control, miscellaneous */
\r
2012 appData.NrFiles = -1;
\r
2013 appData.NrRanks = -1;
\r
2014 appData.holdingsSize = -1;
\r
2015 appData.testClaims = FALSE;
\r
2016 appData.checkMates = FALSE;
\r
2017 appData.materialDraws= FALSE;
\r
2018 appData.trivialDraws = FALSE;
\r
2019 appData.ruleMoves = 51;
\r
2020 appData.drawRepeats = 6;
\r
2021 appData.matchPause = 10000;
\r
2022 appData.alphaRank = FALSE;
\r
2023 appData.allWhite = FALSE;
\r
2024 appData.upsideDown = FALSE;
\r
2025 appData.serverPause = 15;
\r
2026 appData.serverMovesName = NULL;
\r
2027 appData.suppressLoadMoves = FALSE;
\r
2028 appData.firstTimeOdds = 1;
\r
2029 appData.secondTimeOdds = 1;
\r
2030 appData.firstAccumulateTC = 1; // combine previous and current sessions
\r
2031 appData.secondAccumulateTC = 1;
\r
2032 appData.firstNPS = -1; // [HGM] nps: use wall-clock time
\r
2033 appData.secondNPS = -1;
\r
2034 appData.engineComments = 1;
\r
2035 appData.smpCores = 1; // [HGM] SMP: max nr of cores
\r
2036 appData.egtFormats = "";
\r
2039 appData.zippyTalk = ZIPPY_TALK;
\r
2040 appData.zippyPlay = ZIPPY_PLAY;
\r
2041 appData.zippyLines = ZIPPY_LINES;
\r
2042 appData.zippyPinhead = ZIPPY_PINHEAD;
\r
2043 appData.zippyPassword = ZIPPY_PASSWORD;
\r
2044 appData.zippyPassword2 = ZIPPY_PASSWORD2;
\r
2045 appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;
\r
2046 appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;
\r
2047 appData.zippyUseI = ZIPPY_USE_I;
\r
2048 appData.zippyBughouse = ZIPPY_BUGHOUSE;
\r
2049 appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;
\r
2050 appData.zippyGameEnd = ZIPPY_GAME_END;
\r
2051 appData.zippyGameStart = ZIPPY_GAME_START;
\r
2052 appData.zippyAdjourn = ZIPPY_ADJOURN;
\r
2053 appData.zippyAbort = ZIPPY_ABORT;
\r
2054 appData.zippyVariants = ZIPPY_VARIANTS;
\r
2055 appData.zippyMaxGames = ZIPPY_MAX_GAMES;
\r
2056 appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;
\r
2059 /* Point font array elements to structures and
\r
2060 parse default font names */
\r
2061 for (i=0; i<NUM_FONTS; i++) {
\r
2062 for (j=0; j<NUM_SIZES; j++) {
\r
2063 font[j][i] = &fontRec[j][i];
\r
2064 ParseFontName(font[j][i]->def, &font[j][i]->mfp);
\r
2068 /* Parse default settings file if any */
\r
2069 if (ParseSettingsFile(settingsFileName, buf)) {
\r
2070 settingsFileName = strdup(buf);
\r
2073 /* Parse command line */
\r
2074 ParseArgs(StringGet, &lpCmdLine);
\r
2076 /* [HGM] make sure board size is acceptable */
\r
2077 if(appData.NrFiles > BOARD_SIZE ||
\r
2078 appData.NrRanks > BOARD_SIZE )
\r
2079 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
2081 /* [HGM] After parsing the options from the .ini file, and overruling them
\r
2082 * with options from the command line, we now make an even higher priority
\r
2083 * overrule by WB options attached to the engine command line. This so that
\r
2084 * tournament managers can use WB options (such as /timeOdds) that follow
\r
2087 if(appData.firstChessProgram != NULL) {
\r
2088 char *p = StrStr(appData.firstChessProgram, "WBopt");
\r
2089 static char *f = "first";
\r
2090 char buf[MSG_SIZ], *q = buf;
\r
2091 if(p != NULL) { // engine command line contains WinBoard options
\r
2092 sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"
\r
2093 ParseArgs(StringGet, &q);
\r
2094 p[-1] = 0; // cut them offengine command line
\r
2097 // now do same for second chess program
\r
2098 if(appData.secondChessProgram != NULL) {
\r
2099 char *p = StrStr(appData.secondChessProgram, "WBopt");
\r
2100 static char *s = "second";
\r
2101 char buf[MSG_SIZ], *q = buf;
\r
2102 if(p != NULL) { // engine command line contains WinBoard options
\r
2103 sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"
\r
2104 ParseArgs(StringGet, &q);
\r
2105 p[-1] = 0; // cut them offengine command line
\r
2110 /* Propagate options that affect others */
\r
2111 if (appData.matchMode || appData.matchGames) chessProgram = TRUE;
\r
2112 if (appData.icsActive || appData.noChessProgram) {
\r
2113 chessProgram = FALSE; /* not local chess program mode */
\r
2116 /* Open startup dialog if needed */
\r
2117 if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||
\r
2118 (appData.icsActive && *appData.icsHost == NULLCHAR) ||
\r
2119 (chessProgram && (*appData.firstChessProgram == NULLCHAR ||
\r
2120 *appData.secondChessProgram == NULLCHAR))) {
\r
2123 lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);
\r
2124 DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);
\r
2125 FreeProcInstance(lpProc);
\r
2128 /* Make sure save files land in the right (?) directory */
\r
2129 if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {
\r
2130 appData.saveGameFile = strdup(buf);
\r
2132 if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {
\r
2133 appData.savePositionFile = strdup(buf);
\r
2136 /* Finish initialization for fonts and sounds */
\r
2137 for (i=0; i<NUM_FONTS; i++) {
\r
2138 for (j=0; j<NUM_SIZES; j++) {
\r
2139 CreateFontInMF(font[j][i]);
\r
2142 /* xboard, and older WinBoards, controlled the move sound with the
\r
2143 appData.ringBellAfterMoves option. In the current WinBoard, we
\r
2144 always turn the option on (so that the backend will call us),
\r
2145 then let the user turn the sound off by setting it to silence if
\r
2146 desired. To accommodate old winboard.ini files saved by old
\r
2147 versions of WinBoard, we also turn off the sound if the option
\r
2148 was initially set to false. */
\r
2149 if (!appData.ringBellAfterMoves) {
\r
2150 sounds[(int)SoundMove].name = strdup("");
\r
2151 appData.ringBellAfterMoves = TRUE;
\r
2153 GetCurrentDirectory(MSG_SIZ, currDir);
\r
2154 SetCurrentDirectory(installDir);
\r
2156 SetCurrentDirectory(currDir);
\r
2158 p = icsTextMenuString;
\r
2159 if (p[0] == '@') {
\r
2160 FILE* f = fopen(p + 1, "r");
\r
2162 DisplayFatalError(p + 1, errno, 2);
\r
2165 i = fread(buf, 1, sizeof(buf)-1, f);
\r
2167 buf[i] = NULLCHAR;
\r
2170 ParseIcsTextMenu(strdup(p));
\r
2177 HMENU hmenu = GetMenu(hwndMain);
\r
2179 (void) EnableMenuItem(hmenu, IDM_CommPort,
\r
2180 MF_BYCOMMAND|((appData.icsActive &&
\r
2181 *appData.icsCommPort != NULLCHAR) ?
\r
2182 MF_ENABLED : MF_GRAYED));
\r
2183 (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,
\r
2184 MF_BYCOMMAND|(saveSettingsOnExit ?
\r
2185 MF_CHECKED : MF_UNCHECKED));
\r
2190 SaveSettings(char* name)
\r
2193 ArgDescriptor *ad;
\r
2194 WINDOWPLACEMENT wp;
\r
2195 char dir[MSG_SIZ];
\r
2197 if (!hwndMain) return;
\r
2199 GetCurrentDirectory(MSG_SIZ, dir);
\r
2200 SetCurrentDirectory(installDir);
\r
2201 f = fopen(name, "w");
\r
2202 SetCurrentDirectory(dir);
\r
2204 DisplayError(name, errno);
\r
2207 fprintf(f, ";\n");
\r
2208 fprintf(f, "; %s %s.%s Save Settings file\n", PRODUCT, VERSION, PATCHLEVEL);
\r
2209 fprintf(f, ";\n");
\r
2210 fprintf(f, "; You can edit the values of options that are already set in this file,\n");
\r
2211 fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");
\r
2212 fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");
\r
2213 fprintf(f, ";\n");
\r
2215 wp.length = sizeof(WINDOWPLACEMENT);
\r
2216 GetWindowPlacement(hwndMain, &wp);
\r
2217 boardX = wp.rcNormalPosition.left;
\r
2218 boardY = wp.rcNormalPosition.top;
\r
2220 if (hwndConsole) {
\r
2221 GetWindowPlacement(hwndConsole, &wp);
\r
2222 wpConsole.x = wp.rcNormalPosition.left;
\r
2223 wpConsole.y = wp.rcNormalPosition.top;
\r
2224 wpConsole.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2225 wpConsole.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2228 if (analysisDialog) {
\r
2229 GetWindowPlacement(analysisDialog, &wp);
\r
2230 analysisX = wp.rcNormalPosition.left;
\r
2231 analysisY = wp.rcNormalPosition.top;
\r
2232 analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2233 analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2236 if (commentDialog) {
\r
2237 GetWindowPlacement(commentDialog, &wp);
\r
2238 commentX = wp.rcNormalPosition.left;
\r
2239 commentY = wp.rcNormalPosition.top;
\r
2240 commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2241 commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2244 if (editTagsDialog) {
\r
2245 GetWindowPlacement(editTagsDialog, &wp);
\r
2246 editTagsX = wp.rcNormalPosition.left;
\r
2247 editTagsY = wp.rcNormalPosition.top;
\r
2248 editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2249 editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2252 if (gameListDialog) {
\r
2253 GetWindowPlacement(gameListDialog, &wp);
\r
2254 wpGameList.x = wp.rcNormalPosition.left;
\r
2255 wpGameList.y = wp.rcNormalPosition.top;
\r
2256 wpGameList.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2257 wpGameList.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2260 /* [AS] Move history */
\r
2261 wpMoveHistory.visible = MoveHistoryIsUp();
\r
2263 if( moveHistoryDialog ) {
\r
2264 GetWindowPlacement(moveHistoryDialog, &wp);
\r
2265 wpMoveHistory.x = wp.rcNormalPosition.left;
\r
2266 wpMoveHistory.y = wp.rcNormalPosition.top;
\r
2267 wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2268 wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2271 /* [AS] Eval graph */
\r
2272 wpEvalGraph.visible = EvalGraphIsUp();
\r
2274 if( evalGraphDialog ) {
\r
2275 GetWindowPlacement(evalGraphDialog, &wp);
\r
2276 wpEvalGraph.x = wp.rcNormalPosition.left;
\r
2277 wpEvalGraph.y = wp.rcNormalPosition.top;
\r
2278 wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2279 wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2282 /* [AS] Engine output */
\r
2283 wpEngineOutput.visible = EngineOutputIsUp();
\r
2285 if( engineOutputDialog ) {
\r
2286 GetWindowPlacement(engineOutputDialog, &wp);
\r
2287 wpEngineOutput.x = wp.rcNormalPosition.left;
\r
2288 wpEngineOutput.y = wp.rcNormalPosition.top;
\r
2289 wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2290 wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2293 for (ad = argDescriptors; ad->argName != NULL; ad++) {
\r
2294 if (!ad->save) continue;
\r
2295 switch (ad->argType) {
\r
2298 char *p = *(char **)ad->argLoc;
\r
2299 if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {
\r
2300 /* Quote multiline values or \-containing values
\r
2301 with { } if possible */
\r
2302 fprintf(f, "/%s={%s}\n", ad->argName, p);
\r
2304 /* Else quote with " " */
\r
2305 fprintf(f, "/%s=\"", ad->argName);
\r
2307 if (*p == '\n') fprintf(f, "\n");
\r
2308 else if (*p == '\r') fprintf(f, "\\r");
\r
2309 else if (*p == '\t') fprintf(f, "\\t");
\r
2310 else if (*p == '\b') fprintf(f, "\\b");
\r
2311 else if (*p == '\f') fprintf(f, "\\f");
\r
2312 else if (*p < ' ') fprintf(f, "\\%03o", *p);
\r
2313 else if (*p == '\"') fprintf(f, "\\\"");
\r
2314 else if (*p == '\\') fprintf(f, "\\\\");
\r
2318 fprintf(f, "\"\n");
\r
2324 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);
\r
2327 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardX); // [HGM] placement: stor relative value
\r
2330 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardY);
\r
2333 fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);
\r
2336 fprintf(f, "/%s=%s\n", ad->argName,
\r
2337 (*(Boolean *)ad->argLoc) ? "true" : "false");
\r
2340 if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2343 if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2347 COLORREF color = *(COLORREF *)ad->argLoc;
\r
2348 fprintf(f, "/%s=#%02lx%02lx%02lx\n", ad->argName,
\r
2349 color&0xff, (color>>8)&0xff, (color>>16)&0xff);
\r
2354 MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];
\r
2355 fprintf(f, "/%s=\"%s%s%s%s%s#%02lx%02lx%02lx\"\n", ad->argName,
\r
2356 (ta->effects & CFE_BOLD) ? "b" : "",
\r
2357 (ta->effects & CFE_ITALIC) ? "i" : "",
\r
2358 (ta->effects & CFE_UNDERLINE) ? "u" : "",
\r
2359 (ta->effects & CFE_STRIKEOUT) ? "s" : "",
\r
2360 (ta->effects) ? " " : "",
\r
2361 ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);
\r
2365 if (strchr(*(char **)ad->argLoc, '\"')) {
\r
2366 fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);
\r
2368 fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);
\r
2371 case ArgBoardSize:
\r
2372 fprintf(f, "/%s=%s\n", ad->argName,
\r
2373 sizeInfo[*(BoardSize *)ad->argLoc].name);
\r
2378 for (bs=0; bs<NUM_SIZES; bs++) {
\r
2379 MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;
\r
2380 fprintf(f, "/size=%s ", sizeInfo[bs].name);
\r
2381 fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n",
\r
2382 ad->argName, mfp->faceName, mfp->pointSize,
\r
2383 mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",
\r
2384 mfp->bold ? "b" : "",
\r
2385 mfp->italic ? "i" : "",
\r
2386 mfp->underline ? "u" : "",
\r
2387 mfp->strikeout ? "s" : "");
\r
2391 case ArgCommSettings:
\r
2392 PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);
\r
2394 case ArgSettingsFilename: ;
\r
2402 /*---------------------------------------------------------------------------*\
\r
2404 * GDI board drawing routines
\r
2406 \*---------------------------------------------------------------------------*/
\r
2408 /* [AS] Draw square using background texture */
\r
2409 static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )
\r
2414 return; /* Should never happen! */
\r
2417 SetGraphicsMode( dst, GM_ADVANCED );
\r
2424 /* X reflection */
\r
2429 x.eDx = (FLOAT) dw + dx - 1;
\r
2432 SetWorldTransform( dst, &x );
\r
2435 /* Y reflection */
\r
2441 x.eDy = (FLOAT) dh + dy - 1;
\r
2443 SetWorldTransform( dst, &x );
\r
2451 x.eDx = (FLOAT) dx;
\r
2452 x.eDy = (FLOAT) dy;
\r
2455 SetWorldTransform( dst, &x );
\r
2459 BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );
\r
2467 SetWorldTransform( dst, &x );
\r
2469 ModifyWorldTransform( dst, 0, MWT_IDENTITY );
\r
2472 /* [AS] [HGM] Make room for more piece types, so all pieces can be different */
\r
2474 PM_WP = (int) WhitePawn,
\r
2475 PM_WN = (int) WhiteKnight,
\r
2476 PM_WB = (int) WhiteBishop,
\r
2477 PM_WR = (int) WhiteRook,
\r
2478 PM_WQ = (int) WhiteQueen,
\r
2479 PM_WF = (int) WhiteFerz,
\r
2480 PM_WW = (int) WhiteWazir,
\r
2481 PM_WE = (int) WhiteAlfil,
\r
2482 PM_WM = (int) WhiteMan,
\r
2483 PM_WO = (int) WhiteCannon,
\r
2484 PM_WU = (int) WhiteUnicorn,
\r
2485 PM_WH = (int) WhiteNightrider,
\r
2486 PM_WA = (int) WhiteAngel,
\r
2487 PM_WC = (int) WhiteMarshall,
\r
2488 PM_WAB = (int) WhiteCardinal,
\r
2489 PM_WD = (int) WhiteDragon,
\r
2490 PM_WL = (int) WhiteLance,
\r
2491 PM_WS = (int) WhiteCobra,
\r
2492 PM_WV = (int) WhiteFalcon,
\r
2493 PM_WSG = (int) WhiteSilver,
\r
2494 PM_WG = (int) WhiteGrasshopper,
\r
2495 PM_WK = (int) WhiteKing,
\r
2496 PM_BP = (int) BlackPawn,
\r
2497 PM_BN = (int) BlackKnight,
\r
2498 PM_BB = (int) BlackBishop,
\r
2499 PM_BR = (int) BlackRook,
\r
2500 PM_BQ = (int) BlackQueen,
\r
2501 PM_BF = (int) BlackFerz,
\r
2502 PM_BW = (int) BlackWazir,
\r
2503 PM_BE = (int) BlackAlfil,
\r
2504 PM_BM = (int) BlackMan,
\r
2505 PM_BO = (int) BlackCannon,
\r
2506 PM_BU = (int) BlackUnicorn,
\r
2507 PM_BH = (int) BlackNightrider,
\r
2508 PM_BA = (int) BlackAngel,
\r
2509 PM_BC = (int) BlackMarshall,
\r
2510 PM_BG = (int) BlackGrasshopper,
\r
2511 PM_BAB = (int) BlackCardinal,
\r
2512 PM_BD = (int) BlackDragon,
\r
2513 PM_BL = (int) BlackLance,
\r
2514 PM_BS = (int) BlackCobra,
\r
2515 PM_BV = (int) BlackFalcon,
\r
2516 PM_BSG = (int) BlackSilver,
\r
2517 PM_BK = (int) BlackKing
\r
2520 static HFONT hPieceFont = NULL;
\r
2521 static HBITMAP hPieceMask[(int) EmptySquare];
\r
2522 static HBITMAP hPieceFace[(int) EmptySquare];
\r
2523 static int fontBitmapSquareSize = 0;
\r
2524 static char pieceToFontChar[(int) EmptySquare] =
\r
2525 { 'p', 'n', 'b', 'r', 'q',
\r
2526 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',
\r
2527 'k', 'o', 'm', 'v', 't', 'w',
\r
2528 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',
\r
2531 extern BOOL SetCharTable( char *table, const char * map );
\r
2532 /* [HGM] moved to backend.c */
\r
2534 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )
\r
2537 BYTE r1 = GetRValue( color );
\r
2538 BYTE g1 = GetGValue( color );
\r
2539 BYTE b1 = GetBValue( color );
\r
2545 /* Create a uniform background first */
\r
2546 hbrush = CreateSolidBrush( color );
\r
2547 SetRect( &rc, 0, 0, squareSize, squareSize );
\r
2548 FillRect( hdc, &rc, hbrush );
\r
2549 DeleteObject( hbrush );
\r
2552 /* Vertical gradient, good for pawn, knight and rook, less for queen and king */
\r
2553 int steps = squareSize / 2;
\r
2556 for( i=0; i<steps; i++ ) {
\r
2557 BYTE r = r1 - (r1-r2) * i / steps;
\r
2558 BYTE g = g1 - (g1-g2) * i / steps;
\r
2559 BYTE b = b1 - (b1-b2) * i / steps;
\r
2561 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2562 SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );
\r
2563 FillRect( hdc, &rc, hbrush );
\r
2564 DeleteObject(hbrush);
\r
2567 else if( mode == 2 ) {
\r
2568 /* Diagonal gradient, good more or less for every piece */
\r
2569 POINT triangle[3];
\r
2570 HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );
\r
2571 HBRUSH hbrush_old;
\r
2572 int steps = squareSize;
\r
2575 triangle[0].x = squareSize - steps;
\r
2576 triangle[0].y = squareSize;
\r
2577 triangle[1].x = squareSize;
\r
2578 triangle[1].y = squareSize;
\r
2579 triangle[2].x = squareSize;
\r
2580 triangle[2].y = squareSize - steps;
\r
2582 for( i=0; i<steps; i++ ) {
\r
2583 BYTE r = r1 - (r1-r2) * i / steps;
\r
2584 BYTE g = g1 - (g1-g2) * i / steps;
\r
2585 BYTE b = b1 - (b1-b2) * i / steps;
\r
2587 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2588 hbrush_old = SelectObject( hdc, hbrush );
\r
2589 Polygon( hdc, triangle, 3 );
\r
2590 SelectObject( hdc, hbrush_old );
\r
2591 DeleteObject(hbrush);
\r
2596 SelectObject( hdc, hpen );
\r
2601 [AS] The method I use to create the bitmaps it a bit tricky, but it
\r
2602 seems to work ok. The main problem here is to find the "inside" of a chess
\r
2603 piece: follow the steps as explained below.
\r
2605 static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
\r
2609 COLORREF chroma = RGB(0xFF,0x00,0xFF);
\r
2613 int backColor = whitePieceColor;
\r
2614 int foreColor = blackPieceColor;
\r
2616 if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {
\r
2617 backColor = appData.fontBackColorWhite;
\r
2618 foreColor = appData.fontForeColorWhite;
\r
2620 else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {
\r
2621 backColor = appData.fontBackColorBlack;
\r
2622 foreColor = appData.fontForeColorBlack;
\r
2626 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2628 hbm_old = SelectObject( hdc, hbm );
\r
2632 rc.right = squareSize;
\r
2633 rc.bottom = squareSize;
\r
2635 /* Step 1: background is now black */
\r
2636 FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );
\r
2638 GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );
\r
2640 pt.x = (squareSize - sz.cx) / 2;
\r
2641 pt.y = (squareSize - sz.cy) / 2;
\r
2643 SetBkMode( hdc, TRANSPARENT );
\r
2644 SetTextColor( hdc, chroma );
\r
2645 /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */
\r
2646 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2648 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
\r
2649 /* Step 3: the area outside the piece is filled with white */
\r
2650 // FloodFill( hdc, 0, 0, chroma );
\r
2651 ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );
\r
2652 ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big
\r
2653 ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );
\r
2654 ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );
\r
2655 SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
\r
2657 Step 4: this is the tricky part, the area inside the piece is filled with black,
\r
2658 but if the start point is not inside the piece we're lost!
\r
2659 There should be a better way to do this... if we could create a region or path
\r
2660 from the fill operation we would be fine for example.
\r
2662 // FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );
\r
2663 ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );
\r
2665 { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */
\r
2666 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2667 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2669 SelectObject( dc2, bm2 );
\r
2670 BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy
\r
2671 BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2672 BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2673 BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2674 BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2677 DeleteObject( bm2 );
\r
2680 SetTextColor( hdc, 0 );
\r
2682 Step 5: some fonts have "disconnected" areas that are skipped by the fill:
\r
2683 draw the piece again in black for safety.
\r
2685 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2687 SelectObject( hdc, hbm_old );
\r
2689 if( hPieceMask[index] != NULL ) {
\r
2690 DeleteObject( hPieceMask[index] );
\r
2693 hPieceMask[index] = hbm;
\r
2696 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2698 SelectObject( hdc, hbm );
\r
2701 HDC dc1 = CreateCompatibleDC( hdc_window );
\r
2702 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2703 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2705 SelectObject( dc1, hPieceMask[index] );
\r
2706 SelectObject( dc2, bm2 );
\r
2707 FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );
\r
2708 BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );
\r
2711 Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves
\r
2712 the piece background and deletes (makes transparent) the rest.
\r
2713 Thanks to that mask, we are free to paint the background with the greates
\r
2714 freedom, as we'll be able to mask off the unwanted parts when finished.
\r
2715 We use this, to make gradients and give the pieces a "roundish" look.
\r
2717 SetPieceBackground( hdc, backColor, 2 );
\r
2718 BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );
\r
2722 DeleteObject( bm2 );
\r
2725 SetTextColor( hdc, foreColor );
\r
2726 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2728 SelectObject( hdc, hbm_old );
\r
2730 if( hPieceFace[index] != NULL ) {
\r
2731 DeleteObject( hPieceFace[index] );
\r
2734 hPieceFace[index] = hbm;
\r
2737 static int TranslatePieceToFontPiece( int piece )
\r
2767 case BlackMarshall:
\r
2771 case BlackNightrider:
\r
2777 case BlackUnicorn:
\r
2781 case BlackGrasshopper:
\r
2793 case BlackCardinal:
\r
2800 case WhiteMarshall:
\r
2804 case WhiteNightrider:
\r
2810 case WhiteUnicorn:
\r
2814 case WhiteGrasshopper:
\r
2826 case WhiteCardinal:
\r
2835 void CreatePiecesFromFont()
\r
2838 HDC hdc_window = NULL;
\r
2844 if( fontBitmapSquareSize < 0 ) {
\r
2845 /* Something went seriously wrong in the past: do not try to recreate fonts! */
\r
2849 if( appData.renderPiecesWithFont == NULL || appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {
\r
2850 fontBitmapSquareSize = -1;
\r
2854 if( fontBitmapSquareSize != squareSize ) {
\r
2855 hdc_window = GetDC( hwndMain );
\r
2856 hdc = CreateCompatibleDC( hdc_window );
\r
2858 if( hPieceFont != NULL ) {
\r
2859 DeleteObject( hPieceFont );
\r
2862 for( i=0; i<=(int)BlackKing; i++ ) {
\r
2863 hPieceMask[i] = NULL;
\r
2864 hPieceFace[i] = NULL;
\r
2870 if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {
\r
2871 fontHeight = appData.fontPieceSize;
\r
2874 fontHeight = (fontHeight * squareSize) / 100;
\r
2876 lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
\r
2878 lf.lfEscapement = 0;
\r
2879 lf.lfOrientation = 0;
\r
2880 lf.lfWeight = FW_NORMAL;
\r
2882 lf.lfUnderline = 0;
\r
2883 lf.lfStrikeOut = 0;
\r
2884 lf.lfCharSet = DEFAULT_CHARSET;
\r
2885 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
2886 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
2887 lf.lfQuality = PROOF_QUALITY;
\r
2888 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
\r
2889 strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );
\r
2890 lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';
\r
2892 hPieceFont = CreateFontIndirect( &lf );
\r
2894 if( hPieceFont == NULL ) {
\r
2895 fontBitmapSquareSize = -2;
\r
2898 /* Setup font-to-piece character table */
\r
2899 if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {
\r
2900 /* No (or wrong) global settings, try to detect the font */
\r
2901 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {
\r
2903 SetCharTable(pieceToFontChar, "phbrqkojntwl");
\r
2905 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {
\r
2906 /* DiagramTT* family */
\r
2907 SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");
\r
2909 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {
\r
2910 /* Fairy symbols */
\r
2911 SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
\r
2913 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {
\r
2914 /* Good Companion (Some characters get warped as literal :-( */
\r
2915 char s[] = "1cmWG0ñueOS¯®oYI23wgQU";
\r
2916 s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;
\r
2917 SetCharTable(pieceToFontChar, s);
\r
2920 /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */
\r
2921 SetCharTable(pieceToFontChar, "pnbrqkomvtwl");
\r
2925 /* Create bitmaps */
\r
2926 hfont_old = SelectObject( hdc, hPieceFont );
\r
2928 CreatePieceMaskFromFont( hdc_window, hdc, PM_WP );
\r
2929 CreatePieceMaskFromFont( hdc_window, hdc, PM_WN );
\r
2930 CreatePieceMaskFromFont( hdc_window, hdc, PM_WB );
\r
2931 CreatePieceMaskFromFont( hdc_window, hdc, PM_WR );
\r
2932 CreatePieceMaskFromFont( hdc_window, hdc, PM_WQ );
\r
2933 CreatePieceMaskFromFont( hdc_window, hdc, PM_WK );
\r
2934 CreatePieceMaskFromFont( hdc_window, hdc, PM_BP );
\r
2935 CreatePieceMaskFromFont( hdc_window, hdc, PM_BN );
\r
2936 CreatePieceMaskFromFont( hdc_window, hdc, PM_BB );
\r
2937 CreatePieceMaskFromFont( hdc_window, hdc, PM_BR );
\r
2938 CreatePieceMaskFromFont( hdc_window, hdc, PM_BQ );
\r
2939 CreatePieceMaskFromFont( hdc_window, hdc, PM_BK );
\r
2941 CreatePieceMaskFromFont( hdc_window, hdc, PM_WA );
\r
2942 CreatePieceMaskFromFont( hdc_window, hdc, PM_WC );
\r
2943 CreatePieceMaskFromFont( hdc_window, hdc, PM_WF );
\r
2944 CreatePieceMaskFromFont( hdc_window, hdc, PM_WH );
\r
2945 CreatePieceMaskFromFont( hdc_window, hdc, PM_WE );
\r
2946 CreatePieceMaskFromFont( hdc_window, hdc, PM_WW );
\r
2947 CreatePieceMaskFromFont( hdc_window, hdc, PM_WU );
\r
2948 CreatePieceMaskFromFont( hdc_window, hdc, PM_WO );
\r
2949 CreatePieceMaskFromFont( hdc_window, hdc, PM_WG );
\r
2950 CreatePieceMaskFromFont( hdc_window, hdc, PM_WM );
\r
2951 CreatePieceMaskFromFont( hdc_window, hdc, PM_WSG );
\r
2952 CreatePieceMaskFromFont( hdc_window, hdc, PM_WV );
\r
2953 CreatePieceMaskFromFont( hdc_window, hdc, PM_WAB );
\r
2954 CreatePieceMaskFromFont( hdc_window, hdc, PM_WD );
\r
2955 CreatePieceMaskFromFont( hdc_window, hdc, PM_WL );
\r
2956 CreatePieceMaskFromFont( hdc_window, hdc, PM_WS );
\r
2957 CreatePieceMaskFromFont( hdc_window, hdc, PM_BA );
\r
2958 CreatePieceMaskFromFont( hdc_window, hdc, PM_BC );
\r
2959 CreatePieceMaskFromFont( hdc_window, hdc, PM_BF );
\r
2960 CreatePieceMaskFromFont( hdc_window, hdc, PM_BH );
\r
2961 CreatePieceMaskFromFont( hdc_window, hdc, PM_BE );
\r
2962 CreatePieceMaskFromFont( hdc_window, hdc, PM_BW );
\r
2963 CreatePieceMaskFromFont( hdc_window, hdc, PM_BU );
\r
2964 CreatePieceMaskFromFont( hdc_window, hdc, PM_BO );
\r
2965 CreatePieceMaskFromFont( hdc_window, hdc, PM_BG );
\r
2966 CreatePieceMaskFromFont( hdc_window, hdc, PM_BM );
\r
2967 CreatePieceMaskFromFont( hdc_window, hdc, PM_BSG );
\r
2968 CreatePieceMaskFromFont( hdc_window, hdc, PM_BV );
\r
2969 CreatePieceMaskFromFont( hdc_window, hdc, PM_BAB );
\r
2970 CreatePieceMaskFromFont( hdc_window, hdc, PM_BD );
\r
2971 CreatePieceMaskFromFont( hdc_window, hdc, PM_BL );
\r
2972 CreatePieceMaskFromFont( hdc_window, hdc, PM_BS );
\r
2974 for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */
\r
2975 if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */
\r
2976 CreatePieceMaskFromFont( hdc_window, hdc, i );
\r
2978 SelectObject( hdc, hfont_old );
\r
2980 fontBitmapSquareSize = squareSize;
\r
2984 if( hdc != NULL ) {
\r
2988 if( hdc_window != NULL ) {
\r
2989 ReleaseDC( hwndMain, hdc_window );
\r
2994 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)
\r
2998 sprintf(name, "%s%d%s", piece, squareSize, suffix);
\r
2999 if (gameInfo.event &&
\r
3000 strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&
\r
3001 strcmp(name, "k80s") == 0) {
\r
3002 strcpy(name, "tim");
\r
3004 return LoadBitmap(hinst, name);
\r
3008 /* Insert a color into the program's logical palette
\r
3009 structure. This code assumes the given color is
\r
3010 the result of the RGB or PALETTERGB macro, and it
\r
3011 knows how those macros work (which is documented).
\r
3014 InsertInPalette(COLORREF color)
\r
3016 LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);
\r
3018 if (pLogPal->palNumEntries++ >= PALETTESIZE) {
\r
3019 DisplayFatalError("Too many colors", 0, 1);
\r
3020 pLogPal->palNumEntries--;
\r
3024 pe->peFlags = (char) 0;
\r
3025 pe->peRed = (char) (0xFF & color);
\r
3026 pe->peGreen = (char) (0xFF & (color >> 8));
\r
3027 pe->peBlue = (char) (0xFF & (color >> 16));
\r
3033 InitDrawingColors()
\r
3035 if (pLogPal == NULL) {
\r
3036 /* Allocate enough memory for a logical palette with
\r
3037 * PALETTESIZE entries and set the size and version fields
\r
3038 * of the logical palette structure.
\r
3040 pLogPal = (NPLOGPALETTE)
\r
3041 LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +
\r
3042 (sizeof(PALETTEENTRY) * (PALETTESIZE))));
\r
3043 pLogPal->palVersion = 0x300;
\r
3045 pLogPal->palNumEntries = 0;
\r
3047 InsertInPalette(lightSquareColor);
\r
3048 InsertInPalette(darkSquareColor);
\r
3049 InsertInPalette(whitePieceColor);
\r
3050 InsertInPalette(blackPieceColor);
\r
3051 InsertInPalette(highlightSquareColor);
\r
3052 InsertInPalette(premoveHighlightColor);
\r
3054 /* create a logical color palette according the information
\r
3055 * in the LOGPALETTE structure.
\r
3057 hPal = CreatePalette((LPLOGPALETTE) pLogPal);
\r
3059 lightSquareBrush = CreateSolidBrush(lightSquareColor);
\r
3060 blackSquareBrush = CreateSolidBrush(blackPieceColor);
\r
3061 darkSquareBrush = CreateSolidBrush(darkSquareColor);
\r
3062 whitePieceBrush = CreateSolidBrush(whitePieceColor);
\r
3063 blackPieceBrush = CreateSolidBrush(blackPieceColor);
\r
3064 iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
\r
3065 explodeBrush = CreateSolidBrush(highlightSquareColor); // [HGM] atomic
\r
3066 /* [AS] Force rendering of the font-based pieces */
\r
3067 if( fontBitmapSquareSize > 0 ) {
\r
3068 fontBitmapSquareSize = 0;
\r
3074 BoardWidth(int boardSize, int n)
\r
3075 { /* [HGM] argument n added to allow different width and height */
\r
3076 int lineGap = sizeInfo[boardSize].lineGap;
\r
3078 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3079 lineGap = appData.overrideLineGap;
\r
3082 return (n + 1) * lineGap +
\r
3083 n * sizeInfo[boardSize].squareSize;
\r
3086 /* Respond to board resize by dragging edge */
\r
3088 ResizeBoard(int newSizeX, int newSizeY, int flags)
\r
3090 BoardSize newSize = NUM_SIZES - 1;
\r
3091 static int recurse = 0;
\r
3092 if (IsIconic(hwndMain)) return;
\r
3093 if (recurse > 0) return;
\r
3095 while (newSize > 0) {
\r
3096 InitDrawingSizes(newSize+1000, 0); // [HGM] kludge to update sizeInfo without visible effects
\r
3097 if(newSizeX >= sizeInfo[newSize].cliWidth &&
\r
3098 newSizeY >= sizeInfo[newSize].cliHeight) break;
\r
3101 boardSize = newSize;
\r
3102 InitDrawingSizes(boardSize, flags);
\r
3109 InitDrawingSizes(BoardSize boardSize, int flags)
\r
3111 int i, boardWidth, boardHeight; /* [HGM] height treated separately */
\r
3112 ChessSquare piece;
\r
3113 static int oldBoardSize = -1, oldTinyLayout = 0;
\r
3115 SIZE clockSize, messageSize;
\r
3117 char buf[MSG_SIZ];
\r
3119 HMENU hmenu = GetMenu(hwndMain);
\r
3120 RECT crect, wrect, oldRect;
\r
3122 LOGBRUSH logbrush;
\r
3124 int suppressVisibleEffects = 0; // [HGM] kludge to request updating sizeInfo only
\r
3125 if((int)boardSize >= 1000 ) { boardSize -= 1000; suppressVisibleEffects = 1; }
\r
3127 /* [HGM] call with -2 uses old size (for if nr of files, ranks changes) */
\r
3128 if(boardSize == (BoardSize)(-2) ) boardSize = oldBoardSize;
\r
3130 oldRect.left = boardX; //[HGM] placement: remember previous window params
\r
3131 oldRect.top = boardY;
\r
3132 oldRect.right = boardX + winWidth;
\r
3133 oldRect.bottom = boardY + winHeight;
\r
3135 tinyLayout = sizeInfo[boardSize].tinyLayout;
\r
3136 smallLayout = sizeInfo[boardSize].smallLayout;
\r
3137 squareSize = sizeInfo[boardSize].squareSize;
\r
3138 lineGap = sizeInfo[boardSize].lineGap;
\r
3139 minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted */
\r
3141 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3142 lineGap = appData.overrideLineGap;
\r
3145 if (tinyLayout != oldTinyLayout) {
\r
3146 long style = GetWindowLong(hwndMain, GWL_STYLE);
\r
3148 style &= ~WS_SYSMENU;
\r
3149 InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize,
\r
3150 "&Minimize\tCtrl+F4");
\r
3152 style |= WS_SYSMENU;
\r
3153 RemoveMenu(hmenu, IDM_Minimize, MF_BYCOMMAND);
\r
3155 SetWindowLong(hwndMain, GWL_STYLE, style);
\r
3157 for (i=0; menuBarText[tinyLayout][i]; i++) {
\r
3158 ModifyMenu(hmenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP,
\r
3159 (UINT)GetSubMenu(hmenu, i), menuBarText[tinyLayout][i]);
\r
3161 DrawMenuBar(hwndMain);
\r
3164 boardWidth = BoardWidth(boardSize, BOARD_WIDTH);
\r
3165 boardHeight = BoardWidth(boardSize, BOARD_HEIGHT);
\r
3167 /* Get text area sizes */
\r
3168 hdc = GetDC(hwndMain);
\r
3169 if (appData.clockMode) {
\r
3170 sprintf(buf, "White: %s", TimeString(23*60*60*1000L));
\r
3172 sprintf(buf, "White");
\r
3174 oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);
\r
3175 GetTextExtentPoint(hdc, buf, strlen(buf), &clockSize);
\r
3176 SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);
\r
3177 str = "We only care about the height here";
\r
3178 GetTextExtentPoint(hdc, str, strlen(str), &messageSize);
\r
3179 SelectObject(hdc, oldFont);
\r
3180 ReleaseDC(hwndMain, hdc);
\r
3182 /* Compute where everything goes */
\r
3183 if((first.programLogo || second.programLogo) && !tinyLayout) {
\r
3184 /* [HGM] logo: if either logo is on, reserve space for it */
\r
3185 logoHeight = 2*clockSize.cy;
\r
3186 leftLogoRect.left = OUTER_MARGIN;
\r
3187 leftLogoRect.right = leftLogoRect.left + 4*clockSize.cy;
\r
3188 leftLogoRect.top = OUTER_MARGIN;
\r
3189 leftLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3191 rightLogoRect.right = OUTER_MARGIN + boardWidth;
\r
3192 rightLogoRect.left = rightLogoRect.right - 4*clockSize.cy;
\r
3193 rightLogoRect.top = OUTER_MARGIN;
\r
3194 rightLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3197 whiteRect.left = leftLogoRect.right;
\r