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
107 void DisplayMove P((int moveNumber));
\r
108 Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen));
\r
109 int HtmlHelp( HWND hwnd, LPCSTR helpFile, UINT action, DWORD data );
\r
112 ChessSquare piece;
\r
113 POINT pos; /* window coordinates of current pos */
\r
114 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
115 POINT from; /* board coordinates of the piece's orig pos */
\r
116 POINT to; /* board coordinates of the piece's new pos */
\r
119 static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };
\r
122 POINT start; /* window coordinates of start pos */
\r
123 POINT pos; /* window coordinates of current pos */
\r
124 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
125 POINT from; /* board coordinates of the piece's orig pos */
\r
128 static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} };
\r
131 POINT sq[2]; /* board coordinates of from, to squares */
\r
134 static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} };
\r
135 static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };
\r
137 typedef struct { // [HGM] atomic
\r
138 int fromX, fromY, toX, toY, radius;
\r
141 static ExplodeInfo explodeInfo;
\r
143 /* Window class names */
\r
144 char szAppName[] = "WinBoard";
\r
145 char szConsoleName[] = "WBConsole";
\r
147 /* Title bar text */
\r
148 char szTitle[] = "WinBoard";
\r
149 char szConsoleTitle[] = "I C S Interaction";
\r
152 char *settingsFileName;
\r
153 BOOLEAN saveSettingsOnExit;
\r
154 char installDir[MSG_SIZ];
\r
156 BoardSize boardSize;
\r
157 BOOLEAN chessProgram;
\r
158 static int boardX, boardY;
\r
159 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
\r
160 static int squareSize, lineGap, minorSize;
\r
161 static int winWidth, winHeight, winW, winH;
\r
162 static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo
\r
163 static int logoHeight = 0;
\r
164 static char messageText[MESSAGE_TEXT_MAX];
\r
165 static int clockTimerEvent = 0;
\r
166 static int loadGameTimerEvent = 0;
\r
167 static int analysisTimerEvent = 0;
\r
168 static DelayedEventCallback delayedTimerCallback;
\r
169 static int delayedTimerEvent = 0;
\r
170 static int buttonCount = 2;
\r
171 char *icsTextMenuString;
\r
173 char *firstChessProgramNames;
\r
174 char *secondChessProgramNames;
\r
176 #define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */
\r
178 #define PALETTESIZE 256
\r
180 HINSTANCE hInst; /* current instance */
\r
181 HWND hwndMain = NULL; /* root window*/
\r
182 HWND hwndConsole = NULL;
\r
183 BOOLEAN alwaysOnTop = FALSE;
\r
185 COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
\r
186 blackPieceColor, highlightSquareColor, premoveHighlightColor;
\r
188 ColorClass currentColorClass;
\r
190 HWND hCommPort = NULL; /* currently open comm port */
\r
191 static HWND hwndPause; /* pause button */
\r
192 static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */
\r
193 static HBRUSH lightSquareBrush, darkSquareBrush,
\r
194 blackSquareBrush, /* [HGM] for band between board and holdings */
\r
195 explodeBrush, /* [HGM] atomic */
\r
196 whitePieceBrush, blackPieceBrush, iconBkgndBrush /*, outlineBrush*/;
\r
197 static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];
\r
198 static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];
\r
199 static HPEN gridPen = NULL;
\r
200 static HPEN highlightPen = NULL;
\r
201 static HPEN premovePen = NULL;
\r
202 static NPLOGPALETTE pLogPal;
\r
203 static BOOL paletteChanged = FALSE;
\r
204 static HICON iconWhite, iconBlack, iconCurrent;
\r
205 static int doingSizing = FALSE;
\r
206 static int lastSizing = 0;
\r
207 static int prevStderrPort;
\r
208 static HBITMAP userLogo;
\r
210 /* [AS] Support for background textures */
\r
211 #define BACK_TEXTURE_MODE_DISABLED 0
\r
212 #define BACK_TEXTURE_MODE_PLAIN 1
\r
213 #define BACK_TEXTURE_MODE_FULL_RANDOM 2
\r
215 static HBITMAP liteBackTexture = NULL;
\r
216 static HBITMAP darkBackTexture = NULL;
\r
217 static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
218 static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
219 static int backTextureSquareSize = 0;
\r
220 static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_SIZE][BOARD_SIZE];
\r
222 #if __GNUC__ && !defined(_winmajor)
\r
223 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */
\r
225 #define oldDialog (_winmajor < 4)
\r
228 char *defaultTextAttribs[] =
\r
230 COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,
\r
231 COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,
\r
241 int cliWidth, cliHeight;
\r
244 SizeInfo sizeInfo[] =
\r
246 { "tiny", 21, 0, 1, 1, 0, 0 },
\r
247 { "teeny", 25, 1, 1, 1, 0, 0 },
\r
248 { "dinky", 29, 1, 1, 1, 0, 0 },
\r
249 { "petite", 33, 1, 1, 1, 0, 0 },
\r
250 { "slim", 37, 2, 1, 0, 0, 0 },
\r
251 { "small", 40, 2, 1, 0, 0, 0 },
\r
252 { "mediocre", 45, 2, 1, 0, 0, 0 },
\r
253 { "middling", 49, 2, 0, 0, 0, 0 },
\r
254 { "average", 54, 2, 0, 0, 0, 0 },
\r
255 { "moderate", 58, 3, 0, 0, 0, 0 },
\r
256 { "medium", 64, 3, 0, 0, 0, 0 },
\r
257 { "bulky", 72, 3, 0, 0, 0, 0 },
\r
258 { "large", 80, 3, 0, 0, 0, 0 },
\r
259 { "big", 87, 3, 0, 0, 0, 0 },
\r
260 { "huge", 95, 3, 0, 0, 0, 0 },
\r
261 { "giant", 108, 3, 0, 0, 0, 0 },
\r
262 { "colossal", 116, 4, 0, 0, 0, 0 },
\r
263 { "titanic", 129, 4, 0, 0, 0, 0 },
\r
264 { NULL, 0, 0, 0, 0, 0, 0 }
\r
267 #define MF(x) {x, {{0,}, 0. }, {0, }, 0}
\r
268 MyFont fontRec[NUM_SIZES][NUM_FONTS] =
\r
270 { 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
271 { 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
272 { 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
273 { 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
274 { 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
275 { 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
276 { 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
277 { 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
278 { 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
279 { 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
280 { 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
281 { 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
282 { 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
283 { 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
284 { 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
285 { 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
286 { 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
287 { 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
290 MyFont *font[NUM_SIZES][NUM_FONTS];
\r
299 #define BUTTON_WIDTH (tinyLayout ? 16 : 32)
\r
300 #define N_BUTTONS 5
\r
302 MyButtonDesc buttonDesc[N_BUTTONS] =
\r
304 {"<<", IDM_ToStart, NULL, NULL},
\r
305 {"<", IDM_Backward, NULL, NULL},
\r
306 {"P", IDM_Pause, NULL, NULL},
\r
307 {">", IDM_Forward, NULL, NULL},
\r
308 {">>", IDM_ToEnd, NULL, NULL},
\r
311 int tinyLayout = 0, smallLayout = 0;
\r
312 #define MENU_BAR_ITEMS 6
\r
313 char *menuBarText[2][MENU_BAR_ITEMS+1] = {
\r
314 { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },
\r
315 { "&F", "&M", "&A", "&S", "&O", "&H", NULL },
\r
319 MySound sounds[(int)NSoundClasses];
\r
320 MyTextAttribs textAttribs[(int)NColorClasses];
\r
322 MyColorizeAttribs colorizeAttribs[] = {
\r
323 { (COLORREF)0, 0, "Shout Text" },
\r
324 { (COLORREF)0, 0, "SShout/CShout" },
\r
325 { (COLORREF)0, 0, "Channel 1 Text" },
\r
326 { (COLORREF)0, 0, "Channel Text" },
\r
327 { (COLORREF)0, 0, "Kibitz Text" },
\r
328 { (COLORREF)0, 0, "Tell Text" },
\r
329 { (COLORREF)0, 0, "Challenge Text" },
\r
330 { (COLORREF)0, 0, "Request Text" },
\r
331 { (COLORREF)0, 0, "Seek Text" },
\r
332 { (COLORREF)0, 0, "Normal Text" },
\r
333 { (COLORREF)0, 0, "None" }
\r
338 static char *commentTitle;
\r
339 static char *commentText;
\r
340 static int commentIndex;
\r
341 static Boolean editComment = FALSE;
\r
342 HWND commentDialog = NULL;
\r
343 BOOLEAN commentDialogUp = FALSE;
\r
344 static int commentX, commentY, commentH, commentW;
\r
346 static char *analysisTitle;
\r
347 static char *analysisText;
\r
348 HWND analysisDialog = NULL;
\r
349 BOOLEAN analysisDialogUp = FALSE;
\r
350 static int analysisX, analysisY, analysisH, analysisW;
\r
352 char errorTitle[MSG_SIZ];
\r
353 char errorMessage[2*MSG_SIZ];
\r
354 HWND errorDialog = NULL;
\r
355 BOOLEAN moveErrorMessageUp = FALSE;
\r
356 BOOLEAN consoleEcho = TRUE;
\r
357 CHARFORMAT consoleCF;
\r
358 COLORREF consoleBackgroundColor;
\r
360 char *programVersion;
\r
366 typedef int CPKind;
\r
375 SOCKET sock2; /* stderr socket for OpenRcmd */
\r
378 #define INPUT_SOURCE_BUF_SIZE 4096
\r
380 typedef struct _InputSource {
\r
387 char buf[INPUT_SOURCE_BUF_SIZE];
\r
391 InputCallback func;
\r
392 struct _InputSource *second; /* for stderr thread on CPRcmd */
\r
396 InputSource *consoleInputSource;
\r
401 VOID ConsoleOutput(char* data, int length, int forceVisible);
\r
402 VOID ConsoleCreate();
\r
404 ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
405 VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
\r
406 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
\r
407 VOID ParseCommSettings(char *arg, DCB *dcb);
\r
409 StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
410 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
\r
411 void ParseIcsTextMenu(char *icsTextMenuString);
\r
412 VOID PopUpMoveDialog(char firstchar);
\r
413 VOID PopUpNameDialog(char firstchar);
\r
414 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
\r
418 int GameListOptions();
\r
420 HWND moveHistoryDialog = NULL;
\r
421 BOOLEAN moveHistoryDialogUp = FALSE;
\r
423 WindowPlacement wpMoveHistory;
\r
425 HWND evalGraphDialog = NULL;
\r
426 BOOLEAN evalGraphDialogUp = FALSE;
\r
428 WindowPlacement wpEvalGraph;
\r
430 HWND engineOutputDialog = NULL;
\r
431 BOOLEAN engineOutputDialogUp = FALSE;
\r
433 WindowPlacement wpEngineOutput;
\r
434 WindowPlacement wpGameList;
\r
435 WindowPlacement wpConsole;
\r
437 VOID MoveHistoryPopUp();
\r
438 VOID MoveHistoryPopDown();
\r
439 VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
440 BOOL MoveHistoryIsUp();
\r
442 VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
443 VOID EvalGraphPopUp();
\r
444 VOID EvalGraphPopDown();
\r
445 BOOL EvalGraphIsUp();
\r
447 VOID EngineOutputPopUp();
\r
448 VOID EngineOutputPopDown();
\r
449 BOOL EngineOutputIsUp();
\r
450 VOID EngineOutputUpdate( FrontEndProgramStats * stats );
\r
452 VOID GothicPopUp(char *title, VariantClass variant);
\r
454 * Setting "frozen" should disable all user input other than deleting
\r
455 * the window. We do this while engines are initializing themselves.
\r
457 static int frozen = 0;
\r
458 static int oldMenuItemState[MENU_BAR_ITEMS];
\r
464 if (frozen) return;
\r
466 hmenu = GetMenu(hwndMain);
\r
467 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
468 oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
\r
470 DrawMenuBar(hwndMain);
\r
473 /* Undo a FreezeUI */
\r
479 if (!frozen) return;
\r
481 hmenu = GetMenu(hwndMain);
\r
482 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
483 EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
\r
485 DrawMenuBar(hwndMain);
\r
488 static int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them
\r
490 /* JAWS preparation patch (WinBoard for the sight impaired). Define required insertions as empty */
\r
495 #define JAWS_ALT_INTERCEPT
\r
496 #define JAWS_KB_NAVIGATION
\r
497 #define JAWS_MENU_ITEMS
\r
498 #define JAWS_SILENCE
\r
499 #define JAWS_REPLAY
\r
500 #define JAWS_DELETE(X) X
\r
501 #define SAYMACHINEMOVE()
\r
505 /*---------------------------------------------------------------------------*\
\r
509 \*---------------------------------------------------------------------------*/
\r
512 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
\r
513 LPSTR lpCmdLine, int nCmdShow)
\r
516 HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
\r
517 // INITCOMMONCONTROLSEX ex;
\r
521 LoadLibrary("RICHED32.DLL");
\r
522 consoleCF.cbSize = sizeof(CHARFORMAT);
\r
524 if (!InitApplication(hInstance)) {
\r
527 if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
\r
533 // InitCommonControlsEx(&ex);
\r
534 InitCommonControls();
\r
536 hAccelMain = LoadAccelerators (hInstance, szAppName);
\r
537 hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
\r
538 hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
\r
540 /* Acquire and dispatch messages until a WM_QUIT message is received. */
\r
542 while (GetMessage(&msg, /* message structure */
\r
543 NULL, /* handle of window receiving the message */
\r
544 0, /* lowest message to examine */
\r
545 0)) /* highest message to examine */
\r
548 if(msg.message == WM_CHAR && msg.wParam == '\t') {
\r
549 // [HGM] navigate: switch between all windows with tab
\r
550 HWND e1 = NULL, e2 = NULL, mh = NULL, hInput = NULL, hText = NULL;
\r
551 int i, currentElement = 0;
\r
553 // first determine what element of the chain we come from (if any)
\r
554 if(appData.icsActive) {
\r
555 hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);
\r
556 hText = GetDlgItem(hwndConsole, OPT_ConsoleText);
\r
558 if(engineOutputDialog && EngineOutputIsUp()) {
\r
559 e1 = GetDlgItem(engineOutputDialog, IDC_EngineMemo1);
\r
560 e2 = GetDlgItem(engineOutputDialog, IDC_EngineMemo2);
\r
562 if(moveHistoryDialog && MoveHistoryIsUp()) {
\r
563 mh = GetDlgItem(moveHistoryDialog, IDC_MoveHistory);
\r
565 if(msg.hwnd == hwndMain) currentElement = 7 ; else
\r
566 if(msg.hwnd == engineOutputDialog) currentElement = 2; else
\r
567 if(msg.hwnd == e1) currentElement = 2; else
\r
568 if(msg.hwnd == e2) currentElement = 3; else
\r
569 if(msg.hwnd == moveHistoryDialog) currentElement = 4; else
\r
570 if(msg.hwnd == mh) currentElement = 4; else
\r
571 if(msg.hwnd == evalGraphDialog) currentElement = 7; else
\r
572 if(msg.hwnd == hText) currentElement = 5; else
\r
573 if(msg.hwnd == hInput) currentElement = 6; else
\r
574 for (i = 0; i < N_BUTTONS; i++) {
\r
575 if (buttonDesc[i].hwnd == msg.hwnd) { currentElement = 1; break; }
\r
578 // determine where to go to
\r
579 if(currentElement) { HWND h = NULL; int direction = GetKeyState(VK_SHIFT) < 0 ? -1 : 1;
\r
581 currentElement = (currentElement + direction) % 7;
\r
582 switch(currentElement) {
\r
584 h = hwndMain; break; // passing this case always makes the loop exit
\r
586 h = buttonDesc[0].hwnd; break; // could be NULL
\r
588 if(!EngineOutputIsUp()) continue; // skip closed auxiliary windows
\r
591 if(!EngineOutputIsUp()) continue;
\r
594 if(!MoveHistoryIsUp()) continue;
\r
596 // case 5: // input to eval graph does not seem to get here!
\r
597 // if(!EvalGraphIsUp()) continue;
\r
598 // h = evalGraphDialog; break;
\r
600 if(!appData.icsActive) continue;
\r
604 if(!appData.icsActive) continue;
\r
610 if(currentElement > 4 && IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);
\r
611 if(currentElement < 5 && IsIconic(hwndMain)) ShowWindow(hwndMain, SW_RESTORE); // all open together
\r
614 continue; // this message now has been processed
\r
618 if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
\r
619 !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
\r
620 !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
\r
621 !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
\r
622 !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
\r
623 !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
\r
624 !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
\r
625 !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) &&
\r
626 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
\r
627 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
\r
628 TranslateMessage(&msg); /* Translates virtual key codes */
\r
629 DispatchMessage(&msg); /* Dispatches message to window */
\r
634 return (msg.wParam); /* Returns the value from PostQuitMessage */
\r
637 /*---------------------------------------------------------------------------*\
\r
639 * Initialization functions
\r
641 \*---------------------------------------------------------------------------*/
\r
645 { // update user logo if necessary
\r
646 static char oldUserName[MSG_SIZ], *curName;
\r
648 if(appData.autoLogo) {
\r
649 curName = UserName();
\r
650 if(strcmp(curName, oldUserName)) {
\r
651 sprintf(oldUserName, "logos\\%s.bmp", curName);
\r
652 userLogo = LoadImage( 0, oldUserName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
653 strcpy(oldUserName, curName);
\r
659 InitApplication(HINSTANCE hInstance)
\r
663 /* Fill in window class structure with parameters that describe the */
\r
666 wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
\r
667 wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
\r
668 wc.cbClsExtra = 0; /* No per-class extra data. */
\r
669 wc.cbWndExtra = 0; /* No per-window extra data. */
\r
670 wc.hInstance = hInstance; /* Owner of this class */
\r
671 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
672 wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
\r
673 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
\r
674 wc.lpszMenuName = szAppName; /* Menu name from .RC */
\r
675 wc.lpszClassName = szAppName; /* Name to register as */
\r
677 /* Register the window class and return success/failure code. */
\r
678 if (!RegisterClass(&wc)) return FALSE;
\r
680 wc.style = CS_HREDRAW | CS_VREDRAW;
\r
681 wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
\r
683 wc.cbWndExtra = DLGWINDOWEXTRA;
\r
684 wc.hInstance = hInstance;
\r
685 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
686 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
\r
687 wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
\r
688 wc.lpszMenuName = NULL;
\r
689 wc.lpszClassName = szConsoleName;
\r
691 if (!RegisterClass(&wc)) return FALSE;
\r
696 /* Set by InitInstance, used by EnsureOnScreen */
\r
697 int screenHeight, screenWidth;
\r
700 EnsureOnScreen(int *x, int *y, int minX, int minY)
\r
702 // int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
\r
703 /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
\r
704 if (*x > screenWidth - 32) *x = 0;
\r
705 if (*y > screenHeight - 32) *y = 0;
\r
706 if (*x < minX) *x = minX;
\r
707 if (*y < minY) *y = minY;
\r
711 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
\r
713 HWND hwnd; /* Main window handle. */
\r
715 WINDOWPLACEMENT wp;
\r
718 hInst = hInstance; /* Store instance handle in our global variable */
\r
720 if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
\r
721 *filepart = NULLCHAR;
\r
723 GetCurrentDirectory(MSG_SIZ, installDir);
\r
725 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise
\r
726 screenWidth = screenHeight = 1000; // [HGM] placement: kludge to allow calling EnsureOnScreen from InitAppData
\r
727 InitAppData(lpCmdLine); /* Get run-time parameters */
\r
728 if (appData.debugMode) {
\r
729 debugFP = fopen(appData.nameOfDebugFile, "w");
\r
730 setbuf(debugFP, NULL);
\r
735 // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()
\r
736 // InitEngineUCI( installDir, &second );
\r
738 /* Create a main window for this application instance. */
\r
739 hwnd = CreateWindow(szAppName, szTitle,
\r
740 (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
\r
741 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
\r
742 NULL, NULL, hInstance, NULL);
\r
745 /* If window could not be created, return "failure" */
\r
750 /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */
\r
751 if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {
\r
752 first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
754 if (first.programLogo == NULL && appData.debugMode) {
\r
755 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );
\r
757 } else if(appData.autoLogo) {
\r
758 if(appData.firstDirectory && appData.firstDirectory[0]) {
\r
760 sprintf(buf, "%s/logo.bmp", appData.firstDirectory);
\r
761 first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
765 if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {
\r
766 second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
768 if (second.programLogo == NULL && appData.debugMode) {
\r
769 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );
\r
771 } else if(appData.autoLogo) {
\r
773 if(appData.icsActive) { // [HGM] logo: in ICS mode second can be used for ICS
\r
774 sprintf(buf, "logos\\%s.bmp", appData.icsHost);
\r
775 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
777 if(appData.secondDirectory && appData.secondDirectory[0]) {
\r
778 sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);
\r
779 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
785 iconWhite = LoadIcon(hInstance, "icon_white");
\r
786 iconBlack = LoadIcon(hInstance, "icon_black");
\r
787 iconCurrent = iconWhite;
\r
788 InitDrawingColors();
\r
789 screenHeight = GetSystemMetrics(SM_CYSCREEN);
\r
790 screenWidth = GetSystemMetrics(SM_CXSCREEN);
\r
791 for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
\r
792 /* Compute window size for each board size, and use the largest
\r
793 size that fits on this screen as the default. */
\r
794 InitDrawingSizes((BoardSize)(ibs+1000), 0);
\r
795 if (boardSize == (BoardSize)-1 &&
\r
796 winH <= screenHeight
\r
797 - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10
\r
798 && winW <= screenWidth) {
\r
799 boardSize = (BoardSize)ibs;
\r
803 InitDrawingSizes(boardSize, 0);
\r
805 buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
\r
807 /* [AS] Load textures if specified */
\r
808 ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );
\r
810 if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {
\r
811 liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
812 liteBackTextureMode = appData.liteBackTextureMode;
\r
814 if (liteBackTexture == NULL && appData.debugMode) {
\r
815 fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );
\r
819 if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {
\r
820 darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
821 darkBackTextureMode = appData.darkBackTextureMode;
\r
823 if (darkBackTexture == NULL && appData.debugMode) {
\r
824 fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );
\r
828 mysrandom( (unsigned) time(NULL) );
\r
830 /* [AS] Restore layout */
\r
831 if( wpMoveHistory.visible ) {
\r
832 MoveHistoryPopUp();
\r
835 if( wpEvalGraph.visible ) {
\r
839 if( wpEngineOutput.visible ) {
\r
840 EngineOutputPopUp();
\r
845 /* Make the window visible; update its client area; and return "success" */
\r
846 EnsureOnScreen(&boardX, &boardY, minX, minY);
\r
847 wp.length = sizeof(WINDOWPLACEMENT);
\r
849 wp.showCmd = nCmdShow;
\r
850 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
\r
851 wp.rcNormalPosition.left = boardX;
\r
852 wp.rcNormalPosition.right = boardX + winWidth;
\r
853 wp.rcNormalPosition.top = boardY;
\r
854 wp.rcNormalPosition.bottom = boardY + winHeight;
\r
855 SetWindowPlacement(hwndMain, &wp);
\r
857 SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
858 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
862 SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
863 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
865 ShowWindow(hwndConsole, nCmdShow);
\r
867 UpdateWindow(hwnd);
\r
875 ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
\r
876 ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
\r
877 ArgSettingsFilename,
\r
878 ArgX, ArgY, ArgZ // [HGM] placement: for window-placement options stored relative to main window
\r
886 String *pString; // ArgString
\r
887 int *pInt; // ArgInt
\r
888 float *pFloat; // ArgFloat
\r
889 Boolean *pBoolean; // ArgBoolean
\r
890 COLORREF *pColor; // ArgColor
\r
891 ColorClass cc; // ArgAttribs
\r
892 String *pFilename; // ArgFilename
\r
893 BoardSize *pBoardSize; // ArgBoardSize
\r
894 int whichFont; // ArgFont
\r
895 DCB *pDCB; // ArgCommSettings
\r
896 String *pFilename; // ArgSettingsFilename
\r
904 ArgDescriptor argDescriptors[] = {
\r
905 /* positional arguments */
\r
906 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
907 { "", ArgNone, NULL },
\r
908 /* keyword arguments */
\r
909 { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },
\r
910 { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },
\r
911 { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },
\r
912 { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },
\r
913 { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },
\r
914 { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },
\r
915 { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },
\r
916 { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },
\r
917 { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },
\r
918 { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },
\r
919 { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },
\r
920 { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },
\r
921 { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },
\r
922 { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },
\r
923 { "initString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
924 { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
925 { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },
\r
926 { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,
\r
928 { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,
\r
930 { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,
\r
932 { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },
\r
933 { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,
\r
935 { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },
\r
936 { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
937 { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
938 { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
939 { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
940 { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },
\r
941 { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },
\r
942 { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
943 { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
944 { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
945 { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
946 { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
947 { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
948 { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
949 { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
950 { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
951 { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
952 /*!!bitmapDirectory?*/
\r
953 { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
954 { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
955 { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
956 { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
957 { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },
\r
958 { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },
\r
959 { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },
\r
960 { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },
\r
961 { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },
\r
962 { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },
\r
963 { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },
\r
964 { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },
\r
965 { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
966 { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
967 { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
968 { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
969 { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
970 { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
971 { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
972 { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
973 { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
974 { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
975 { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
976 { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
977 { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },
\r
978 { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },
\r
979 { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
980 { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
981 { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },
\r
982 { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },
\r
983 { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },
\r
984 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
985 { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
986 { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
987 { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
988 { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },
\r
989 { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },
\r
990 { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },
\r
991 { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },
\r
992 { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
993 { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
994 { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
995 { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
996 { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
997 { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
998 { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
999 { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
1000 { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },
\r
1001 { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },
\r
1002 { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
1003 { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
1004 { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
1005 { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
1006 { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },
\r
1007 { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },
\r
1008 { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
1009 { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
1010 { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },
\r
1011 { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },
\r
1012 { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
1013 { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
1014 { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },
\r
1015 { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },
\r
1016 { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
1017 { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
1018 { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
1019 { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
1020 { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
1021 { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
1022 { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },
\r
1023 { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },
\r
1024 { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
1025 { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
1026 { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },
\r
1027 { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },
\r
1028 { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
1029 { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
1030 { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },
\r
1031 { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1032 { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1033 { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1034 { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },
\r
1035 { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1036 { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1037 { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1038 { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },
\r
1039 { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1040 { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1041 { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1042 { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },
\r
1043 { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1044 { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1045 { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1046 { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors,
\r
1047 FALSE }, /* only so that old WinBoard.ini files from betas can be read */
\r
1048 { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },
\r
1049 { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },
\r
1050 { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },
\r
1051 { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },
\r
1052 { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },
\r
1053 { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },
\r
1054 { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE }, /* [AS] */
\r
1055 { "boardSize", ArgBoardSize, (LPVOID) &boardSize,
\r
1056 TRUE }, /* must come after all fonts */
\r
1057 { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },
\r
1058 { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,
\r
1059 FALSE }, /* historical; kept only so old winboard.ini files will parse */
\r
1060 { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },
\r
1061 { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },
\r
1062 { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
1063 { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
1064 { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },
\r
1065 { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1066 { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1067 { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1068 { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },
\r
1069 { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },
\r
1070 { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
1071 { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
1072 { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },
\r
1073 { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },
\r
1074 { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
1075 { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
1076 { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },
\r
1077 { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },
\r
1078 { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
1079 { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
1080 { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },
\r
1081 { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },
\r
1082 { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
1083 { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
1084 { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },
\r
1085 { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1086 { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1087 { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1089 { "cmailGameName", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
1090 { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
1092 { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },
\r
1093 { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1094 { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1095 { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1096 { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },
\r
1097 { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1098 { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1099 { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1100 { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },
\r
1101 { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },
\r
1102 { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
1103 { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
1104 { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },
\r
1105 { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },
\r
1106 { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
1107 { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
1108 { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },
\r
1109 { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },
\r
1110 { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
1111 { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
1112 { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },
\r
1113 { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },
\r
1114 { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
1115 { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
1116 { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },
\r
1117 { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },
\r
1118 { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
1119 { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
1120 { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },
\r
1121 { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },
\r
1122 { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },
\r
1123 { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1124 { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1125 { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },
\r
1126 { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},
\r
1127 { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},
\r
1128 { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1129 { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1130 { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},
\r
1131 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1132 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1133 { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },
\r
1134 { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1135 { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1136 { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },
\r
1137 { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },
\r
1138 { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1139 { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1140 { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },
\r
1141 { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },
\r
1142 { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },
\r
1143 { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1144 { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1145 { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },
\r
1146 { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },
\r
1147 { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1148 { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1149 { "highlightLastMove", ArgBoolean,
\r
1150 (LPVOID) &appData.highlightLastMove, TRUE },
\r
1151 { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1152 { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1153 { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1154 { "highlightDragging", ArgBoolean,
\r
1155 (LPVOID) &appData.highlightDragging, TRUE },
\r
1156 { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },
\r
1157 { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1158 { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1159 { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },
\r
1160 { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },
\r
1161 { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1162 { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1163 { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },
\r
1164 { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },
\r
1165 { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },
\r
1166 { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },
\r
1167 { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },
\r
1168 { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },
\r
1169 { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },
\r
1170 { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },
\r
1171 { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },
\r
1172 { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },
\r
1173 { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },
\r
1174 { "soundShout", ArgFilename,
\r
1175 (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },
\r
1176 { "soundSShout", ArgFilename,
\r
1177 (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },
\r
1178 { "soundChannel1", ArgFilename,
\r
1179 (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },
\r
1180 { "soundChannel", ArgFilename,
\r
1181 (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },
\r
1182 { "soundKibitz", ArgFilename,
\r
1183 (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },
\r
1184 { "soundTell", ArgFilename,
\r
1185 (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },
\r
1186 { "soundChallenge", ArgFilename,
\r
1187 (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },
\r
1188 { "soundRequest", ArgFilename,
\r
1189 (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },
\r
1190 { "soundSeek", ArgFilename,
\r
1191 (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },
\r
1192 { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },
\r
1193 { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },
\r
1194 { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },
\r
1195 { "soundIcsLoss", ArgFilename,
\r
1196 (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },
\r
1197 { "soundIcsDraw", ArgFilename,
\r
1198 (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },
\r
1199 { "soundIcsUnfinished", ArgFilename,
\r
1200 (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},
\r
1201 { "soundIcsAlarm", ArgFilename,
\r
1202 (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },
\r
1203 { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },
\r
1204 { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },
\r
1205 { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1206 { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1207 { "reuseChessPrograms", ArgBoolean,
\r
1208 (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */
\r
1209 { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },
\r
1210 { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },
\r
1211 { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1212 { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1213 { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },
\r
1214 { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1215 { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1216 { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },
\r
1217 { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },
\r
1218 { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },
\r
1219 { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1220 { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1221 { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },
\r
1222 { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },
\r
1223 { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,
\r
1225 { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,
\r
1227 { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1228 { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1229 { "variant", ArgString, (LPVOID) &appData.variant, FALSE },
\r
1230 { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion, FALSE },
\r
1231 { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,FALSE },
\r
1232 { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },
\r
1233 { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },
\r
1234 { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1235 { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1236 /* [AS] New features */
\r
1237 { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE },
\r
1238 { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE },
\r
1239 { "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE },
\r
1240 { "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE },
\r
1241 { "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE },
\r
1242 { "darkBackTextureFile", ArgString, (LPVOID) &appData.darkBackTextureFile, TRUE },
\r
1243 { "liteBackTextureMode", ArgInt, (LPVOID) &appData.liteBackTextureMode, TRUE },
\r
1244 { "darkBackTextureMode", ArgInt, (LPVOID) &appData.darkBackTextureMode, TRUE },
\r
1245 { "renderPiecesWithFont", ArgString, (LPVOID) &appData.renderPiecesWithFont, TRUE },
\r
1246 { "fontPieceToCharTable", ArgString, (LPVOID) &appData.fontToPieceTable, TRUE },
\r
1247 { "fontPieceBackColorWhite", ArgColor, (LPVOID) &appData.fontBackColorWhite, TRUE },
\r
1248 { "fontPieceForeColorWhite", ArgColor, (LPVOID) &appData.fontForeColorWhite, TRUE },
\r
1249 { "fontPieceBackColorBlack", ArgColor, (LPVOID) &appData.fontBackColorBlack, TRUE },
\r
1250 { "fontPieceForeColorBlack", ArgColor, (LPVOID) &appData.fontForeColorBlack, TRUE },
\r
1251 { "fontPieceSize", ArgInt, (LPVOID) &appData.fontPieceSize, TRUE },
\r
1252 { "overrideLineGap", ArgInt, (LPVOID) &appData.overrideLineGap, TRUE },
\r
1253 { "adjudicateLossThreshold", ArgInt, (LPVOID) &appData.adjudicateLossThreshold, TRUE },
\r
1254 { "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE },
\r
1255 { "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE },
\r
1256 { "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1257 { "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1258 { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },
\r
1259 { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE },
\r
1260 { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE },
\r
1261 { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE },
\r
1262 { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE },
\r
1263 { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE },
\r
1264 { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE },
\r
1265 { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE },
\r
1266 { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE },
\r
1267 { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE },
\r
1268 { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE },
\r
1269 { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE },
\r
1270 { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE },
\r
1271 { "firstIsUCI", ArgBoolean, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1272 { "fUCI", ArgTrue, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1273 { "secondIsUCI", ArgBoolean, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1274 { "sUCI", ArgTrue, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1275 { "firstHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1276 { "fNoOwnBookUCI", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1277 { "firstXBook", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1278 { "secondHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1279 { "sNoOwnBookUCI", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1280 { "secondXBook", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1281 { "polyglotDir", ArgFilename, (LPVOID) &appData.polyglotDir, TRUE },
\r
1282 { "usePolyglotBook", ArgBoolean, (LPVOID) &appData.usePolyglotBook, TRUE },
\r
1283 { "polyglotBook", ArgFilename, (LPVOID) &appData.polyglotBook, TRUE },
\r
1284 { "defaultHashSize", ArgInt, (LPVOID) &appData.defaultHashSize, TRUE },
\r
1285 { "defaultCacheSizeEGTB", ArgInt, (LPVOID) &appData.defaultCacheSizeEGTB, TRUE },
\r
1286 { "defaultPathEGTB", ArgFilename, (LPVOID) &appData.defaultPathEGTB, TRUE },
\r
1288 /* [HGM] board-size, adjudication and misc. options */
\r
1289 { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE },
\r
1290 { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE },
\r
1291 { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE },
\r
1292 { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE },
\r
1293 { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE },
\r
1294 { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE },
\r
1295 { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE },
\r
1296 { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE },
\r
1297 { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE },
\r
1298 { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE },
\r
1299 { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE },
\r
1300 { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE },
\r
1301 { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE },
\r
1302 { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE },
\r
1303 { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE },
\r
1304 { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE },
\r
1305 { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE },
\r
1306 { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE },
\r
1307 { "userName", ArgString, (LPVOID) &appData.userName, FALSE },
\r
1308 { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE },
\r
1309 { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE },
\r
1310 { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE },
\r
1311 { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE },
\r
1312 { "niceEngines", ArgInt, (LPVOID) &appData.niceEngines, TRUE },
\r
1313 { "firstLogo", ArgFilename, (LPVOID) &appData.firstLogo, FALSE },
\r
1314 { "secondLogo", ArgFilename, (LPVOID) &appData.secondLogo, FALSE },
\r
1315 { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE },
\r
1316 { "firstOptions", ArgString, (LPVOID) &appData.firstOptions, FALSE },
\r
1317 { "secondOptions", ArgString, (LPVOID) &appData.secondOptions, FALSE },
\r
1318 { "firstNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride1, FALSE },
\r
1319 { "secondNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride2, FALSE },
\r
1322 { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },
\r
1323 { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },
\r
1324 { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1325 { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1326 { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },
\r
1327 { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },
\r
1328 { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1329 { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1330 { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },
\r
1331 { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },
\r
1332 { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },
\r
1333 { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE },
\r
1334 { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,
\r
1336 { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE },
\r
1337 { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE },
\r
1338 { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE },
\r
1339 { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1340 { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1341 { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE },
\r
1342 { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,
\r
1344 { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1345 { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1346 { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1347 { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE },
\r
1348 { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE },
\r
1349 { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1350 { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1351 { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1352 { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1353 { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE },
\r
1354 { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE },
\r
1355 { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1356 { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1357 { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },
\r
1358 { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },
\r
1359 { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },
\r
1360 { "zippyShortGame", ArgInt, (LPVOID)&appData.zippyShortGame, FALSE },
\r
1361 /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */
\r
1362 { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },
\r
1364 /* [HGM] options for broadcasting and time odds */
\r
1365 { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },
\r
1366 { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },
\r
1367 { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },
\r
1368 { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },
\r
1369 { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },
\r
1370 { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },
\r
1371 { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },
\r
1372 { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },
\r
1373 { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },
\r
1374 { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },
\r
1375 { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE },
\r
1377 // [HGM] placement: put all window layouts last in ini file, but man X,Y before all others
\r
1378 { "minX", ArgZ, (LPVOID) &minX, FALSE }, // [HGM] placement: to make suer auxialary windows can be placed
\r
1379 { "minY", ArgZ, (LPVOID) &minY, FALSE },
\r
1380 { "winWidth", ArgInt, (LPVOID) &winWidth, TRUE }, // [HGM] placement: dummies to remember right & bottom
\r
1381 { "winHeight", ArgInt, (LPVOID) &winHeight, TRUE }, // for attaching auxiliary windows to them
\r
1382 { "x", ArgInt, (LPVOID) &boardX, TRUE },
\r
1383 { "y", ArgInt, (LPVOID) &boardY, TRUE },
\r
1384 { "icsX", ArgX, (LPVOID) &wpConsole.x, TRUE },
\r
1385 { "icsY", ArgY, (LPVOID) &wpConsole.y, TRUE },
\r
1386 { "icsW", ArgInt, (LPVOID) &wpConsole.width, TRUE },
\r
1387 { "icsH", ArgInt, (LPVOID) &wpConsole.height, TRUE },
\r
1388 { "analysisX", ArgX, (LPVOID) &analysisX, FALSE }, // [HGM] placement: analysis window no longer exists
\r
1389 { "analysisY", ArgY, (LPVOID) &analysisY, FALSE }, // provided for compatibility with old ini files
\r
1390 { "analysisW", ArgInt, (LPVOID) &analysisW, FALSE },
\r
1391 { "analysisH", ArgInt, (LPVOID) &analysisH, FALSE },
\r
1392 { "commentX", ArgX, (LPVOID) &commentX, TRUE },
\r
1393 { "commentY", ArgY, (LPVOID) &commentY, TRUE },
\r
1394 { "commentW", ArgInt, (LPVOID) &commentW, TRUE },
\r
1395 { "commentH", ArgInt, (LPVOID) &commentH, TRUE },
\r
1396 { "tagsX", ArgX, (LPVOID) &editTagsX, TRUE },
\r
1397 { "tagsY", ArgY, (LPVOID) &editTagsY, TRUE },
\r
1398 { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },
\r
1399 { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },
\r
1400 { "gameListX", ArgX, (LPVOID) &wpGameList.x, TRUE },
\r
1401 { "gameListY", ArgY, (LPVOID) &wpGameList.y, TRUE },
\r
1402 { "gameListW", ArgInt, (LPVOID) &wpGameList.width, TRUE },
\r
1403 { "gameListH", ArgInt, (LPVOID) &wpGameList.height, TRUE },
\r
1404 /* [AS] Layout stuff */
\r
1405 { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },
\r
1406 { "moveHistoryX", ArgX, (LPVOID) &wpMoveHistory.x, TRUE },
\r
1407 { "moveHistoryY", ArgY, (LPVOID) &wpMoveHistory.y, TRUE },
\r
1408 { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },
\r
1409 { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },
\r
1411 { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },
\r
1412 { "evalGraphX", ArgX, (LPVOID) &wpEvalGraph.x, TRUE },
\r
1413 { "evalGraphY", ArgY, (LPVOID) &wpEvalGraph.y, TRUE },
\r
1414 { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },
\r
1415 { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },
\r
1417 { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },
\r
1418 { "engineOutputX", ArgX, (LPVOID) &wpEngineOutput.x, TRUE },
\r
1419 { "engineOutputY", ArgY, (LPVOID) &wpEngineOutput.y, TRUE },
\r
1420 { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },
\r
1421 { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },
\r
1423 { NULL, ArgNone, NULL, FALSE }
\r
1427 /* Kludge for indirection files on command line */
\r
1428 char* lastIndirectionFilename;
\r
1429 ArgDescriptor argDescriptorIndirection =
\r
1430 { "", ArgSettingsFilename, (LPVOID) NULL, FALSE };
\r
1434 ExitArgError(char *msg, char *badArg)
\r
1436 char buf[MSG_SIZ];
\r
1438 sprintf(buf, "%s %s", msg, badArg);
\r
1439 DisplayFatalError(buf, 0, 2);
\r
1443 /* Command line font name parser. NULL name means do nothing.
\r
1444 Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"
\r
1445 For backward compatibility, syntax without the colon is also
\r
1446 accepted, but font names with digits in them won't work in that case.
\r
1449 ParseFontName(char *name, MyFontParams *mfp)
\r
1452 if (name == NULL) return;
\r
1454 q = strchr(p, ':');
\r
1456 if (q - p >= sizeof(mfp->faceName))
\r
1457 ExitArgError("Font name too long:", name);
\r
1458 memcpy(mfp->faceName, p, q - p);
\r
1459 mfp->faceName[q - p] = NULLCHAR;
\r
1462 q = mfp->faceName;
\r
1463 while (*p && !isdigit(*p)) {
\r
1465 if (q - mfp->faceName >= sizeof(mfp->faceName))
\r
1466 ExitArgError("Font name too long:", name);
\r
1468 while (q > mfp->faceName && q[-1] == ' ') q--;
\r
1471 if (!*p) ExitArgError("Font point size missing:", name);
\r
1472 mfp->pointSize = (float) atof(p);
\r
1473 mfp->bold = (strchr(p, 'b') != NULL);
\r
1474 mfp->italic = (strchr(p, 'i') != NULL);
\r
1475 mfp->underline = (strchr(p, 'u') != NULL);
\r
1476 mfp->strikeout = (strchr(p, 's') != NULL);
\r
1479 /* Color name parser.
\r
1480 X version accepts X color names, but this one
\r
1481 handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */
\r
1483 ParseColorName(char *name)
\r
1485 int red, green, blue, count;
\r
1486 char buf[MSG_SIZ];
\r
1488 count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);
\r
1490 count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d",
\r
1491 &red, &green, &blue);
\r
1494 sprintf(buf, "Can't parse color name %s", name);
\r
1495 DisplayError(buf, 0);
\r
1496 return RGB(0, 0, 0);
\r
1498 return PALETTERGB(red, green, blue);
\r
1502 void ParseAttribs(COLORREF *color, int *effects, char* argValue)
\r
1504 char *e = argValue;
\r
1508 if (*e == 'b') eff |= CFE_BOLD;
\r
1509 else if (*e == 'i') eff |= CFE_ITALIC;
\r
1510 else if (*e == 'u') eff |= CFE_UNDERLINE;
\r
1511 else if (*e == 's') eff |= CFE_STRIKEOUT;
\r
1512 else if (*e == '#' || isdigit(*e)) break;
\r
1516 *color = ParseColorName(e);
\r
1521 ParseBoardSize(char *name)
\r
1523 BoardSize bs = SizeTiny;
\r
1524 while (sizeInfo[bs].name != NULL) {
\r
1525 if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;
\r
1528 ExitArgError("Unrecognized board size value", name);
\r
1529 return bs; /* not reached */
\r
1534 StringGet(void *getClosure)
\r
1536 char **p = (char **) getClosure;
\r
1541 FileGet(void *getClosure)
\r
1544 FILE* f = (FILE*) getClosure;
\r
1547 if (c == '\r') c = getc(f); // work around DOS format files by bypassing the '\r' completely
\r
1554 /* Parse settings file named "name". If file found, return the
\r
1555 full name in fullname and return TRUE; else return FALSE */
\r
1557 ParseSettingsFile(char *name, char fullname[MSG_SIZ])
\r
1561 int ok; char buf[MSG_SIZ];
\r
1563 ok = SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy);
\r
1564 if(!ok && strchr(name, '.') == NULL) { // [HGM] append default file-name extension '.ini' when needed
\r
1565 sprintf(buf, "%s.ini", name);
\r
1566 ok = SearchPath(installDir, buf, NULL, MSG_SIZ, fullname, &dummy);
\r
1569 f = fopen(fullname, "r");
\r
1571 ParseArgs(FileGet, f);
\r
1580 ParseArgs(GetFunc get, void *cl)
\r
1582 char argName[ARG_MAX];
\r
1583 char argValue[ARG_MAX];
\r
1584 ArgDescriptor *ad;
\r
1593 while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);
\r
1594 if (ch == NULLCHAR) break;
\r
1596 /* Comment to end of line */
\r
1598 while (ch != '\n' && ch != NULLCHAR) ch = get(cl);
\r
1600 } else if (ch == '/' || ch == '-') {
\r
1603 while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&
\r
1604 ch != '\n' && ch != '\t') {
\r
1610 for (ad = argDescriptors; ad->argName != NULL; ad++)
\r
1611 if (strcmp(ad->argName, argName + 1) == 0) break;
\r
1613 if (ad->argName == NULL)
\r
1614 ExitArgError("Unrecognized argument", argName);
\r
1616 } else if (ch == '@') {
\r
1617 /* Indirection file */
\r
1618 ad = &argDescriptorIndirection;
\r
1621 /* Positional argument */
\r
1622 ad = &argDescriptors[posarg++];
\r
1623 strcpy(argName, ad->argName);
\r
1626 if (ad->argType == ArgTrue) {
\r
1627 *(Boolean *) ad->argLoc = TRUE;
\r
1630 if (ad->argType == ArgFalse) {
\r
1631 *(Boolean *) ad->argLoc = FALSE;
\r
1635 while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
\r
1636 if (ch == NULLCHAR || ch == '\n') {
\r
1637 ExitArgError("No value provided for argument", argName);
\r
1641 // Quoting with { }. No characters have to (or can) be escaped.
\r
1642 // Thus the string cannot contain a '}' character.
\r
1662 } else if (ch == '\'' || ch == '"') {
\r
1663 // Quoting with ' ' or " ", with \ as escape character.
\r
1664 // Inconvenient for long strings that may contain Windows filenames.
\r
1681 if (ch == start) {
\r
1690 if (ad->argType == ArgFilename
\r
1691 || ad->argType == ArgSettingsFilename) {
\r
1697 ExitArgError("Incomplete \\ escape in value for", argName);
\r
1721 for (i = 0; i < 3; i++) {
\r
1722 if (ch >= '0' && ch <= '7') {
\r
1723 octval = octval*8 + (ch - '0');
\r
1730 *q++ = (char) octval;
\r
1741 while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {
\r
1748 switch (ad->argType) {
\r
1750 *(int *) ad->argLoc = atoi(argValue);
\r
1754 *(int *) ad->argLoc = atoi(argValue) + boardX; // [HGM] placement: translate stored relative to absolute
\r
1758 *(int *) ad->argLoc = atoi(argValue) + boardY; // (this is really kludgey, it should be done where used...)
\r
1762 *(int *) ad->argLoc = atoi(argValue);
\r
1763 EnsureOnScreen(&boardX, &boardY, minX, minY);
\r
1767 *(float *) ad->argLoc = (float) atof(argValue);
\r
1772 *(char **) ad->argLoc = strdup(argValue);
\r
1775 case ArgSettingsFilename:
\r
1777 char fullname[MSG_SIZ];
\r
1778 if (ParseSettingsFile(argValue, fullname)) {
\r
1779 if (ad->argLoc != NULL) {
\r
1780 *(char **) ad->argLoc = strdup(fullname);
\r
1783 if (ad->argLoc != NULL) {
\r
1785 ExitArgError("Failed to open indirection file", argValue);
\r
1792 switch (argValue[0]) {
\r
1795 *(Boolean *) ad->argLoc = TRUE;
\r
1799 *(Boolean *) ad->argLoc = FALSE;
\r
1802 ExitArgError("Unrecognized boolean argument value", argValue);
\r
1808 *(COLORREF *)ad->argLoc = ParseColorName(argValue);
\r
1811 case ArgAttribs: {
\r
1812 ColorClass cc = (ColorClass)ad->argLoc;
\r
1813 ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);
\r
1817 case ArgBoardSize:
\r
1818 *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);
\r
1822 ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);
\r
1825 case ArgCommSettings:
\r
1826 ParseCommSettings(argValue, &dcb);
\r
1830 ExitArgError("Unrecognized argument", argValue);
\r
1839 LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
\r
1841 HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
\r
1842 lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);
\r
1845 lf->lfEscapement = 0;
\r
1846 lf->lfOrientation = 0;
\r
1847 lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;
\r
1848 lf->lfItalic = mfp->italic;
\r
1849 lf->lfUnderline = mfp->underline;
\r
1850 lf->lfStrikeOut = mfp->strikeout;
\r
1851 lf->lfCharSet = DEFAULT_CHARSET;
\r
1852 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
1853 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
1854 lf->lfQuality = DEFAULT_QUALITY;
\r
1855 lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
\r
1856 strcpy(lf->lfFaceName, mfp->faceName);
\r
1860 CreateFontInMF(MyFont *mf)
\r
1862 LFfromMFP(&mf->lf, &mf->mfp);
\r
1863 if (mf->hf) DeleteObject(mf->hf);
\r
1864 mf->hf = CreateFontIndirect(&mf->lf);
\r
1868 SetDefaultTextAttribs()
\r
1871 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1872 ParseAttribs(&textAttribs[cc].color,
\r
1873 &textAttribs[cc].effects,
\r
1874 defaultTextAttribs[cc]);
\r
1879 SetDefaultSounds()
\r
1883 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1884 textAttribs[cc].sound.name = strdup("");
\r
1885 textAttribs[cc].sound.data = NULL;
\r
1887 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1888 sounds[sc].name = strdup("");
\r
1889 sounds[sc].data = NULL;
\r
1891 sounds[(int)SoundBell].name = strdup(SOUND_BELL);
\r
1899 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1900 MyLoadSound(&textAttribs[cc].sound);
\r
1902 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1903 MyLoadSound(&sounds[sc]);
\r
1908 InitAppData(LPSTR lpCmdLine)
\r
1911 char buf[ARG_MAX], currDir[MSG_SIZ];
\r
1914 programName = szAppName;
\r
1916 /* Initialize to defaults */
\r
1917 lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);
\r
1918 darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);
\r
1919 whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);
\r
1920 blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);
\r
1921 highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);
\r
1922 premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);
\r
1923 consoleBackgroundColor = ParseColorName(COLOR_BKGD);
\r
1924 SetDefaultTextAttribs();
\r
1925 SetDefaultSounds();
\r
1926 appData.movesPerSession = MOVES_PER_SESSION;
\r
1927 appData.initString = INIT_STRING;
\r
1928 appData.secondInitString = INIT_STRING;
\r
1929 appData.firstComputerString = COMPUTER_STRING;
\r
1930 appData.secondComputerString = COMPUTER_STRING;
\r
1931 appData.firstChessProgram = FIRST_CHESS_PROGRAM;
\r
1932 appData.secondChessProgram = SECOND_CHESS_PROGRAM;
\r
1933 appData.firstPlaysBlack = FALSE;
\r
1934 appData.noChessProgram = FALSE;
\r
1935 chessProgram = FALSE;
\r
1936 appData.firstHost = FIRST_HOST;
\r
1937 appData.secondHost = SECOND_HOST;
\r
1938 appData.firstDirectory = FIRST_DIRECTORY;
\r
1939 appData.secondDirectory = SECOND_DIRECTORY;
\r
1940 appData.bitmapDirectory = "";
\r
1941 appData.remoteShell = REMOTE_SHELL;
\r
1942 appData.remoteUser = "";
\r
1943 appData.timeDelay = TIME_DELAY;
\r
1944 appData.timeControl = TIME_CONTROL;
\r
1945 appData.timeIncrement = TIME_INCREMENT;
\r
1946 appData.icsActive = FALSE;
\r
1947 appData.icsHost = "";
\r
1948 appData.icsPort = ICS_PORT;
\r
1949 appData.icsCommPort = ICS_COMM_PORT;
\r
1950 appData.icsLogon = ICS_LOGON;
\r
1951 appData.icsHelper = "";
\r
1952 appData.useTelnet = FALSE;
\r
1953 appData.telnetProgram = TELNET_PROGRAM;
\r
1954 appData.gateway = "";
\r
1955 appData.loadGameFile = "";
\r
1956 appData.loadGameIndex = 0;
\r
1957 appData.saveGameFile = "";
\r
1958 appData.autoSaveGames = FALSE;
\r
1959 appData.loadPositionFile = "";
\r
1960 appData.loadPositionIndex = 1;
\r
1961 appData.savePositionFile = "";
\r
1962 appData.matchMode = FALSE;
\r
1963 appData.matchGames = 0;
\r
1964 appData.monoMode = FALSE;
\r
1965 appData.debugMode = FALSE;
\r
1966 appData.clockMode = TRUE;
\r
1967 boardSize = (BoardSize) -1; /* determine by screen size */
\r
1968 appData.Iconic = FALSE; /*unused*/
\r
1969 appData.searchTime = "";
\r
1970 appData.searchDepth = 0;
\r
1971 appData.showCoords = FALSE;
\r
1972 appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/
\r
1973 appData.autoCallFlag = FALSE;
\r
1974 appData.flipView = FALSE;
\r
1975 appData.autoFlipView = TRUE;
\r
1976 appData.cmailGameName = "";
\r
1977 appData.alwaysPromoteToQueen = FALSE;
\r
1978 appData.oldSaveStyle = FALSE;
\r
1979 appData.quietPlay = FALSE;
\r
1980 appData.showThinking = FALSE;
\r
1981 appData.ponderNextMove = TRUE;
\r
1982 appData.periodicUpdates = TRUE;
\r
1983 appData.popupExitMessage = TRUE;
\r
1984 appData.popupMoveErrors = FALSE;
\r
1985 appData.autoObserve = FALSE;
\r
1986 appData.autoComment = FALSE;
\r
1987 appData.animate = TRUE;
\r
1988 appData.animSpeed = 10;
\r
1989 appData.animateDragging = TRUE;
\r
1990 appData.highlightLastMove = TRUE;
\r
1991 appData.getMoveList = TRUE;
\r
1992 appData.testLegality = TRUE;
\r
1993 appData.premove = TRUE;
\r
1994 appData.premoveWhite = FALSE;
\r
1995 appData.premoveWhiteText = "";
\r
1996 appData.premoveBlack = FALSE;
\r
1997 appData.premoveBlackText = "";
\r
1998 appData.icsAlarm = TRUE;
\r
1999 appData.icsAlarmTime = 5000;
\r
2000 appData.autoRaiseBoard = TRUE;
\r
2001 appData.localLineEditing = TRUE;
\r
2002 appData.colorize = TRUE;
\r
2003 appData.reuseFirst = TRUE;
\r
2004 appData.reuseSecond = TRUE;
\r
2005 appData.blindfold = FALSE;
\r
2006 appData.icsEngineAnalyze = FALSE;
\r
2007 memset(&dcb, 0, sizeof(DCB)); // required by VS 2002 +
\r
2008 dcb.DCBlength = sizeof(DCB);
\r
2009 dcb.BaudRate = 9600;
\r
2010 dcb.fBinary = TRUE;
\r
2011 dcb.fParity = FALSE;
\r
2012 dcb.fOutxCtsFlow = FALSE;
\r
2013 dcb.fOutxDsrFlow = FALSE;
\r
2014 dcb.fDtrControl = DTR_CONTROL_ENABLE;
\r
2015 dcb.fDsrSensitivity = FALSE;
\r
2016 dcb.fTXContinueOnXoff = TRUE;
\r
2017 dcb.fOutX = FALSE;
\r
2019 dcb.fNull = FALSE;
\r
2020 dcb.fRtsControl = RTS_CONTROL_ENABLE;
\r
2021 dcb.fAbortOnError = FALSE;
\r
2023 dcb.Parity = SPACEPARITY;
\r
2024 dcb.StopBits = ONESTOPBIT;
\r
2025 settingsFileName = SETTINGS_FILE;
\r
2026 saveSettingsOnExit = TRUE;
\r
2027 boardX = CW_USEDEFAULT;
\r
2028 boardY = CW_USEDEFAULT;
\r
2029 analysisX = CW_USEDEFAULT;
\r
2030 analysisY = CW_USEDEFAULT;
\r
2031 analysisW = CW_USEDEFAULT;
\r
2032 analysisH = CW_USEDEFAULT;
\r
2033 commentX = CW_USEDEFAULT;
\r
2034 commentY = CW_USEDEFAULT;
\r
2035 commentW = CW_USEDEFAULT;
\r
2036 commentH = CW_USEDEFAULT;
\r
2037 editTagsX = CW_USEDEFAULT;
\r
2038 editTagsY = CW_USEDEFAULT;
\r
2039 editTagsW = CW_USEDEFAULT;
\r
2040 editTagsH = CW_USEDEFAULT;
\r
2041 icsTextMenuString = ICS_TEXT_MENU_DEFAULT;
\r
2042 icsNames = ICS_NAMES;
\r
2043 firstChessProgramNames = FCP_NAMES;
\r
2044 secondChessProgramNames = SCP_NAMES;
\r
2045 appData.initialMode = "";
\r
2046 appData.variant = "normal";
\r
2047 appData.firstProtocolVersion = PROTOVER;
\r
2048 appData.secondProtocolVersion = PROTOVER;
\r
2049 appData.showButtonBar = TRUE;
\r
2051 /* [AS] New properties (see comments in header file) */
\r
2052 appData.firstScoreIsAbsolute = FALSE;
\r
2053 appData.secondScoreIsAbsolute = FALSE;
\r
2054 appData.saveExtendedInfoInPGN = FALSE;
\r
2055 appData.hideThinkingFromHuman = FALSE;
\r
2056 appData.liteBackTextureFile = "";
\r
2057 appData.liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
2058 appData.darkBackTextureFile = "";
\r
2059 appData.darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
2060 appData.renderPiecesWithFont = "";
\r
2061 appData.fontToPieceTable = "";
\r
2062 appData.fontBackColorWhite = 0;
\r
2063 appData.fontForeColorWhite = 0;
\r
2064 appData.fontBackColorBlack = 0;
\r
2065 appData.fontForeColorBlack = 0;
\r
2066 appData.fontPieceSize = 80;
\r
2067 appData.overrideLineGap = 1;
\r
2068 appData.adjudicateLossThreshold = 0;
\r
2069 appData.delayBeforeQuit = 0;
\r
2070 appData.delayAfterQuit = 0;
\r
2071 appData.nameOfDebugFile = "winboard.debug";
\r
2072 appData.pgnEventHeader = "Computer Chess Game";
\r
2073 appData.defaultFrcPosition = -1;
\r
2074 appData.gameListTags = GLT_DEFAULT_TAGS;
\r
2075 appData.saveOutOfBookInfo = TRUE;
\r
2076 appData.showEvalInMoveHistory = TRUE;
\r
2077 appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );
\r
2078 appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );
\r
2079 appData.highlightMoveWithArrow = FALSE;
\r
2080 appData.highlightArrowColor = ParseColorName( "#FFFF80" );
\r
2081 appData.useStickyWindows = TRUE;
\r
2082 appData.adjudicateDrawMoves = 0;
\r
2083 appData.autoDisplayComment = TRUE;
\r
2084 appData.autoDisplayTags = TRUE;
\r
2085 appData.firstIsUCI = FALSE;
\r
2086 appData.secondIsUCI = FALSE;
\r
2087 appData.firstHasOwnBookUCI = TRUE;
\r
2088 appData.secondHasOwnBookUCI = TRUE;
\r
2089 appData.polyglotDir = "";
\r
2090 appData.usePolyglotBook = FALSE;
\r
2091 appData.polyglotBook = "";
\r
2092 appData.defaultHashSize = 64;
\r
2093 appData.defaultCacheSizeEGTB = 4;
\r
2094 appData.defaultPathEGTB = "c:\\egtb";
\r
2095 appData.firstOptions = "";
\r
2096 appData.secondOptions = "";
\r
2098 InitWindowPlacement( &wpGameList );
\r
2099 InitWindowPlacement( &wpMoveHistory );
\r
2100 InitWindowPlacement( &wpEvalGraph );
\r
2101 InitWindowPlacement( &wpEngineOutput );
\r
2102 InitWindowPlacement( &wpConsole );
\r
2104 /* [HGM] User-selectable board size, adjudication control, miscellaneous */
\r
2105 appData.NrFiles = -1;
\r
2106 appData.NrRanks = -1;
\r
2107 appData.holdingsSize = -1;
\r
2108 appData.testClaims = FALSE;
\r
2109 appData.checkMates = FALSE;
\r
2110 appData.materialDraws= FALSE;
\r
2111 appData.trivialDraws = FALSE;
\r
2112 appData.ruleMoves = 51;
\r
2113 appData.drawRepeats = 6;
\r
2114 appData.matchPause = 10000;
\r
2115 appData.alphaRank = FALSE;
\r
2116 appData.allWhite = FALSE;
\r
2117 appData.upsideDown = FALSE;
\r
2118 appData.serverPause = 15;
\r
2119 appData.serverMovesName = NULL;
\r
2120 appData.suppressLoadMoves = FALSE;
\r
2121 appData.firstTimeOdds = 1;
\r
2122 appData.secondTimeOdds = 1;
\r
2123 appData.firstAccumulateTC = 1; // combine previous and current sessions
\r
2124 appData.secondAccumulateTC = 1;
\r
2125 appData.firstNPS = -1; // [HGM] nps: use wall-clock time
\r
2126 appData.secondNPS = -1;
\r
2127 appData.engineComments = 1;
\r
2128 appData.smpCores = 1; // [HGM] SMP: max nr of cores
\r
2129 appData.egtFormats = "";
\r
2132 appData.zippyTalk = ZIPPY_TALK;
\r
2133 appData.zippyPlay = ZIPPY_PLAY;
\r
2134 appData.zippyLines = ZIPPY_LINES;
\r
2135 appData.zippyPinhead = ZIPPY_PINHEAD;
\r
2136 appData.zippyPassword = ZIPPY_PASSWORD;
\r
2137 appData.zippyPassword2 = ZIPPY_PASSWORD2;
\r
2138 appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;
\r
2139 appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;
\r
2140 appData.zippyUseI = ZIPPY_USE_I;
\r
2141 appData.zippyBughouse = ZIPPY_BUGHOUSE;
\r
2142 appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;
\r
2143 appData.zippyGameEnd = ZIPPY_GAME_END;
\r
2144 appData.zippyGameStart = ZIPPY_GAME_START;
\r
2145 appData.zippyAdjourn = ZIPPY_ADJOURN;
\r
2146 appData.zippyAbort = ZIPPY_ABORT;
\r
2147 appData.zippyVariants = ZIPPY_VARIANTS;
\r
2148 appData.zippyMaxGames = ZIPPY_MAX_GAMES;
\r
2149 appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;
\r
2152 /* Point font array elements to structures and
\r
2153 parse default font names */
\r
2154 for (i=0; i<NUM_FONTS; i++) {
\r
2155 for (j=0; j<NUM_SIZES; j++) {
\r
2156 font[j][i] = &fontRec[j][i];
\r
2157 ParseFontName(font[j][i]->def, &font[j][i]->mfp);
\r
2161 /* Parse default settings file if any */
\r
2162 if (ParseSettingsFile(settingsFileName, buf)) {
\r
2163 settingsFileName = strdup(buf);
\r
2166 /* Parse command line */
\r
2167 ParseArgs(StringGet, &lpCmdLine);
\r
2169 /* [HGM] make sure board size is acceptable */
\r
2170 if(appData.NrFiles > BOARD_SIZE ||
\r
2171 appData.NrRanks > BOARD_SIZE )
\r
2172 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
2174 /* [HGM] After parsing the options from the .ini file, and overruling them
\r
2175 * with options from the command line, we now make an even higher priority
\r
2176 * overrule by WB options attached to the engine command line. This so that
\r
2177 * tournament managers can use WB options (such as /timeOdds) that follow
\r
2180 if(appData.firstChessProgram != NULL) {
\r
2181 char *p = StrStr(appData.firstChessProgram, "WBopt");
\r
2182 static char *f = "first";
\r
2183 char buf[MSG_SIZ], *q = buf;
\r
2184 if(p != NULL) { // engine command line contains WinBoard options
\r
2185 sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"
\r
2186 ParseArgs(StringGet, &q);
\r
2187 p[-1] = 0; // cut them offengine command line
\r
2190 // now do same for second chess program
\r
2191 if(appData.secondChessProgram != NULL) {
\r
2192 char *p = StrStr(appData.secondChessProgram, "WBopt");
\r
2193 static char *s = "second";
\r
2194 char buf[MSG_SIZ], *q = buf;
\r
2195 if(p != NULL) { // engine command line contains WinBoard options
\r
2196 sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"
\r
2197 ParseArgs(StringGet, &q);
\r
2198 p[-1] = 0; // cut them offengine command line
\r
2203 /* Propagate options that affect others */
\r
2204 if (appData.matchMode || appData.matchGames) chessProgram = TRUE;
\r
2205 if (appData.icsActive || appData.noChessProgram) {
\r
2206 chessProgram = FALSE; /* not local chess program mode */
\r
2209 /* Open startup dialog if needed */
\r
2210 if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||
\r
2211 (appData.icsActive && *appData.icsHost == NULLCHAR) ||
\r
2212 (chessProgram && (*appData.firstChessProgram == NULLCHAR ||
\r
2213 *appData.secondChessProgram == NULLCHAR))) {
\r
2216 lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);
\r
2217 DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);
\r
2218 FreeProcInstance(lpProc);
\r
2221 /* Make sure save files land in the right (?) directory */
\r
2222 if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {
\r
2223 appData.saveGameFile = strdup(buf);
\r
2225 if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {
\r
2226 appData.savePositionFile = strdup(buf);
\r
2229 /* Finish initialization for fonts and sounds */
\r
2230 for (i=0; i<NUM_FONTS; i++) {
\r
2231 for (j=0; j<NUM_SIZES; j++) {
\r
2232 CreateFontInMF(font[j][i]);
\r
2235 /* xboard, and older WinBoards, controlled the move sound with the
\r
2236 appData.ringBellAfterMoves option. In the current WinBoard, we
\r
2237 always turn the option on (so that the backend will call us),
\r
2238 then let the user turn the sound off by setting it to silence if
\r
2239 desired. To accommodate old winboard.ini files saved by old
\r
2240 versions of WinBoard, we also turn off the sound if the option
\r
2241 was initially set to false. */
\r
2242 if (!appData.ringBellAfterMoves) {
\r
2243 sounds[(int)SoundMove].name = strdup("");
\r
2244 appData.ringBellAfterMoves = TRUE;
\r
2246 GetCurrentDirectory(MSG_SIZ, currDir);
\r
2247 SetCurrentDirectory(installDir);
\r
2249 SetCurrentDirectory(currDir);
\r
2251 p = icsTextMenuString;
\r
2252 if (p[0] == '@') {
\r
2253 FILE* f = fopen(p + 1, "r");
\r
2255 DisplayFatalError(p + 1, errno, 2);
\r
2258 i = fread(buf, 1, sizeof(buf)-1, f);
\r
2260 buf[i] = NULLCHAR;
\r
2263 ParseIcsTextMenu(strdup(p));
\r
2270 HMENU hmenu = GetMenu(hwndMain);
\r
2272 (void) EnableMenuItem(hmenu, IDM_CommPort,
\r
2273 MF_BYCOMMAND|((appData.icsActive &&
\r
2274 *appData.icsCommPort != NULLCHAR) ?
\r
2275 MF_ENABLED : MF_GRAYED));
\r
2276 (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,
\r
2277 MF_BYCOMMAND|(saveSettingsOnExit ?
\r
2278 MF_CHECKED : MF_UNCHECKED));
\r
2283 SaveSettings(char* name)
\r
2286 ArgDescriptor *ad;
\r
2287 WINDOWPLACEMENT wp;
\r
2288 char dir[MSG_SIZ];
\r
2290 if (!hwndMain) return;
\r
2292 GetCurrentDirectory(MSG_SIZ, dir);
\r
2293 SetCurrentDirectory(installDir);
\r
2294 f = fopen(name, "w");
\r
2295 SetCurrentDirectory(dir);
\r
2297 DisplayError(name, errno);
\r
2300 fprintf(f, ";\n");
\r
2301 fprintf(f, "; %s %s.%s Save Settings file\n", PRODUCT, VERSION, PATCHLEVEL);
\r
2302 fprintf(f, ";\n");
\r
2303 fprintf(f, "; You can edit the values of options that are already set in this file,\n");
\r
2304 fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");
\r
2305 fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");
\r
2306 fprintf(f, ";\n");
\r
2308 wp.length = sizeof(WINDOWPLACEMENT);
\r
2309 GetWindowPlacement(hwndMain, &wp);
\r
2310 boardX = wp.rcNormalPosition.left;
\r
2311 boardY = wp.rcNormalPosition.top;
\r
2313 if (hwndConsole) {
\r
2314 GetWindowPlacement(hwndConsole, &wp);
\r
2315 wpConsole.x = wp.rcNormalPosition.left;
\r
2316 wpConsole.y = wp.rcNormalPosition.top;
\r
2317 wpConsole.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2318 wpConsole.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2321 if (analysisDialog) {
\r
2322 GetWindowPlacement(analysisDialog, &wp);
\r
2323 analysisX = wp.rcNormalPosition.left;
\r
2324 analysisY = wp.rcNormalPosition.top;
\r
2325 analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2326 analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2329 if (commentDialog) {
\r
2330 GetWindowPlacement(commentDialog, &wp);
\r
2331 commentX = wp.rcNormalPosition.left;
\r
2332 commentY = wp.rcNormalPosition.top;
\r
2333 commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2334 commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2337 if (editTagsDialog) {
\r
2338 GetWindowPlacement(editTagsDialog, &wp);
\r
2339 editTagsX = wp.rcNormalPosition.left;
\r
2340 editTagsY = wp.rcNormalPosition.top;
\r
2341 editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2342 editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2345 if (gameListDialog) {
\r
2346 GetWindowPlacement(gameListDialog, &wp);
\r
2347 wpGameList.x = wp.rcNormalPosition.left;
\r
2348 wpGameList.y = wp.rcNormalPosition.top;
\r
2349 wpGameList.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2350 wpGameList.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2353 /* [AS] Move history */
\r
2354 wpMoveHistory.visible = MoveHistoryIsUp();
\r
2356 if( moveHistoryDialog ) {
\r
2357 GetWindowPlacement(moveHistoryDialog, &wp);
\r
2358 wpMoveHistory.x = wp.rcNormalPosition.left;
\r
2359 wpMoveHistory.y = wp.rcNormalPosition.top;
\r
2360 wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2361 wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2364 /* [AS] Eval graph */
\r
2365 wpEvalGraph.visible = EvalGraphIsUp();
\r
2367 if( evalGraphDialog ) {
\r
2368 GetWindowPlacement(evalGraphDialog, &wp);
\r
2369 wpEvalGraph.x = wp.rcNormalPosition.left;
\r
2370 wpEvalGraph.y = wp.rcNormalPosition.top;
\r
2371 wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2372 wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2375 /* [AS] Engine output */
\r
2376 wpEngineOutput.visible = EngineOutputIsUp();
\r
2378 if( engineOutputDialog ) {
\r
2379 GetWindowPlacement(engineOutputDialog, &wp);
\r
2380 wpEngineOutput.x = wp.rcNormalPosition.left;
\r
2381 wpEngineOutput.y = wp.rcNormalPosition.top;
\r
2382 wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2383 wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2386 for (ad = argDescriptors; ad->argName != NULL; ad++) {
\r
2387 if (!ad->save) continue;
\r
2388 switch (ad->argType) {
\r
2391 char *p = *(char **)ad->argLoc;
\r
2392 if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {
\r
2393 /* Quote multiline values or \-containing values
\r
2394 with { } if possible */
\r
2395 fprintf(f, "/%s={%s}\n", ad->argName, p);
\r
2397 /* Else quote with " " */
\r
2398 fprintf(f, "/%s=\"", ad->argName);
\r
2400 if (*p == '\n') fprintf(f, "\n");
\r
2401 else if (*p == '\r') fprintf(f, "\\r");
\r
2402 else if (*p == '\t') fprintf(f, "\\t");
\r
2403 else if (*p == '\b') fprintf(f, "\\b");
\r
2404 else if (*p == '\f') fprintf(f, "\\f");
\r
2405 else if (*p < ' ') fprintf(f, "\\%03o", *p);
\r
2406 else if (*p == '\"') fprintf(f, "\\\"");
\r
2407 else if (*p == '\\') fprintf(f, "\\\\");
\r
2411 fprintf(f, "\"\n");
\r
2417 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);
\r
2420 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardX); // [HGM] placement: stor relative value
\r
2423 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardY);
\r
2426 fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);
\r
2429 fprintf(f, "/%s=%s\n", ad->argName,
\r
2430 (*(Boolean *)ad->argLoc) ? "true" : "false");
\r
2433 if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2436 if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2440 COLORREF color = *(COLORREF *)ad->argLoc;
\r
2441 fprintf(f, "/%s=#%02lx%02lx%02lx\n", ad->argName,
\r
2442 color&0xff, (color>>8)&0xff, (color>>16)&0xff);
\r
2447 MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];
\r
2448 fprintf(f, "/%s=\"%s%s%s%s%s#%02lx%02lx%02lx\"\n", ad->argName,
\r
2449 (ta->effects & CFE_BOLD) ? "b" : "",
\r
2450 (ta->effects & CFE_ITALIC) ? "i" : "",
\r
2451 (ta->effects & CFE_UNDERLINE) ? "u" : "",
\r
2452 (ta->effects & CFE_STRIKEOUT) ? "s" : "",
\r
2453 (ta->effects) ? " " : "",
\r
2454 ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);
\r
2458 if (strchr(*(char **)ad->argLoc, '\"')) {
\r
2459 fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);
\r
2461 fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);
\r
2464 case ArgBoardSize:
\r
2465 fprintf(f, "/%s=%s\n", ad->argName,
\r
2466 sizeInfo[*(BoardSize *)ad->argLoc].name);
\r
2471 for (bs=0; bs<NUM_SIZES; bs++) {
\r
2472 MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;
\r
2473 fprintf(f, "/size=%s ", sizeInfo[bs].name);
\r
2474 fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n",
\r
2475 ad->argName, mfp->faceName, mfp->pointSize,
\r
2476 mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",
\r
2477 mfp->bold ? "b" : "",
\r
2478 mfp->italic ? "i" : "",
\r
2479 mfp->underline ? "u" : "",
\r
2480 mfp->strikeout ? "s" : "");
\r
2484 case ArgCommSettings:
\r
2485 PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);
\r
2487 case ArgSettingsFilename: ;
\r
2495 /*---------------------------------------------------------------------------*\
\r
2497 * GDI board drawing routines
\r
2499 \*---------------------------------------------------------------------------*/
\r
2501 /* [AS] Draw square using background texture */
\r
2502 static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )
\r
2507 return; /* Should never happen! */
\r
2510 SetGraphicsMode( dst, GM_ADVANCED );
\r
2517 /* X reflection */
\r
2522 x.eDx = (FLOAT) dw + dx - 1;
\r
2525 SetWorldTransform( dst, &x );
\r
2528 /* Y reflection */
\r
2534 x.eDy = (FLOAT) dh + dy - 1;
\r
2536 SetWorldTransform( dst, &x );
\r
2544 x.eDx = (FLOAT) dx;
\r
2545 x.eDy = (FLOAT) dy;
\r
2548 SetWorldTransform( dst, &x );
\r
2552 BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );
\r
2560 SetWorldTransform( dst, &x );
\r
2562 ModifyWorldTransform( dst, 0, MWT_IDENTITY );
\r
2565 /* [AS] [HGM] Make room for more piece types, so all pieces can be different */
\r
2567 PM_WP = (int) WhitePawn,
\r
2568 PM_WN = (int) WhiteKnight,
\r
2569 PM_WB = (int) WhiteBishop,
\r
2570 PM_WR = (int) WhiteRook,
\r
2571 PM_WQ = (int) WhiteQueen,
\r
2572 PM_WF = (int) WhiteFerz,
\r
2573 PM_WW = (int) WhiteWazir,
\r
2574 PM_WE = (int) WhiteAlfil,
\r
2575 PM_WM = (int) WhiteMan,
\r
2576 PM_WO = (int) WhiteCannon,
\r
2577 PM_WU = (int) WhiteUnicorn,
\r
2578 PM_WH = (int) WhiteNightrider,
\r
2579 PM_WA = (int) WhiteAngel,
\r
2580 PM_WC = (int) WhiteMarshall,
\r
2581 PM_WAB = (int) WhiteCardinal,
\r
2582 PM_WD = (int) WhiteDragon,
\r
2583 PM_WL = (int) WhiteLance,
\r
2584 PM_WS = (int) WhiteCobra,
\r
2585 PM_WV = (int) WhiteFalcon,
\r
2586 PM_WSG = (int) WhiteSilver,
\r
2587 PM_WG = (int) WhiteGrasshopper,
\r
2588 PM_WK = (int) WhiteKing,
\r
2589 PM_BP = (int) BlackPawn,
\r
2590 PM_BN = (int) BlackKnight,
\r
2591 PM_BB = (int) BlackBishop,
\r
2592 PM_BR = (int) BlackRook,
\r
2593 PM_BQ = (int) BlackQueen,
\r
2594 PM_BF = (int) BlackFerz,
\r
2595 PM_BW = (int) BlackWazir,
\r
2596 PM_BE = (int) BlackAlfil,
\r
2597 PM_BM = (int) BlackMan,
\r
2598 PM_BO = (int) BlackCannon,
\r
2599 PM_BU = (int) BlackUnicorn,
\r
2600 PM_BH = (int) BlackNightrider,
\r
2601 PM_BA = (int) BlackAngel,
\r
2602 PM_BC = (int) BlackMarshall,
\r
2603 PM_BG = (int) BlackGrasshopper,
\r
2604 PM_BAB = (int) BlackCardinal,
\r
2605 PM_BD = (int) BlackDragon,
\r
2606 PM_BL = (int) BlackLance,
\r
2607 PM_BS = (int) BlackCobra,
\r
2608 PM_BV = (int) BlackFalcon,
\r
2609 PM_BSG = (int) BlackSilver,
\r
2610 PM_BK = (int) BlackKing
\r
2613 static HFONT hPieceFont = NULL;
\r
2614 static HBITMAP hPieceMask[(int) EmptySquare];
\r
2615 static HBITMAP hPieceFace[(int) EmptySquare];
\r
2616 static int fontBitmapSquareSize = 0;
\r
2617 static char pieceToFontChar[(int) EmptySquare] =
\r
2618 { 'p', 'n', 'b', 'r', 'q',
\r
2619 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',
\r
2620 'k', 'o', 'm', 'v', 't', 'w',
\r
2621 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',
\r
2624 extern BOOL SetCharTable( char *table, const char * map );
\r
2625 /* [HGM] moved to backend.c */
\r
2627 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )
\r
2630 BYTE r1 = GetRValue( color );
\r
2631 BYTE g1 = GetGValue( color );
\r
2632 BYTE b1 = GetBValue( color );
\r
2638 /* Create a uniform background first */
\r
2639 hbrush = CreateSolidBrush( color );
\r
2640 SetRect( &rc, 0, 0, squareSize, squareSize );
\r
2641 FillRect( hdc, &rc, hbrush );
\r
2642 DeleteObject( hbrush );
\r
2645 /* Vertical gradient, good for pawn, knight and rook, less for queen and king */
\r
2646 int steps = squareSize / 2;
\r
2649 for( i=0; i<steps; i++ ) {
\r
2650 BYTE r = r1 - (r1-r2) * i / steps;
\r
2651 BYTE g = g1 - (g1-g2) * i / steps;
\r
2652 BYTE b = b1 - (b1-b2) * i / steps;
\r
2654 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2655 SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );
\r
2656 FillRect( hdc, &rc, hbrush );
\r
2657 DeleteObject(hbrush);
\r
2660 else if( mode == 2 ) {
\r
2661 /* Diagonal gradient, good more or less for every piece */
\r
2662 POINT triangle[3];
\r
2663 HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );
\r
2664 HBRUSH hbrush_old;
\r
2665 int steps = squareSize;
\r
2668 triangle[0].x = squareSize - steps;
\r
2669 triangle[0].y = squareSize;
\r
2670 triangle[1].x = squareSize;
\r
2671 triangle[1].y = squareSize;
\r
2672 triangle[2].x = squareSize;
\r
2673 triangle[2].y = squareSize - steps;
\r
2675 for( i=0; i<steps; i++ ) {
\r
2676 BYTE r = r1 - (r1-r2) * i / steps;
\r
2677 BYTE g = g1 - (g1-g2) * i / steps;
\r
2678 BYTE b = b1 - (b1-b2) * i / steps;
\r
2680 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2681 hbrush_old = SelectObject( hdc, hbrush );
\r
2682 Polygon( hdc, triangle, 3 );
\r
2683 SelectObject( hdc, hbrush_old );
\r
2684 DeleteObject(hbrush);
\r
2689 SelectObject( hdc, hpen );
\r
2694 [AS] The method I use to create the bitmaps it a bit tricky, but it
\r
2695 seems to work ok. The main problem here is to find the "inside" of a chess
\r
2696 piece: follow the steps as explained below.
\r
2698 static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
\r
2702 COLORREF chroma = RGB(0xFF,0x00,0xFF);
\r
2706 int backColor = whitePieceColor;
\r
2707 int foreColor = blackPieceColor;
\r
2709 if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {
\r
2710 backColor = appData.fontBackColorWhite;
\r
2711 foreColor = appData.fontForeColorWhite;
\r
2713 else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {
\r
2714 backColor = appData.fontBackColorBlack;
\r
2715 foreColor = appData.fontForeColorBlack;
\r
2719 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2721 hbm_old = SelectObject( hdc, hbm );
\r
2725 rc.right = squareSize;
\r
2726 rc.bottom = squareSize;
\r
2728 /* Step 1: background is now black */
\r
2729 FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );
\r
2731 GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );
\r
2733 pt.x = (squareSize - sz.cx) / 2;
\r
2734 pt.y = (squareSize - sz.cy) / 2;
\r
2736 SetBkMode( hdc, TRANSPARENT );
\r
2737 SetTextColor( hdc, chroma );
\r
2738 /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */
\r
2739 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2741 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
\r
2742 /* Step 3: the area outside the piece is filled with white */
\r
2743 // FloodFill( hdc, 0, 0, chroma );
\r
2744 ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );
\r
2745 ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big
\r
2746 ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );
\r
2747 ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );
\r
2748 SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
\r
2750 Step 4: this is the tricky part, the area inside the piece is filled with black,
\r
2751 but if the start point is not inside the piece we're lost!
\r
2752 There should be a better way to do this... if we could create a region or path
\r
2753 from the fill operation we would be fine for example.
\r
2755 // FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );
\r
2756 ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );
\r
2758 { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */
\r
2759 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2760 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2762 SelectObject( dc2, bm2 );
\r
2763 BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy
\r
2764 BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2765 BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2766 BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2767 BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2770 DeleteObject( bm2 );
\r
2773 SetTextColor( hdc, 0 );
\r
2775 Step 5: some fonts have "disconnected" areas that are skipped by the fill:
\r
2776 draw the piece again in black for safety.
\r
2778 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2780 SelectObject( hdc, hbm_old );
\r
2782 if( hPieceMask[index] != NULL ) {
\r
2783 DeleteObject( hPieceMask[index] );
\r
2786 hPieceMask[index] = hbm;
\r
2789 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2791 SelectObject( hdc, hbm );
\r
2794 HDC dc1 = CreateCompatibleDC( hdc_window );
\r
2795 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2796 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2798 SelectObject( dc1, hPieceMask[index] );
\r
2799 SelectObject( dc2, bm2 );
\r
2800 FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );
\r
2801 BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );
\r
2804 Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves
\r
2805 the piece background and deletes (makes transparent) the rest.
\r
2806 Thanks to that mask, we are free to paint the background with the greates
\r
2807 freedom, as we'll be able to mask off the unwanted parts when finished.
\r
2808 We use this, to make gradients and give the pieces a "roundish" look.
\r
2810 SetPieceBackground( hdc, backColor, 2 );
\r
2811 BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );
\r
2815 DeleteObject( bm2 );
\r
2818 SetTextColor( hdc, foreColor );
\r
2819 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2821 SelectObject( hdc, hbm_old );
\r
2823 if( hPieceFace[index] != NULL ) {
\r
2824 DeleteObject( hPieceFace[index] );
\r
2827 hPieceFace[index] = hbm;
\r
2830 static int TranslatePieceToFontPiece( int piece )
\r
2860 case BlackMarshall:
\r
2864 case BlackNightrider:
\r
2870 case BlackUnicorn:
\r
2874 case BlackGrasshopper:
\r
2886 case BlackCardinal:
\r
2893 case WhiteMarshall:
\r
2897 case WhiteNightrider:
\r
2903 case WhiteUnicorn:
\r
2907 case WhiteGrasshopper:
\r
2919 case WhiteCardinal:
\r
2928 void CreatePiecesFromFont()
\r
2931 HDC hdc_window = NULL;
\r
2937 if( fontBitmapSquareSize < 0 ) {
\r
2938 /* Something went seriously wrong in the past: do not try to recreate fonts! */
\r
2942 if( appData.renderPiecesWithFont == NULL || appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {
\r
2943 fontBitmapSquareSize = -1;
\r
2947 if( fontBitmapSquareSize != squareSize ) {
\r
2948 hdc_window = GetDC( hwndMain );
\r
2949 hdc = CreateCompatibleDC( hdc_window );
\r
2951 if( hPieceFont != NULL ) {
\r
2952 DeleteObject( hPieceFont );
\r
2955 for( i=0; i<=(int)BlackKing; i++ ) {
\r
2956 hPieceMask[i] = NULL;
\r
2957 hPieceFace[i] = NULL;
\r
2963 if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {
\r
2964 fontHeight = appData.fontPieceSize;
\r
2967 fontHeight = (fontHeight * squareSize) / 100;
\r
2969 lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
\r
2971 lf.lfEscapement = 0;
\r
2972 lf.lfOrientation = 0;
\r
2973 lf.lfWeight = FW_NORMAL;
\r
2975 lf.lfUnderline = 0;
\r
2976 lf.lfStrikeOut = 0;
\r
2977 lf.lfCharSet = DEFAULT_CHARSET;
\r
2978 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
2979 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
2980 lf.lfQuality = PROOF_QUALITY;
\r
2981 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
\r
2982 strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );
\r
2983 lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';
\r
2985 hPieceFont = CreateFontIndirect( &lf );
\r
2987 if( hPieceFont == NULL ) {
\r
2988 fontBitmapSquareSize = -2;
\r
2991 /* Setup font-to-piece character table */
\r
2992 if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {
\r
2993 /* No (or wrong) global settings, try to detect the font */
\r
2994 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {
\r
2996 SetCharTable(pieceToFontChar, "phbrqkojntwl");
\r
2998 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {
\r
2999 /* DiagramTT* family */
\r
3000 SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");
\r
3002 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {
\r
3003 /* Fairy symbols */
\r
3004 SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
\r
3006 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {
\r
3007 /* Good Companion (Some characters get warped as literal :-( */
\r
3008 char s[] = "1cmWG0ñueOS¯®oYI23wgQU";
\r
3009 s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;
\r
3010 SetCharTable(pieceToFontChar, s);
\r
3013 /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */
\r
3014 SetCharTable(pieceToFontChar, "pnbrqkomvtwl");
\r
3018 /* Create bitmaps */
\r
3019 hfont_old = SelectObject( hdc, hPieceFont );
\r
3021 CreatePieceMaskFromFont( hdc_window, hdc, PM_WP );
\r
3022 CreatePieceMaskFromFont( hdc_window, hdc, PM_WN );
\r
3023 CreatePieceMaskFromFont( hdc_window, hdc, PM_WB );
\r
3024 CreatePieceMaskFromFont( hdc_window, hdc, PM_WR );
\r
3025 CreatePieceMaskFromFont( hdc_window, hdc, PM_WQ );
\r
3026 CreatePieceMaskFromFont( hdc_window, hdc, PM_WK );
\r
3027 CreatePieceMaskFromFont( hdc_window, hdc, PM_BP );
\r
3028 CreatePieceMaskFromFont( hdc_window, hdc, PM_BN );
\r
3029 CreatePieceMaskFromFont( hdc_window, hdc, PM_BB );
\r
3030 CreatePieceMaskFromFont( hdc_window, hdc, PM_BR );
\r
3031 CreatePieceMaskFromFont( hdc_window, hdc, PM_BQ );
\r
3032 CreatePieceMaskFromFont( hdc_window, hdc, PM_BK );
\r
3034 CreatePieceMaskFromFont( hdc_window, hdc, PM_WA );
\r
3035 CreatePieceMaskFromFont( hdc_window, hdc, PM_WC );
\r
3036 CreatePieceMaskFromFont( hdc_window, hdc, PM_WF );
\r
3037 CreatePieceMaskFromFont( hdc_window, hdc, PM_WH );
\r
3038 CreatePieceMaskFromFont( hdc_window, hdc, PM_WE );
\r
3039 CreatePieceMaskFromFont( hdc_window, hdc, PM_WW );
\r
3040 CreatePieceMaskFromFont( hdc_window, hdc, PM_WU );
\r
3041 CreatePieceMaskFromFont( hdc_window, hdc, PM_WO );
\r
3042 CreatePieceMaskFromFont( hdc_window, hdc, PM_WG );
\r
3043 CreatePieceMaskFromFont( hdc_window, hdc, PM_WM );
\r
3044 CreatePieceMaskFromFont( hdc_window, hdc, PM_WSG );
\r
3045 CreatePieceMaskFromFont( hdc_window, hdc, PM_WV );
\r
3046 CreatePieceMaskFromFont( hdc_window, hdc, PM_WAB );
\r
3047 CreatePieceMaskFromFont( hdc_window, hdc, PM_WD );
\r
3048 CreatePieceMaskFromFont( hdc_window, hdc, PM_WL );
\r
3049 CreatePieceMaskFromFont( hdc_window, hdc, PM_WS );
\r
3050 CreatePieceMaskFromFont( hdc_window, hdc, PM_BA );
\r
3051 CreatePieceMaskFromFont( hdc_window, hdc, PM_BC );
\r
3052 CreatePieceMaskFromFont( hdc_window, hdc, PM_BF );
\r
3053 CreatePieceMaskFromFont( hdc_window, hdc, PM_BH );
\r
3054 CreatePieceMaskFromFont( hdc_window, hdc, PM_BE );
\r
3055 CreatePieceMaskFromFont( hdc_window, hdc, PM_BW );
\r
3056 CreatePieceMaskFromFont( hdc_window, hdc, PM_BU );
\r
3057 CreatePieceMaskFromFont( hdc_window, hdc, PM_BO );
\r
3058 CreatePieceMaskFromFont( hdc_window, hdc, PM_BG );
\r
3059 CreatePieceMaskFromFont( hdc_window, hdc, PM_BM );
\r
3060 CreatePieceMaskFromFont( hdc_window, hdc, PM_BSG );
\r
3061 CreatePieceMaskFromFont( hdc_window, hdc, PM_BV );
\r
3062 CreatePieceMaskFromFont( hdc_window, hdc, PM_BAB );
\r
3063 CreatePieceMaskFromFont( hdc_window, hdc, PM_BD );
\r
3064 CreatePieceMaskFromFont( hdc_window, hdc, PM_BL );
\r
3065 CreatePieceMaskFromFont( hdc_window, hdc, PM_BS );
\r
3067 for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */
\r
3068 if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */
\r
3069 CreatePieceMaskFromFont( hdc_window, hdc, i );
\r
3071 SelectObject( hdc, hfont_old );
\r
3073 fontBitmapSquareSize = squareSize;
\r
3077 if( hdc != NULL ) {
\r
3081 if( hdc_window != NULL ) {
\r
3082 ReleaseDC( hwndMain, hdc_window );
\r
3087 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)
\r
3091 sprintf(name, "%s%d%s", piece, squareSize, suffix);
\r
3092 if (gameInfo.event &&
\r
3093 strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&
\r
3094 strcmp(name, "k80s") == 0) {
\r
3095 strcpy(name, "tim");
\r
3097 return LoadBitmap(hinst, name);
\r
3101 /* Insert a color into the program's logical palette
\r
3102 structure. This code assumes the given color is
\r
3103 the result of the RGB or PALETTERGB macro, and it
\r
3104 knows how those macros work (which is documented).
\r
3107 InsertInPalette(COLORREF color)
\r
3109 LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);
\r
3111 if (pLogPal->palNumEntries++ >= PALETTESIZE) {
\r
3112 DisplayFatalError("Too many colors", 0, 1);
\r
3113 pLogPal->palNumEntries--;
\r
3117 pe->peFlags = (char) 0;
\r
3118 pe->peRed = (char) (0xFF & color);
\r
3119 pe->peGreen = (char) (0xFF & (color >> 8));
\r
3120 pe->peBlue = (char) (0xFF & (color >> 16));
\r
3126 InitDrawingColors()
\r
3128 if (pLogPal == NULL) {
\r
3129 /* Allocate enough memory for a logical palette with
\r
3130 * PALETTESIZE entries and set the size and version fields
\r
3131 * of the logical palette structure.
\r
3133 pLogPal = (NPLOGPALETTE)
\r
3134 LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +
\r
3135 (sizeof(PALETTEENTRY) * (PALETTESIZE))));
\r
3136 pLogPal->palVersion = 0x300;
\r
3138 pLogPal->palNumEntries = 0;
\r
3140 InsertInPalette(lightSquareColor);
\r
3141 InsertInPalette(darkSquareColor);
\r
3142 InsertInPalette(whitePieceColor);
\r
3143 InsertInPalette(blackPieceColor);
\r
3144 InsertInPalette(highlightSquareColor);
\r
3145 InsertInPalette(premoveHighlightColor);
\r
3147 /* create a logical color palette according the information
\r
3148 * in the LOGPALETTE structure.
\r
3150 hPal = CreatePalette((LPLOGPALETTE) pLogPal);
\r
3152 lightSquareBrush = CreateSolidBrush(lightSquareColor);
\r
3153 blackSquareBrush = CreateSolidBrush(blackPieceColor);
\r
3154 darkSquareBrush = CreateSolidBrush(darkSquareColor);
\r
3155 whitePieceBrush = CreateSolidBrush(whitePieceColor);
\r
3156 blackPieceBrush = CreateSolidBrush(blackPieceColor);
\r
3157 iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
\r
3158 explodeBrush = CreateSolidBrush(highlightSquareColor); // [HGM] atomic
\r
3159 /* [AS] Force rendering of the font-based pieces */
\r
3160 if( fontBitmapSquareSize > 0 ) {
\r
3161 fontBitmapSquareSize = 0;
\r
3167 BoardWidth(int boardSize, int n)
\r
3168 { /* [HGM] argument n added to allow different width and height */
\r
3169 int lineGap = sizeInfo[boardSize].lineGap;
\r
3171 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3172 lineGap = appData.overrideLineGap;
\r
3175 return (n + 1) * lineGap +
\r
3176 n * sizeInfo[boardSize].squareSize;
\r
3179 /* Respond to board resize by dragging edge */
\r
3181 ResizeBoard(int newSizeX, int newSizeY, int flags)
\r
3183 BoardSize newSize = NUM_SIZES - 1;
\r
3184 static int recurse = 0;
\r
3185 if (IsIconic(hwndMain)) return;
\r