2 * WinBoard.c -- Windows NT front end to XBoard
\r
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
\r
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
\r
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
\r
10 * Enhancements Copyright 2005 Alessandro Scotti
\r
12 * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,
\r
13 * which was written and is copyrighted by Wayne Christopher.
\r
15 * The following terms apply to Digital Equipment Corporation's copyright
\r
16 * interest in XBoard:
\r
17 * ------------------------------------------------------------------------
\r
18 * All Rights Reserved
\r
20 * Permission to use, copy, modify, and distribute this software and its
\r
21 * documentation for any purpose and without fee is hereby granted,
\r
22 * provided that the above copyright notice appear in all copies and that
\r
23 * both that copyright notice and this permission notice appear in
\r
24 * supporting documentation, and that the name of Digital not be
\r
25 * used in advertising or publicity pertaining to distribution of the
\r
26 * software without specific, written prior permission.
\r
28 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
\r
29 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
\r
30 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
\r
31 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
\r
32 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
\r
33 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
\r
35 * ------------------------------------------------------------------------
\r
37 * The following terms apply to the enhanced version of XBoard
\r
38 * distributed by the Free Software Foundation:
\r
39 * ------------------------------------------------------------------------
\r
41 * GNU XBoard is free software: you can redistribute it and/or modify
\r
42 * it under the terms of the GNU General Public License as published by
\r
43 * the Free Software Foundation, either version 3 of the License, or (at
\r
44 * your option) any later version.
\r
46 * GNU XBoard is distributed in the hope that it will be useful, but
\r
47 * WITHOUT ANY WARRANTY; without even the implied warranty of
\r
48 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
49 * General Public License for more details.
\r
51 * You should have received a copy of the GNU General Public License
\r
52 * along with this program. If not, see http://www.gnu.org/licenses/. *
\r
54 *------------------------------------------------------------------------
\r
55 ** See the file ChangeLog for a revision history. */
\r
59 #include <windows.h>
\r
60 #include <winuser.h>
\r
61 #include <winsock.h>
\r
62 #include <commctrl.h>
\r
68 #include <sys/stat.h>
\r
71 #include <commdlg.h>
\r
73 #include <richedit.h>
\r
74 #include <mmsystem.h>
\r
83 #include "frontend.h"
\r
84 #include "backend.h"
\r
85 #include "winboard.h"
\r
87 #include "wclipbrd.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
101 extern HANDLE chatHandle[];
\r
102 extern int ics_type;
\r
104 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);
\r
105 VOID NewVariantPopup(HWND hwnd);
\r
106 int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,
\r
107 /*char*/int promoChar));
\r
108 void AnimateAtomicCapture(int fromX, int fromY, int toX, int toY, int nFrames);
\r
109 void DisplayMove P((int moveNumber));
\r
110 Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen));
\r
111 void ChatPopUp P(());
\r
113 ChessSquare piece;
\r
114 POINT pos; /* window coordinates of current pos */
\r
115 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
116 POINT from; /* board coordinates of the piece's orig pos */
\r
117 POINT to; /* board coordinates of the piece's new pos */
\r
120 static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };
\r
123 POINT start; /* window coordinates of start pos */
\r
124 POINT pos; /* window coordinates of current pos */
\r
125 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
126 POINT from; /* board coordinates of the piece's orig pos */
\r
129 static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} };
\r
132 POINT sq[2]; /* board coordinates of from, to squares */
\r
135 static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} };
\r
136 static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };
\r
138 typedef struct { // [HGM] atomic
\r
139 int fromX, fromY, toX, toY, radius;
\r
142 static ExplodeInfo explodeInfo;
\r
144 /* Window class names */
\r
145 char szAppName[] = "WinBoard";
\r
146 char szConsoleName[] = "WBConsole";
\r
148 /* Title bar text */
\r
149 char szTitle[] = "WinBoard";
\r
150 char szConsoleTitle[] = "I C S Interaction";
\r
153 char *settingsFileName;
\r
154 BOOLEAN saveSettingsOnExit;
\r
155 char installDir[MSG_SIZ];
\r
157 BoardSize boardSize;
\r
158 BOOLEAN chessProgram;
\r
159 //static int boardX, boardY;
\r
160 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
\r
161 static int squareSize, lineGap, minorSize;
\r
162 static int winW, winH;
\r
163 static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo
\r
164 static int logoHeight = 0;
\r
165 static char messageText[MESSAGE_TEXT_MAX];
\r
166 static int clockTimerEvent = 0;
\r
167 static int loadGameTimerEvent = 0;
\r
168 static int analysisTimerEvent = 0;
\r
169 static DelayedEventCallback delayedTimerCallback;
\r
170 static int delayedTimerEvent = 0;
\r
171 static int buttonCount = 2;
\r
172 char *icsTextMenuString;
\r
174 char *firstChessProgramNames;
\r
175 char *secondChessProgramNames;
\r
177 #define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */
\r
179 #define PALETTESIZE 256
\r
181 HINSTANCE hInst; /* current instance */
\r
182 BOOLEAN alwaysOnTop = FALSE;
\r
184 COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
\r
185 blackPieceColor, highlightSquareColor, premoveHighlightColor;
\r
187 ColorClass currentColorClass;
\r
189 HWND hCommPort = NULL; /* currently open comm port */
\r
190 static HWND hwndPause; /* pause button */
\r
191 static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */
\r
192 static HBRUSH lightSquareBrush, darkSquareBrush,
\r
193 blackSquareBrush, /* [HGM] for band between board and holdings */
\r
194 explodeBrush, /* [HGM] atomic */
\r
195 whitePieceBrush, blackPieceBrush, iconBkgndBrush /*, outlineBrush*/;
\r
196 static POINT gridEndpoints[(BOARD_RANKS + BOARD_FILES + 2) * 2];
\r
197 static DWORD gridVertexCounts[BOARD_RANKS + BOARD_FILES + 2];
\r
198 static HPEN gridPen = NULL;
\r
199 static HPEN highlightPen = NULL;
\r
200 static HPEN premovePen = NULL;
\r
201 static NPLOGPALETTE pLogPal;
\r
202 static BOOL paletteChanged = FALSE;
\r
203 static HICON iconWhite, iconBlack, iconCurrent;
\r
204 static int doingSizing = FALSE;
\r
205 static int lastSizing = 0;
\r
206 static int prevStderrPort;
\r
207 static HBITMAP userLogo;
\r
209 /* [AS] Support for background textures */
\r
210 #define BACK_TEXTURE_MODE_DISABLED 0
\r
211 #define BACK_TEXTURE_MODE_PLAIN 1
\r
212 #define BACK_TEXTURE_MODE_FULL_RANDOM 2
\r
214 static HBITMAP liteBackTexture = NULL;
\r
215 static HBITMAP darkBackTexture = NULL;
\r
216 static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
217 static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
218 static int backTextureSquareSize = 0;
\r
219 static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_RANKS][BOARD_FILES];
\r
221 #if __GNUC__ && !defined(_winmajor)
\r
222 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */
\r
224 #if defined(_winmajor)
\r
225 #define oldDialog (_winmajor < 4)
\r
227 #define oldDialog 0
\r
231 char *defaultTextAttribs[] =
\r
233 COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,
\r
234 COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,
\r
244 int cliWidth, cliHeight;
\r
247 SizeInfo sizeInfo[] =
\r
249 { "tiny", 21, 0, 1, 1, 0, 0 },
\r
250 { "teeny", 25, 1, 1, 1, 0, 0 },
\r
251 { "dinky", 29, 1, 1, 1, 0, 0 },
\r
252 { "petite", 33, 1, 1, 1, 0, 0 },
\r
253 { "slim", 37, 2, 1, 0, 0, 0 },
\r
254 { "small", 40, 2, 1, 0, 0, 0 },
\r
255 { "mediocre", 45, 2, 1, 0, 0, 0 },
\r
256 { "middling", 49, 2, 0, 0, 0, 0 },
\r
257 { "average", 54, 2, 0, 0, 0, 0 },
\r
258 { "moderate", 58, 3, 0, 0, 0, 0 },
\r
259 { "medium", 64, 3, 0, 0, 0, 0 },
\r
260 { "bulky", 72, 3, 0, 0, 0, 0 },
\r
261 { "large", 80, 3, 0, 0, 0, 0 },
\r
262 { "big", 87, 3, 0, 0, 0, 0 },
\r
263 { "huge", 95, 3, 0, 0, 0, 0 },
\r
264 { "giant", 108, 3, 0, 0, 0, 0 },
\r
265 { "colossal", 116, 4, 0, 0, 0, 0 },
\r
266 { "titanic", 129, 4, 0, 0, 0, 0 },
\r
267 { NULL, 0, 0, 0, 0, 0, 0 }
\r
270 #define MF(x) {x, {{0,}, 0. }, {0, }, 0}
\r
271 MyFont fontRec[NUM_SIZES][NUM_FONTS] =
\r
273 { 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
274 { 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
275 { 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
276 { 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
277 { 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
278 { 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
279 { 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
280 { 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
281 { 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
282 { 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
283 { 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
284 { 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
285 { 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
286 { 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
287 { 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
288 { 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
289 { 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
290 { 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
293 MyFont *font[NUM_SIZES][NUM_FONTS];
\r
302 #define BUTTON_WIDTH (tinyLayout ? 16 : 32)
\r
303 #define N_BUTTONS 5
\r
305 MyButtonDesc buttonDesc[N_BUTTONS] =
\r
307 {"<<", IDM_ToStart, NULL, NULL},
\r
308 {"<", IDM_Backward, NULL, NULL},
\r
309 {"P", IDM_Pause, NULL, NULL},
\r
310 {">", IDM_Forward, NULL, NULL},
\r
311 {">>", IDM_ToEnd, NULL, NULL},
\r
314 int tinyLayout = 0, smallLayout = 0;
\r
315 #define MENU_BAR_ITEMS 7
\r
316 char *menuBarText[2][MENU_BAR_ITEMS+1] = {
\r
317 { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },
\r
318 { "&F", "&M", "&A", "&S", "&O", "&H", NULL },
\r
322 MySound sounds[(int)NSoundClasses];
\r
323 MyTextAttribs textAttribs[(int)NColorClasses];
\r
325 MyColorizeAttribs colorizeAttribs[] = {
\r
326 { (COLORREF)0, 0, "Shout Text" },
\r
327 { (COLORREF)0, 0, "SShout/CShout" },
\r
328 { (COLORREF)0, 0, "Channel 1 Text" },
\r
329 { (COLORREF)0, 0, "Channel Text" },
\r
330 { (COLORREF)0, 0, "Kibitz Text" },
\r
331 { (COLORREF)0, 0, "Tell Text" },
\r
332 { (COLORREF)0, 0, "Challenge Text" },
\r
333 { (COLORREF)0, 0, "Request Text" },
\r
334 { (COLORREF)0, 0, "Seek Text" },
\r
335 { (COLORREF)0, 0, "Normal Text" },
\r
336 { (COLORREF)0, 0, "None" }
\r
341 static char *commentTitle;
\r
342 static char *commentText;
\r
343 static int commentIndex;
\r
344 static Boolean editComment = FALSE;
\r
347 char errorTitle[MSG_SIZ];
\r
348 char errorMessage[2*MSG_SIZ];
\r
349 HWND errorDialog = NULL;
\r
350 BOOLEAN moveErrorMessageUp = FALSE;
\r
351 BOOLEAN consoleEcho = TRUE;
\r
352 CHARFORMAT consoleCF;
\r
353 COLORREF consoleBackgroundColor;
\r
355 char *programVersion;
\r
361 typedef int CPKind;
\r
370 SOCKET sock2; /* stderr socket for OpenRcmd */
\r
373 #define INPUT_SOURCE_BUF_SIZE 4096
\r
375 typedef struct _InputSource {
\r
382 char buf[INPUT_SOURCE_BUF_SIZE];
\r
386 InputCallback func;
\r
387 struct _InputSource *second; /* for stderr thread on CPRcmd */
\r
391 InputSource *consoleInputSource;
\r
396 VOID ConsoleOutput(char* data, int length, int forceVisible);
\r
397 VOID ConsoleCreate();
\r
399 ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
400 VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
\r
401 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
\r
402 VOID ParseCommSettings(char *arg, DCB *dcb);
\r
404 StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
405 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
\r
406 void ParseIcsTextMenu(char *icsTextMenuString);
\r
407 VOID PopUpMoveDialog(char firstchar);
\r
408 VOID PopUpNameDialog(char firstchar);
\r
409 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
\r
413 int GameListOptions();
\r
415 int dummy; // [HGM] for obsolete args
\r
417 HWND hwndMain = NULL; /* root window*/
\r
418 HWND hwndConsole = NULL;
\r
419 HWND commentDialog = NULL;
\r
420 HWND moveHistoryDialog = NULL;
\r
421 HWND evalGraphDialog = NULL;
\r
422 HWND engineOutputDialog = NULL;
\r
423 HWND gameListDialog = NULL;
\r
424 HWND editTagsDialog = NULL;
\r
426 int commentUp = FALSE;
\r
428 WindowPlacement wpMain;
\r
429 WindowPlacement wpConsole;
\r
430 WindowPlacement wpComment;
\r
431 WindowPlacement wpMoveHistory;
\r
432 WindowPlacement wpEvalGraph;
\r
433 WindowPlacement wpEngineOutput;
\r
434 WindowPlacement wpGameList;
\r
435 WindowPlacement wpTags;
\r
437 VOID EngineOptionsPopup(); // [HGM] settings
\r
439 VOID GothicPopUp(char *title, VariantClass variant);
\r
441 * Setting "frozen" should disable all user input other than deleting
\r
442 * the window. We do this while engines are initializing themselves.
\r
444 static int frozen = 0;
\r
445 static int oldMenuItemState[MENU_BAR_ITEMS];
\r
451 if (frozen) return;
\r
453 hmenu = GetMenu(hwndMain);
\r
454 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
455 oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
\r
457 DrawMenuBar(hwndMain);
\r
460 /* Undo a FreezeUI */
\r
466 if (!frozen) return;
\r
468 hmenu = GetMenu(hwndMain);
\r
469 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
470 EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
\r
472 DrawMenuBar(hwndMain);
\r
475 /*static*/ int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them
\r
477 /* JAWS preparation patch (WinBoard for the sight impaired). Define required insertions as empty */
\r
483 #define JAWS_ALT_INTERCEPT
\r
484 #define JAWS_KB_NAVIGATION
\r
485 #define JAWS_MENU_ITEMS
\r
486 #define JAWS_SILENCE
\r
487 #define JAWS_REPLAY
\r
489 #define JAWS_COPYRIGHT
\r
490 #define JAWS_DELETE(X) X
\r
491 #define SAYMACHINEMOVE()
\r
495 /*---------------------------------------------------------------------------*\
\r
499 \*---------------------------------------------------------------------------*/
\r
502 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
\r
503 LPSTR lpCmdLine, int nCmdShow)
\r
506 HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
\r
507 // INITCOMMONCONTROLSEX ex;
\r
511 LoadLibrary("RICHED32.DLL");
\r
512 consoleCF.cbSize = sizeof(CHARFORMAT);
\r
514 if (!InitApplication(hInstance)) {
\r
517 if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
\r
523 // InitCommonControlsEx(&ex);
\r
524 InitCommonControls();
\r
526 hAccelMain = LoadAccelerators (hInstance, szAppName);
\r
527 hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
\r
528 hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
\r
530 /* Acquire and dispatch messages until a WM_QUIT message is received. */
\r
532 while (GetMessage(&msg, /* message structure */
\r
533 NULL, /* handle of window receiving the message */
\r
534 0, /* lowest message to examine */
\r
535 0)) /* highest message to examine */
\r
538 if(msg.message == WM_CHAR && msg.wParam == '\t') {
\r
539 // [HGM] navigate: switch between all windows with tab
\r
540 HWND e1 = NULL, e2 = NULL, mh = NULL, hInput = NULL, hText = NULL;
\r
541 int i, currentElement = 0;
\r
543 // first determine what element of the chain we come from (if any)
\r
544 if(appData.icsActive) {
\r
545 hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);
\r
546 hText = GetDlgItem(hwndConsole, OPT_ConsoleText);
\r
548 if(engineOutputDialog && EngineOutputIsUp()) {
\r
549 e1 = GetDlgItem(engineOutputDialog, IDC_EngineMemo1);
\r
550 e2 = GetDlgItem(engineOutputDialog, IDC_EngineMemo2);
\r
552 if(moveHistoryDialog && MoveHistoryIsUp()) {
\r
553 mh = GetDlgItem(moveHistoryDialog, IDC_MoveHistory);
\r
555 if(msg.hwnd == hwndMain) currentElement = 7 ; else
\r
556 if(msg.hwnd == engineOutputDialog) currentElement = 2; else
\r
557 if(msg.hwnd == e1) currentElement = 2; else
\r
558 if(msg.hwnd == e2) currentElement = 3; else
\r
559 if(msg.hwnd == moveHistoryDialog) currentElement = 4; else
\r
560 if(msg.hwnd == mh) currentElement = 4; else
\r
561 if(msg.hwnd == evalGraphDialog) currentElement = 6; else
\r
562 if(msg.hwnd == hText) currentElement = 5; else
\r
563 if(msg.hwnd == hInput) currentElement = 6; else
\r
564 for (i = 0; i < N_BUTTONS; i++) {
\r
565 if (buttonDesc[i].hwnd == msg.hwnd) { currentElement = 1; break; }
\r
568 // determine where to go to
\r
569 if(currentElement) { HWND h = NULL; int direction = GetKeyState(VK_SHIFT) < 0 ? -1 : 1;
\r
571 currentElement = (currentElement + direction) % 7;
\r
572 switch(currentElement) {
\r
574 h = hwndMain; break; // passing this case always makes the loop exit
\r
576 h = buttonDesc[0].hwnd; break; // could be NULL
\r
578 if(!EngineOutputIsUp()) continue; // skip closed auxiliary windows
\r
581 if(!EngineOutputIsUp()) continue;
\r
584 if(!MoveHistoryIsUp()) continue;
\r
586 // case 6: // input to eval graph does not seem to get here!
\r
587 // if(!EvalGraphIsUp()) continue;
\r
588 // h = evalGraphDialog; break;
\r
590 if(!appData.icsActive) continue;
\r
594 if(!appData.icsActive) continue;
\r
600 if(currentElement > 4 && IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);
\r
601 if(currentElement < 5 && IsIconic(hwndMain)) ShowWindow(hwndMain, SW_RESTORE); // all open together
\r
604 continue; // this message now has been processed
\r
608 if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
\r
609 !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
\r
610 !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
\r
611 !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
\r
612 !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
\r
613 !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
\r
614 !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
\r
615 !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) && JAWS_ACCEL
\r
616 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
\r
617 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
\r
618 int done = 0, i; // [HGM] chat: dispatch cat-box messages
\r
619 for(i=0; i<MAX_CHAT; i++)
\r
620 if(chatHandle[i] && IsDialogMessage(chatHandle[i], &msg)) {
\r
623 if(done) continue; // [HGM] chat: end patch
\r
624 TranslateMessage(&msg); /* Translates virtual key codes */
\r
625 DispatchMessage(&msg); /* Dispatches message to window */
\r
630 return (msg.wParam); /* Returns the value from PostQuitMessage */
\r
633 /*---------------------------------------------------------------------------*\
\r
635 * Initialization functions
\r
637 \*---------------------------------------------------------------------------*/
\r
641 { // update user logo if necessary
\r
642 static char oldUserName[MSG_SIZ], *curName;
\r
644 if(appData.autoLogo) {
\r
645 curName = UserName();
\r
646 if(strcmp(curName, oldUserName)) {
\r
647 sprintf(oldUserName, "logos\\%s.bmp", curName);
\r
648 userLogo = LoadImage( 0, oldUserName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
649 strcpy(oldUserName, curName);
\r
655 InitApplication(HINSTANCE hInstance)
\r
659 /* Fill in window class structure with parameters that describe the */
\r
662 wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
\r
663 wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
\r
664 wc.cbClsExtra = 0; /* No per-class extra data. */
\r
665 wc.cbWndExtra = 0; /* No per-window extra data. */
\r
666 wc.hInstance = hInstance; /* Owner of this class */
\r
667 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
668 wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
\r
669 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
\r
670 wc.lpszMenuName = szAppName; /* Menu name from .RC */
\r
671 wc.lpszClassName = szAppName; /* Name to register as */
\r
673 /* Register the window class and return success/failure code. */
\r
674 if (!RegisterClass(&wc)) return FALSE;
\r
676 wc.style = CS_HREDRAW | CS_VREDRAW;
\r
677 wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
\r
679 wc.cbWndExtra = DLGWINDOWEXTRA;
\r
680 wc.hInstance = hInstance;
\r
681 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
682 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
\r
683 wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
\r
684 wc.lpszMenuName = NULL;
\r
685 wc.lpszClassName = szConsoleName;
\r
687 if (!RegisterClass(&wc)) return FALSE;
\r
692 /* Set by InitInstance, used by EnsureOnScreen */
\r
693 int screenHeight, screenWidth;
\r
696 EnsureOnScreen(int *x, int *y, int minX, int minY)
\r
698 // int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
\r
699 /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
\r
700 if (*x > screenWidth - 32) *x = 0;
\r
701 if (*y > screenHeight - 32) *y = 0;
\r
702 if (*x < minX) *x = minX;
\r
703 if (*y < minY) *y = minY;
\r
707 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
\r
709 HWND hwnd; /* Main window handle. */
\r
711 WINDOWPLACEMENT wp;
\r
714 hInst = hInstance; /* Store instance handle in our global variable */
\r
716 if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
\r
717 *filepart = NULLCHAR;
\r
719 GetCurrentDirectory(MSG_SIZ, installDir);
\r
721 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise
\r
722 screenWidth = screenHeight = 1000; // [HGM] placement: kludge to allow calling EnsureOnScreen from InitAppData
\r
723 InitAppData(lpCmdLine); /* Get run-time parameters */
\r
724 if (appData.debugMode) {
\r
725 debugFP = fopen(appData.nameOfDebugFile, "w");
\r
726 setbuf(debugFP, NULL);
\r
731 // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()
\r
732 // InitEngineUCI( installDir, &second );
\r
734 /* Create a main window for this application instance. */
\r
735 hwnd = CreateWindow(szAppName, szTitle,
\r
736 (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
\r
737 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
\r
738 NULL, NULL, hInstance, NULL);
\r
741 /* If window could not be created, return "failure" */
\r
746 /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */
\r
747 if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {
\r
748 first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
750 if (first.programLogo == NULL && appData.debugMode) {
\r
751 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );
\r
753 } else if(appData.autoLogo) {
\r
754 if(appData.firstDirectory && appData.firstDirectory[0]) {
\r
756 sprintf(buf, "%s/logo.bmp", appData.firstDirectory);
\r
757 first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
761 if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {
\r
762 second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
764 if (second.programLogo == NULL && appData.debugMode) {
\r
765 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );
\r
767 } else if(appData.autoLogo) {
\r
769 if(appData.icsActive) { // [HGM] logo: in ICS mode second can be used for ICS
\r
770 sprintf(buf, "logos\\%s.bmp", appData.icsHost);
\r
771 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
773 if(appData.secondDirectory && appData.secondDirectory[0]) {
\r
774 sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);
\r
775 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
781 iconWhite = LoadIcon(hInstance, "icon_white");
\r
782 iconBlack = LoadIcon(hInstance, "icon_black");
\r
783 iconCurrent = iconWhite;
\r
784 InitDrawingColors();
\r
785 screenHeight = GetSystemMetrics(SM_CYSCREEN);
\r
786 screenWidth = GetSystemMetrics(SM_CXSCREEN);
\r
787 for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
\r
788 /* Compute window size for each board size, and use the largest
\r
789 size that fits on this screen as the default. */
\r
790 InitDrawingSizes((BoardSize)(ibs+1000), 0);
\r
791 if (boardSize == (BoardSize)-1 &&
\r
792 winH <= screenHeight
\r
793 - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10
\r
794 && winW <= screenWidth) {
\r
795 boardSize = (BoardSize)ibs;
\r
799 InitDrawingSizes(boardSize, 0);
\r
801 buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
\r
803 /* [AS] Load textures if specified */
\r
804 ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );
\r
806 if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {
\r
807 liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
808 liteBackTextureMode = appData.liteBackTextureMode;
\r
810 if (liteBackTexture == NULL && appData.debugMode) {
\r
811 fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );
\r
815 if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {
\r
816 darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
817 darkBackTextureMode = appData.darkBackTextureMode;
\r
819 if (darkBackTexture == NULL && appData.debugMode) {
\r
820 fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );
\r
824 mysrandom( (unsigned) time(NULL) );
\r
826 /* [AS] Restore layout */
\r
827 if( wpMoveHistory.visible ) {
\r
828 MoveHistoryPopUp();
\r
831 if( wpEvalGraph.visible ) {
\r
835 if( wpEngineOutput.visible ) {
\r
836 EngineOutputPopUp();
\r
841 /* Make the window visible; update its client area; and return "success" */
\r
842 EnsureOnScreen(&wpMain.x, &wpMain.y, minX, minY);
\r
843 wp.length = sizeof(WINDOWPLACEMENT);
\r
845 wp.showCmd = nCmdShow;
\r
846 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
\r
847 wp.rcNormalPosition.left = wpMain.x;
\r
848 wp.rcNormalPosition.right = wpMain.x + wpMain.width;
\r
849 wp.rcNormalPosition.top = wpMain.y;
\r
850 wp.rcNormalPosition.bottom = wpMain.y + wpMain.height;
\r
851 SetWindowPlacement(hwndMain, &wp);
\r
853 if(!appData.noGUI) SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
854 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
858 SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
859 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
861 ShowWindow(hwndConsole, nCmdShow);
\r
863 if(!appData.noGUI) UpdateWindow(hwnd); else ShowWindow(hwnd, SW_MINIMIZE);
\r
864 if(gameListDialog) SetFocus(gameListDialog); // [HGM] jaws: for if we clicked multi-game game file
\r
872 ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
\r
873 ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
\r
874 ArgSettingsFilename,
\r
875 ArgX, ArgY, ArgZ // [HGM] placement: for window-placement options stored relative to main window
\r
878 typedef void *ArgIniType;
\r
879 #define INVALID (ArgIniType) 6915 /* Some number unlikely to be needed as default for anything */
\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
901 ArgIniType defaultValue;
\r
906 #define XBOARD FALSE
\r
908 ArgDescriptor argDescriptors[] = {
\r
909 /* positional arguments */
\r
910 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE, INVALID },
\r
911 { "", ArgNone, NULL, FALSE, INVALID },
\r
912 /* keyword arguments */
\r
914 { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE, INVALID },
\r
915 { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE, INVALID },
\r
916 { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE, INVALID },
\r
917 { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE, INVALID },
\r
918 { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE, INVALID },
\r
919 { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE, INVALID },
\r
920 { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE, INVALID },
\r
921 { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE, INVALID },
\r
922 { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE, INVALID },
\r
923 { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE, INVALID },
\r
924 { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE, INVALID },
\r
925 { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE, INVALID },
\r
926 { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE, (ArgIniType) MOVES_PER_SESSION },
\r
927 { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE, INVALID },
\r
928 { "initString", ArgString, (LPVOID) &appData.initString, FALSE, INVALID },
\r
929 { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE, (ArgIniType) INIT_STRING },
\r
930 { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE, (ArgIniType) INIT_STRING },
\r
931 { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,
\r
932 FALSE, (ArgIniType) COMPUTER_STRING },
\r
933 { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,
\r
934 FALSE, (ArgIniType) COMPUTER_STRING },
\r
935 { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,
\r
936 FALSE, (ArgIniType) FIRST_CHESS_PROGRAM },
\r
937 { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE, INVALID },
\r
938 { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,
\r
939 FALSE, (ArgIniType) SECOND_CHESS_PROGRAM },
\r
940 { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE, INVALID },
\r
941 { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE, FALSE },
\r
942 { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE, FALSE },
\r
943 { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE, INVALID },
\r
944 { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE, INVALID },
\r
945 { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE, FALSE },
\r
946 { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE, INVALID },
\r
947 { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE, INVALID },
\r
948 { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE, INVALID },
\r
949 { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE, (ArgIniType) FIRST_HOST },
\r
950 { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE, INVALID },
\r
951 { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE, (ArgIniType) SECOND_HOST },
\r
952 { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE, INVALID },
\r
953 { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE, (ArgIniType) FIRST_DIRECTORY },
\r
954 { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE, INVALID },
\r
955 { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE, (ArgIniType) SECOND_DIRECTORY },
\r
956 { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE, INVALID },
\r
958 /* some options only used by the XBoard front end, and ignored in WinBoard */
\r
959 /* Their saving is controlled by XBOARD, which in WinBoard is defined as FALSE */
\r
960 { "internetChessServerInputBox", ArgBoolean, (LPVOID) &appData.icsInputBox, XBOARD, (ArgIniType) FALSE },
\r
961 { "icsinput", ArgTrue, (LPVOID) &appData.icsInputBox, FALSE, INVALID },
\r
962 { "xicsinput", ArgFalse, (LPVOID) &appData.icsInputBox, FALSE, INVALID },
\r
963 { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE, (ArgIniType) "" },
\r
964 { "soundProgram", ArgFilename, (LPVOID) &appData.soundProgram, XBOARD, (ArgIniType) "play" },
\r
965 { "fontSizeTolerance", ArgInt, (LPVOID) &appData.fontSizeTolerance, XBOARD, (ArgIniType) 4 },
\r
966 { "lowTimeWarningColor", ArgColor, (LPVOID) &appData.lowTimeWarningColor, XBOARD,
\r
967 (ArgIniType) LOWTIMEWARNING_COLOR },
\r
968 { "lowTimeWarning", ArgBoolean, (LPVOID) &appData.lowTimeWarning, XBOARD, (ArgIniType) FALSE },
\r
969 { "titleInWindow", ArgBoolean, (LPVOID) &appData.titleInWindow, XBOARD, (ArgIniType) FALSE },
\r
970 { "title", ArgTrue, (LPVOID) &appData.titleInWindow, FALSE, INVALID },
\r
971 { "xtitle", ArgFalse, (LPVOID) &appData.titleInWindow, FALSE, INVALID },
\r
972 { "flashCount", ArgInt, (LPVOID) &appData.flashCount, XBOARD, (ArgIniType) FLASH_COUNT },
\r
973 { "flashRate", ArgInt, (LPVOID) &appData.flashRate, XBOARD, (ArgIniType) FLASH_RATE },
\r
974 { "pixmapDirectory", ArgFilename, (LPVOID) &appData.pixmapDirectory, XBOARD, (ArgIniType) "" },
\r
975 { "pixmap", ArgFilename, (LPVOID) &appData.pixmapDirectory, FALSE, INVALID },
\r
976 { "bitmapDirectory", ArgFilename, (LPVOID) &appData.bitmapDirectory, XBOARD, (ArgIniType) "" },
\r
977 { "bm", ArgFilename, (LPVOID) &appData.bitmapDirectory, FALSE, INVALID },
\r
978 { "msLoginDelay", ArgInt, (LPVOID) &appData.msLoginDelay, XBOARD, (ArgIniType) MS_LOGIN_DELAY },
\r
979 { "pasteSelection", ArgBoolean, (LPVOID) &appData.pasteSelection, XBOARD, (ArgIniType) FALSE },
\r
981 { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE, (ArgIniType) REMOTE_SHELL },
\r
982 { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE, INVALID },
\r
983 { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE, INVALID },
\r
984 { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE, INVALID },
\r
985 { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE, INVALID },
\r
986 { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE, INVALID },
\r
987 { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE, (ArgIniType) TIME_CONTROL },
\r
988 { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE, INVALID },
\r
989 { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE, (ArgIniType) TIME_INCREMENT },
\r
990 { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE, INVALID },
\r
991 { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE, INVALID },
\r
992 { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE, (ArgIniType) FALSE },
\r
993 { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE, INVALID },
\r
994 { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE, INVALID },
\r
995 { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE, (ArgIniType) "" },
\r
996 { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE, INVALID },
\r
997 { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE, (ArgIniType) ICS_PORT },
\r
998 { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE, INVALID },
\r
999 { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE, (ArgIniType) ICS_COMM_PORT },
\r
1000 { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE, INVALID },
\r
1001 { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE, INVALID },
\r
1002 { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE, INVALID },
\r
1003 { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE, (ArgIniType) ICS_LOGON },
\r
1004 { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE, INVALID },
\r
1005 { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE, INVALID },
\r
1006 { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE, INVALID },
\r
1007 { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE, INVALID },
\r
1008 { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE, INVALID },
\r
1009 { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE, (ArgIniType) TELNET_PROGRAM },
\r
1010 { "internetChessserverHelper", ArgFilename, (LPVOID) &appData.icsHelper,
\r
1011 FALSE, INVALID }, // for XB
\r
1012 { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE, (ArgIniType) "" },
\r
1013 { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE, (ArgIniType) "" },
\r
1014 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE, (ArgIniType) "" },
\r
1015 { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE, INVALID },
\r
1016 { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE, (ArgIniType) 0 },
\r
1017 { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE, INVALID },
\r
1018 { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE, (ArgIniType) "" },
\r
1019 { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE, INVALID },
\r
1020 { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE, (ArgIniType) FALSE },
\r
1021 { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE, INVALID },
\r
1022 { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE, INVALID },
\r
1023 { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE, INVALID },
\r
1024 { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE, (ArgIniType) "" },
\r
1025 { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE, INVALID },
\r
1026 { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE, (ArgIniType) 1 },
\r
1027 { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE, INVALID },
\r
1028 { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE, (ArgIniType) "" },
\r
1029 { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE, INVALID },
\r
1030 { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE, (ArgIniType) FALSE },
\r
1031 { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE, INVALID },
\r
1032 { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE, INVALID },
\r
1033 { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE, INVALID },
\r
1034 { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE, (ArgIniType) 0 },
\r
1035 { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE, INVALID },
\r
1036 { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE, (ArgIniType) FALSE },
\r
1037 { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE, INVALID },
\r
1038 { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE, INVALID },
\r
1039 { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE, INVALID },
\r
1040 { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE, (ArgIniType) FALSE },
\r
1041 { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE, INVALID },
\r
1042 { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE, INVALID },
\r
1043 { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE, INVALID },
\r
1044 { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE, (ArgIniType) TRUE },
\r
1045 { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE, INVALID },
\r
1046 { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE, INVALID },
\r
1047 { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE, INVALID },
\r
1048 { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE, (ArgIniType) "" },
\r
1049 { "st", ArgString, (LPVOID) &appData.searchTime, FALSE, INVALID },
\r
1050 { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE, (ArgIniType) 0 },
\r
1051 { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE, INVALID },
\r
1052 { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE, (ArgIniType) FALSE },
\r
1053 { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE, INVALID },
\r
1054 { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE, INVALID },
\r
1055 { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE, INVALID },
\r
1056 { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE, (ArgIniType) FALSE },
\r
1057 { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE, INVALID },
\r
1058 { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE, INVALID },
\r
1059 { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE, INVALID },
\r
1060 { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE, (ArgIniType) TRUE },
\r
1061 { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE, INVALID },
\r
1062 { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE, INVALID },
\r
1063 { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE, INVALID },
\r
1064 { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE, (ArgIniType) TRUE },
\r
1065 { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE, INVALID },
\r
1066 { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE, INVALID },
\r
1067 { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE, INVALID },
\r
1068 { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE, (ArgIniType) TRUE },
\r
1069 { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE, INVALID },
\r
1070 { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE, INVALID },
\r
1071 { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE, INVALID },
\r
1072 { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE, (ArgIniType) FALSE },
\r
1073 { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE, INVALID },
\r
1074 { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE, INVALID },
\r
1075 { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE, INVALID },
\r
1076 { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors,
\r
1077 FALSE, INVALID }, /* only so that old WinBoard.ini files from betas can be read */
\r
1078 { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE, INVALID },
\r
1079 { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE, INVALID },
\r
1080 { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE, INVALID },
\r
1081 { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE, INVALID },
\r
1082 { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE, INVALID },
\r
1083 { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE, INVALID },
\r
1084 { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE, INVALID }, /* [AS] */
\r
1085 { "boardSize", ArgBoardSize, (LPVOID) &boardSize,
\r
1086 TRUE, (ArgIniType) -1 }, /* must come after all fonts */
\r
1087 { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE, INVALID },
\r
1088 { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,
\r
1089 FALSE, (ArgIniType) TRUE }, /* historical; kept only so old winboard.ini files will parse */
\r
1090 { "bell", ArgTrue, (LPVOID) &appData.ringBellAfterMoves, FALSE, INVALID }, // for XB
\r
1091 { "xbell", ArgFalse, (LPVOID) &appData.ringBellAfterMoves, FALSE, INVALID }, // for XB
\r
1092 { "movesound", ArgTrue, (LPVOID) &appData.ringBellAfterMoves, FALSE, INVALID }, // for XB
\r
1093 { "xmovesound", ArgFalse, (LPVOID) &appData.ringBellAfterMoves, FALSE, INVALID }, // for XB
\r
1094 { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE, INVALID },
\r
1095 { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE, INVALID },
\r
1096 { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE, INVALID },
\r
1097 { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE, INVALID },
\r
1098 { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE, (ArgIniType) FALSE },
\r
1099 { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE, INVALID },
\r
1100 { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE, INVALID },
\r
1101 { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE, INVALID },
\r
1102 { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE, (ArgIniType) FALSE },
\r
1103 { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE, INVALID },
\r
1104 { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE, INVALID },
\r
1105 { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE, INVALID },
\r
1106 { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE, (ArgIniType) FALSE },
\r
1107 { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE, INVALID },
\r
1108 { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE, INVALID },
\r
1109 { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE, INVALID },
\r
1110 { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE, (ArgIniType) FALSE },
\r
1111 { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE, INVALID },
\r
1112 { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE, INVALID },
\r
1113 { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE, INVALID },
\r
1114 { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE, (ArgIniType) TRUE },
\r
1115 { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE, INVALID },
\r
1116 { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE, INVALID },
\r
1117 { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE, INVALID },
\r
1118 { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE, (ArgIniType) TRUE },
\r
1119 { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE, INVALID },
\r
1120 { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE, INVALID },
\r
1121 { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE, INVALID },
\r
1122 { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE, (ArgIniType) FALSE },
\r
1123 { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE, INVALID },
\r
1124 { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE, INVALID },
\r
1125 { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE, INVALID },
\r
1126 { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE, (ArgIniType) FALSE },
\r
1127 { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE, INVALID },
\r
1128 { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE, INVALID },
\r
1129 { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE, INVALID },
\r
1130 { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE, (ArgIniType) FALSE },
\r
1131 { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE, INVALID },
\r
1132 { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE, INVALID },
\r
1133 { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE, INVALID },
\r
1134 { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE, (ArgIniType) TRUE },
\r
1135 { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE, INVALID },
\r
1136 { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE, INVALID },
\r
1137 { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE, INVALID },
\r
1138 { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE, (ArgIniType) TRUE },
\r
1139 { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE, INVALID },
\r
1140 { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE, INVALID },
\r
1141 { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE, INVALID },
\r
1142 { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE, (ArgIniType) TRUE },
\r
1143 { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE, INVALID },
\r
1144 { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE, INVALID },
\r
1145 { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE, INVALID },
\r
1146 { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE, (ArgIniType) FALSE },
\r
1147 { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE, INVALID },
\r
1148 { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE, INVALID },
\r
1149 { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE, INVALID },
\r
1150 { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE, (ArgIniType) "" },
\r
1151 { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE, (ArgIniType) FALSE },
\r
1152 { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE, INVALID },
\r
1153 { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE, INVALID },
\r
1154 { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE, INVALID },
\r
1155 { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE, (ArgIniType) "" },
\r
1156 { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE, (ArgIniType) TRUE},
\r
1157 { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},
\r
1158 { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1159 { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1160 { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE, (ArgIniType) 5000},
\r
1161 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE, (ArgIniType) TRUE},
\r
1162 { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE, INVALID },
\r
1163 { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE, INVALID },
\r
1164 { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE, INVALID },
\r
1165 { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE, (ArgIniType) TRUE },
\r
1166 { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE, INVALID },
\r
1167 { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE, INVALID },
\r
1168 { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE, INVALID },
\r
1169 { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE, (ArgIniType) 10 },
\r
1170 { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE, (ArgIniType) TRUE },
\r
1171 { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE, INVALID },
\r
1172 { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE, INVALID },
\r
1173 { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE, INVALID },
\r
1174 { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE, (ArgIniType) FALSE },
\r
1175 { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE, INVALID },
\r
1176 { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE, INVALID },
\r
1177 { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE, INVALID },
\r
1178 { "highlightLastMove", ArgBoolean,
\r
1179 (LPVOID) &appData.highlightLastMove, TRUE, (ArgIniType) TRUE },
\r
1180 { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE, INVALID },
\r
1181 { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE, INVALID },
\r
1182 { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE, INVALID },
\r
1183 { "highlightDragging", ArgBoolean,
\r
1184 (LPVOID) &appData.highlightDragging, TRUE, INVALID },
\r
1185 { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE, INVALID },
\r
1186 { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE, INVALID },
\r
1187 { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE, INVALID },
\r
1188 { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE, (ArgIniType) TRUE },
\r
1189 { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE, INVALID },
\r
1190 { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE, INVALID },
\r
1191 { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE, INVALID },
\r
1192 { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE, INVALID },
\r
1193 { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE, INVALID },
\r
1194 { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE, INVALID },
\r
1195 { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE, INVALID },
\r
1196 { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE, INVALID },
\r
1197 { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE, INVALID },
\r
1198 { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE, INVALID },
\r
1199 { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE, INVALID },
\r
1200 { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE, INVALID },
\r
1201 { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE, INVALID },
\r
1202 { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE, INVALID },
\r
1203 { "soundShout", ArgFilename, (LPVOID) &appData.soundShout, TRUE, (ArgIniType) "" },
\r
1204 { "soundSShout", ArgFilename, (LPVOID) &appData.soundSShout, TRUE, (ArgIniType) "" },
\r
1205 { "soundCShout", ArgFilename, (LPVOID) &appData.soundSShout, TRUE, (ArgIniType) "" }, // for XB
\r
1206 { "soundChannel1", ArgFilename, (LPVOID) &appData.soundChannel1, TRUE, (ArgIniType) "" },
\r
1207 { "soundChannel", ArgFilename, (LPVOID) &appData.soundChannel, TRUE, (ArgIniType) "" },
\r
1208 { "soundKibitz", ArgFilename, (LPVOID) &appData.soundKibitz, TRUE, (ArgIniType) "" },
\r
1209 { "soundTell", ArgFilename, (LPVOID) &appData.soundTell, TRUE, (ArgIniType) "" },
\r
1210 { "soundChallenge", ArgFilename, (LPVOID) &appData.soundChallenge, TRUE, (ArgIniType) "" },
\r
1211 { "soundRequest", ArgFilename, (LPVOID) &appData.soundRequest, TRUE, (ArgIniType) "" },
\r
1212 { "soundSeek", ArgFilename, (LPVOID) &appData.soundSeek, TRUE, (ArgIniType) "" },
\r
1213 { "soundMove", ArgFilename, (LPVOID) &appData.soundMove, TRUE, (ArgIniType) "" },
\r
1214 { "soundBell", ArgFilename, (LPVOID) &appData.soundBell, TRUE, (ArgIniType) SOUND_BELL },
\r
1215 { "soundIcsWin", ArgFilename, (LPVOID) &appData.soundIcsWin, TRUE, (ArgIniType) "" },
\r
1216 { "soundIcsLoss", ArgFilename, (LPVOID) &appData.soundIcsLoss, TRUE, (ArgIniType) "" },
\r
1217 { "soundIcsDraw", ArgFilename, (LPVOID) &appData.soundIcsDraw, TRUE, (ArgIniType) "" },
\r
1218 { "soundIcsUnfinished", ArgFilename, (LPVOID) &appData.soundIcsUnfinished, TRUE, (ArgIniType) "" },
\r
1219 { "soundIcsAlarm", ArgFilename, (LPVOID) &appData.soundIcsAlarm, TRUE, (ArgIniType) "" },
\r
1220 { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE, (ArgIniType) TRUE },
\r
1221 { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE, INVALID },
\r
1222 { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE, INVALID },
\r
1223 { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE, INVALID },
\r
1224 { "reuseChessPrograms", ArgBoolean,
\r
1225 (LPVOID) &appData.reuseFirst, FALSE, INVALID }, /* backward compat only */
\r
1226 { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE, (ArgIniType) TRUE },
\r
1227 { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE, INVALID },
\r
1228 { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE, INVALID },
\r
1229 { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE, INVALID },
\r
1230 { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE, INVALID },
\r
1231 { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE, (ArgIniType) SETTINGS_FILE },
\r
1232 { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE, INVALID },
\r
1233 { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE, (ArgIniType) TRUE },
\r
1234 { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE, (ArgIniType) FALSE },
\r
1235 { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE, INVALID },
\r
1236 { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE, INVALID },
\r
1237 { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE, INVALID },
\r
1238 { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE, (ArgIniType) ICS_TEXT_MENU_DEFAULT },
\r
1239 { "icsNames", ArgString, (LPVOID) &icsNames, TRUE, (ArgIniType) ICS_NAMES },
\r
1240 { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,
\r
1241 TRUE, (ArgIniType) FCP_NAMES },
\r
1242 { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,
\r
1243 TRUE, (ArgIniType) SCP_NAMES },
\r
1244 { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE, (ArgIniType) "" },
\r
1245 { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE, INVALID },
\r
1246 { "variant", ArgString, (LPVOID) &appData.variant, FALSE, (ArgIniType) "normal" },
\r
1247 { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion, FALSE, (ArgIniType) PROTOVER },
\r
1248 { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,FALSE, (ArgIniType) PROTOVER },
\r
1249 { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE, (ArgIniType) TRUE },
\r
1250 { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE, INVALID },
\r
1251 { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE, INVALID },
\r
1252 { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE, INVALID },
\r
1254 /* [AS] New features */
\r
1255 { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE, (ArgIniType) FALSE },
\r
1256 { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE, (ArgIniType) FALSE },
\r
1257 { "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE, (ArgIniType) FALSE },
\r
1258 { "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE, (ArgIniType) FALSE },
\r
1259 { "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE, (ArgIniType) "" },
\r
1260 { "darkBackTextureFile", ArgString, (LPVOID) &appData.darkBackTextureFile, TRUE, (ArgIniType) "" },
\r
1261 { "liteBackTextureMode", ArgInt, (LPVOID) &appData.liteBackTextureMode, TRUE, (ArgIniType) BACK_TEXTURE_MODE_PLAIN },
\r
1262 { "darkBackTextureMode", ArgInt, (LPVOID) &appData.darkBackTextureMode, TRUE, (ArgIniType) BACK_TEXTURE_MODE_PLAIN },
\r
1263 { "renderPiecesWithFont", ArgString, (LPVOID) &appData.renderPiecesWithFont, TRUE, (ArgIniType) "" },
\r
1264 { "fontPieceToCharTable", ArgString, (LPVOID) &appData.fontToPieceTable, TRUE, (ArgIniType) "" },
\r
1265 { "fontPieceBackColorWhite", ArgColor, (LPVOID) &appData.fontBackColorWhite, TRUE, (ArgIniType) 0 },
\r
1266 { "fontPieceForeColorWhite", ArgColor, (LPVOID) &appData.fontForeColorWhite, TRUE, (ArgIniType) 0 },
\r
1267 { "fontPieceBackColorBlack", ArgColor, (LPVOID) &appData.fontBackColorBlack, TRUE, (ArgIniType) 0 },
\r
1268 { "fontPieceForeColorBlack", ArgColor, (LPVOID) &appData.fontForeColorBlack, TRUE, (ArgIniType) 0 },
\r
1269 { "fontPieceSize", ArgInt, (LPVOID) &appData.fontPieceSize, TRUE, (ArgIniType) 80 },
\r
1270 { "overrideLineGap", ArgInt, (LPVOID) &appData.overrideLineGap, TRUE, (ArgIniType) 1 },
\r
1271 { "adjudicateLossThreshold", ArgInt, (LPVOID) &appData.adjudicateLossThreshold, TRUE, (ArgIniType) 0 },
\r
1272 { "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE, (ArgIniType) 0 },
\r
1273 { "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE, (ArgIniType) 0 },
\r
1274 { "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE, (ArgIniType) "winboard.debug" },
\r
1275 { "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE, INVALID },
\r
1276 { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE, (ArgIniType) "Computer Chess Game" },
\r
1277 { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE, (ArgIniType) -1 },
\r
1278 { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE, (ArgIniType) GLT_DEFAULT_TAGS },
\r
1279 { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE, (ArgIniType) TRUE },
\r
1280 { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE, (ArgIniType) TRUE },
\r
1281 { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE, INVALID },
\r
1282 { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE, INVALID },
\r
1283 { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE, (ArgIniType) FALSE },
\r
1284 { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE, INVALID },
\r
1285 { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE, (ArgIniType) TRUE },
\r
1286 { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE, (ArgIniType) TRUE },
\r
1287 { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE, (ArgIniType) TRUE },
\r
1288 { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE, (ArgIniType) TRUE },
\r
1289 { "firstIsUCI", ArgBoolean, (LPVOID) &appData.firstIsUCI, FALSE, (ArgIniType) FALSE },
\r
1290 { "fUCI", ArgTrue, (LPVOID) &appData.firstIsUCI, FALSE, INVALID },
\r
1291 { "secondIsUCI", ArgBoolean, (LPVOID) &appData.secondIsUCI, FALSE, (ArgIniType) FALSE },
\r
1292 { "sUCI", ArgTrue, (LPVOID) &appData.secondIsUCI, FALSE, INVALID },
\r
1293 { "firstHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.firstHasOwnBookUCI, FALSE, (ArgIniType) TRUE },
\r
1294 { "fNoOwnBookUCI", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE, INVALID },
\r
1295 { "firstXBook", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE, INVALID },
\r
1296 { "secondHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.secondHasOwnBookUCI, FALSE, (ArgIniType) TRUE },
\r
1297 { "sNoOwnBookUCI", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE, INVALID },
\r
1298 { "secondXBook", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE, INVALID },
\r
1299 { "polyglotDir", ArgFilename, (LPVOID) &appData.polyglotDir, TRUE, (ArgIniType) "" },
\r
1300 { "usePolyglotBook", ArgBoolean, (LPVOID) &appData.usePolyglotBook, TRUE, (ArgIniType) FALSE },
\r
1301 { "polyglotBook", ArgFilename, (LPVOID) &appData.polyglotBook, TRUE, (ArgIniType) "" },
\r
1302 { "defaultHashSize", ArgInt, (LPVOID) &appData.defaultHashSize, TRUE, (ArgIniType) 64 },
\r
1303 { "defaultCacheSizeEGTB", ArgInt, (LPVOID) &appData.defaultCacheSizeEGTB, TRUE, (ArgIniType) 4 },
\r
1304 { "defaultPathEGTB", ArgFilename, (LPVOID) &appData.defaultPathEGTB, TRUE, (ArgIniType) "c:\\egtb" },
\r
1306 /* [HGM] board-size, adjudication and misc. options */
\r
1307 { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE, (ArgIniType) -1 },
\r
1308 { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE, (ArgIniType) -1 },
\r
1309 { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE, (ArgIniType) -1 },
\r
1310 { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE, (ArgIniType) 10000 },
\r
1311 { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE, INVALID },
\r
1312 { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE, (ArgIniType) FALSE },
\r
1313 { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE, (ArgIniType) FALSE },
\r
1314 { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE, (ArgIniType) FALSE },
\r
1315 { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE, (ArgIniType) FALSE },
\r
1316 { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE, (ArgIniType) FALSE },
\r
1317 { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE, (ArgIniType) FALSE },
\r
1318 { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE, (ArgIniType) FALSE },
\r
1319 { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE, (ArgIniType) FALSE },
\r
1320 { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE, (ArgIniType) FALSE },
\r
1321 { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE, (ArgIniType) 51 },
\r
1322 { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE, (ArgIniType) 6 },
\r
1323 { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE, INVALID },
\r
1324 { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE, (ArgIniType) 1 },
\r
1325 { "userName", ArgString, (LPVOID) &appData.userName, FALSE, INVALID },
\r
1326 { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE, INVALID },
\r
1327 { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE, INVALID },
\r
1328 { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE, (ArgIniType) 1 },
\r
1329 { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE, (ArgIniType) "" },
\r
1330 { "niceEngines", ArgInt, (LPVOID) &appData.niceEngines, TRUE, INVALID },
\r
1331 { "firstLogo", ArgFilename, (LPVOID) &appData.firstLogo, FALSE, INVALID },
\r
1332 { "secondLogo", ArgFilename, (LPVOID) &appData.secondLogo, FALSE, INVALID },
\r
1333 { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE, INVALID },
\r
1334 { "firstOptions", ArgString, (LPVOID) &appData.firstOptions, FALSE, (ArgIniType) "" },
\r
1335 { "secondOptions", ArgString, (LPVOID) &appData.secondOptions, FALSE, (ArgIniType) "" },
\r
1336 { "firstNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride1, FALSE, (ArgIniType) "" },
\r
1337 { "secondNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride2, FALSE, (ArgIniType) "" },
\r
1338 { "keepAlive", ArgInt, (LPVOID) &appData.keepAlive, FALSE, INVALID },
\r
1339 { "icstype", ArgInt, (LPVOID) &ics_type, FALSE, INVALID },
\r
1340 { "forceIllegalMoves", ArgTrue, (LPVOID) &appData.forceIllegal, FALSE, INVALID },
\r
1343 { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE, (ArgIniType) ZIPPY_TALK },
\r
1344 { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE, INVALID },
\r
1345 { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE, INVALID },
\r
1346 { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE, INVALID },
\r
1347 { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE, (ArgIniType) ZIPPY_PLAY },
\r
1348 { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE, INVALID },
\r
1349 { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE, INVALID },
\r
1350 { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE, INVALID },
\r
1351 { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE, (ArgIniType) ZIPPY_LINES },
\r
1352 { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE, (ArgIniType) ZIPPY_PINHEAD },
\r
1353 { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE, (ArgIniType) ZIPPY_PASSWORD },
\r
1354 { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE, (ArgIniType) ZIPPY_PASSWORD2 },
\r
1355 { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,
\r
1356 FALSE, (ArgIniType) ZIPPY_WRONG_PASSWORD },
\r
1357 { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE, (ArgIniType) ZIPPY_ACCEPT_ONLY },
\r
1358 { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE, (ArgIniType) ZIPPY_USE_I },
\r
1359 { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE, INVALID },
\r
1360 { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE, INVALID },
\r
1361 { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE, INVALID },
\r
1362 { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE, (ArgIniType) ZIPPY_BUGHOUSE },
\r
1363 { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,
\r
1364 FALSE, (ArgIniType) ZIPPY_NOPLAY_CRAFTY },
\r
1365 { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE, INVALID },
\r
1366 { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE, INVALID },
\r
1367 { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE, INVALID },
\r
1368 { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE, (ArgIniType) ZIPPY_GAME_END },
\r
1369 { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE, (ArgIniType) ZIPPY_GAME_START },
\r
1370 { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE, (ArgIniType) ZIPPY_ADJOURN },
\r
1371 { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE, INVALID },
\r
1372 { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE, INVALID },
\r
1373 { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE, INVALID },
\r
1374 { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE, (ArgIniType) ZIPPY_ABORT },
\r
1375 { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE, INVALID },
\r
1376 { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE, INVALID },
\r
1377 { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE, INVALID },
\r
1378 { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE, (ArgIniType) ZIPPY_VARIANTS },
\r
1379 { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE, (ArgIniType) ZIPPY_MAX_GAMES},
\r
1380 { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE, (ArgIniType) ZIPPY_REPLAY_TIMEOUT },
\r
1381 { "zippyShortGame", ArgInt, (LPVOID)&appData.zippyShortGame, FALSE, INVALID },
\r
1382 /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */
\r
1383 { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE, INVALID },
\r
1385 /* [HGM] options for broadcasting and time odds */
\r
1386 { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE, (ArgIniType) NULL },
\r
1387 { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE, (ArgIniType) FALSE },
\r
1388 { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE, (ArgIniType) 15 },
\r
1389 { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE, (ArgIniType) 1 },
\r
1390 { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE, (ArgIniType) 1 },
\r
1391 { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE, INVALID },
\r
1392 { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE, (ArgIniType) 1 },
\r
1393 { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE, (ArgIniType) 1 },
\r
1394 { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE, (ArgIniType) -1 },
\r
1395 { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE, (ArgIniType) -1 },
\r
1396 { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE, INVALID },
\r
1397 { "keepLineBreaksICS", ArgBoolean, (LPVOID) &appData.noJoin, TRUE, INVALID },
\r
1398 { "wrapContinuationSequence", ArgString, (LPVOID) &appData.wrapContSeq, FALSE, INVALID },
\r
1399 { "useInternalWrap", ArgTrue, (LPVOID) &appData.useInternalWrap, FALSE, INVALID }, /* noJoin usurps this if set */
\r
1401 // [HGM] placement: put all window layouts last in ini file, but man X,Y before all others
\r
1402 { "minX", ArgZ, (LPVOID) &minX, FALSE, INVALID }, // [HGM] placement: to make suer auxialary windows can be placed
\r
1403 { "minY", ArgZ, (LPVOID) &minY, FALSE, INVALID },
\r
1404 { "winWidth", ArgInt, (LPVOID) &wpMain.width, TRUE, INVALID }, // [HGM] placement: dummies to remember right & bottom
\r
1405 { "winHeight", ArgInt, (LPVOID) &wpMain.height, TRUE, INVALID }, // for attaching auxiliary windows to them
\r
1406 { "x", ArgInt, (LPVOID) &wpMain.x, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1407 { "y", ArgInt, (LPVOID) &wpMain.y, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1408 { "icsX", ArgX, (LPVOID) &wpConsole.x, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1409 { "icsY", ArgY, (LPVOID) &wpConsole.y, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1410 { "icsW", ArgInt, (LPVOID) &wpConsole.width, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1411 { "icsH", ArgInt, (LPVOID) &wpConsole.height, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1412 { "analysisX", ArgX, (LPVOID) &dummy, FALSE, INVALID }, // [HGM] placement: analysis window no longer exists
\r
1413 { "analysisY", ArgY, (LPVOID) &dummy, FALSE, INVALID }, // provided for compatibility with old ini files
\r
1414 { "analysisW", ArgInt, (LPVOID) &dummy, FALSE, INVALID },
\r
1415 { "analysisH", ArgInt, (LPVOID) &dummy, FALSE, INVALID },
\r
1416 { "commentX", ArgX, (LPVOID) &wpComment.x, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1417 { "commentY", ArgY, (LPVOID) &wpComment.y, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1418 { "commentW", ArgInt, (LPVOID) &wpComment.width, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1419 { "commentH", ArgInt, (LPVOID) &wpComment.height, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1420 { "tagsX", ArgX, (LPVOID) &wpTags.x, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1421 { "tagsY", ArgY, (LPVOID) &wpTags.y, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1422 { "tagsW", ArgInt, (LPVOID) &wpTags.width, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1423 { "tagsH", ArgInt, (LPVOID) &wpTags.height, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1424 { "gameListX", ArgX, (LPVOID) &wpGameList.x, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1425 { "gameListY", ArgY, (LPVOID) &wpGameList.y, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1426 { "gameListW", ArgInt, (LPVOID) &wpGameList.width, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1427 { "gameListH", ArgInt, (LPVOID) &wpGameList.height, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1428 /* [AS] Layout stuff */
\r
1429 { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE, (ArgIniType) TRUE },
\r
1430 { "moveHistoryX", ArgX, (LPVOID) &wpMoveHistory.x, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1431 { "moveHistoryY", ArgY, (LPVOID) &wpMoveHistory.y, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1432 { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1433 { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1435 { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE, (ArgIniType) TRUE },
\r
1436 { "evalGraphX", ArgX, (LPVOID) &wpEvalGraph.x, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1437 { "evalGraphY", ArgY, (LPVOID) &wpEvalGraph.y, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1438 { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1439 { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1441 { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE, (ArgIniType) TRUE },
\r
1442 { "engineOutputX", ArgX, (LPVOID) &wpEngineOutput.x, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1443 { "engineOutputY", ArgY, (LPVOID) &wpEngineOutput.y, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1444 { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1445 { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE, (ArgIniType) CW_USEDEFAULT },
\r
1447 { NULL, ArgNone, NULL, FALSE, INVALID }
\r
1451 /* Kludge for indirection files on command line */
\r
1452 char* lastIndirectionFilename;
\r
1453 ArgDescriptor argDescriptorIndirection =
\r
1454 { "", ArgSettingsFilename, (LPVOID) NULL, FALSE };
\r
1458 ExitArgError(char *msg, char *badArg)
\r
1460 char buf[MSG_SIZ];
\r
1462 sprintf(buf, "%s %s", msg, badArg);
\r
1463 DisplayFatalError(buf, 0, 2);
\r
1467 /* Command line font name parser. NULL name means do nothing.
\r
1468 Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"
\r
1469 For backward compatibility, syntax without the colon is also
\r
1470 accepted, but font names with digits in them won't work in that case.
\r
1473 ParseFontName(char *name, MyFontParams *mfp)
\r
1476 if (name == NULL) return;
\r
1478 q = strchr(p, ':');
\r
1480 if (q - p >= sizeof(mfp->faceName))
\r
1481 ExitArgError("Font name too long:", name);
\r
1482 memcpy(mfp->faceName, p, q - p);
\r
1483 mfp->faceName[q - p] = NULLCHAR;
\r
1486 q = mfp->faceName;
\r
1487 while (*p && !isdigit(*p)) {
\r
1489 if (q - mfp->faceName >= sizeof(mfp->faceName))
\r
1490 ExitArgError("Font name too long:", name);
\r
1492 while (q > mfp->faceName && q[-1] == ' ') q--;
\r
1495 if (!*p) ExitArgError("Font point size missing:", name);
\r
1496 mfp->pointSize = (float) atof(p);
\r
1497 mfp->bold = (strchr(p, 'b') != NULL);
\r
1498 mfp->italic = (strchr(p, 'i') != NULL);
\r
1499 mfp->underline = (strchr(p, 'u') != NULL);
\r
1500 mfp->strikeout = (strchr(p, 's') != NULL);
\r
1501 mfp->charset = DEFAULT_CHARSET;
\r
1502 q = strchr(p, 'c');
\r
1504 mfp->charset = (BYTE) atoi(q+1);
\r
1507 /* Color name parser.
\r
1508 X version accepts X color names, but this one
\r
1509 handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */
\r
1511 ParseColorName(char *name)
\r
1513 int red, green, blue, count;
\r
1514 char buf[MSG_SIZ];
\r
1516 count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);
\r
1518 count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d",
\r
1519 &red, &green, &blue);
\r
1522 sprintf(buf, "Can't parse color name %s", name);
\r
1523 DisplayError(buf, 0);
\r
1524 return RGB(0, 0, 0);
\r
1526 return PALETTERGB(red, green, blue);
\r
1530 void ParseAttribs(COLORREF *color, int *effects, char* argValue)
\r
1532 char *e = argValue;
\r
1536 if (*e == 'b') eff |= CFE_BOLD;
\r
1537 else if (*e == 'i') eff |= CFE_ITALIC;
\r
1538 else if (*e == 'u') eff |= CFE_UNDERLINE;
\r
1539 else if (*e == 's') eff |= CFE_STRIKEOUT;
\r
1540 else if (*e == '#' || isdigit(*e)) break;
\r
1544 *color = ParseColorName(e);
\r
1549 ParseBoardSize(char *name)
\r
1551 BoardSize bs = SizeTiny;
\r
1552 while (sizeInfo[bs].name != NULL) {
\r
1553 if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;
\r
1556 ExitArgError("Unrecognized board size value", name);
\r
1557 return bs; /* not reached */
\r
1562 StringGet(void *getClosure)
\r
1564 char **p = (char **) getClosure;
\r
1569 FileGet(void *getClosure)
\r
1572 FILE* f = (FILE*) getClosure;
\r
1575 if (c == '\r') c = getc(f); // work around DOS format files by bypassing the '\r' completely
\r
1582 /* Parse settings file named "name". If file found, return the
\r
1583 full name in fullname and return TRUE; else return FALSE */
\r
1585 ParseSettingsFile(char *name, char fullname[MSG_SIZ])
\r
1589 int ok; char buf[MSG_SIZ];
\r
1591 ok = SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy);
\r
1592 if(!ok && strchr(name, '.') == NULL) { // [HGM] append default file-name extension '.ini' when needed
\r
1593 sprintf(buf, "%s.ini", name);
\r
1594 ok = SearchPath(installDir, buf, NULL, MSG_SIZ, fullname, &dummy);
\r
1597 f = fopen(fullname, "r");
\r
1599 ParseArgs(FileGet, f);
\r
1608 ParseArgs(GetFunc get, void *cl)
\r
1610 char argName[ARG_MAX];
\r
1611 char argValue[ARG_MAX];
\r
1612 ArgDescriptor *ad;
\r
1621 while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);
\r
1622 if (ch == NULLCHAR) break;
\r
1624 /* Comment to end of line */
\r
1626 while (ch != '\n' && ch != NULLCHAR) ch = get(cl);
\r
1628 } else if (ch == '/' || ch == '-') {
\r
1631 while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&
\r
1632 ch != '\n' && ch != '\t') {
\r
1638 for (ad = argDescriptors; ad->argName != NULL; ad++)
\r
1639 if (strcmp(ad->argName, argName + 1) == 0) break;
\r
1641 if (ad->argName == NULL)
\r
1642 ExitArgError("Unrecognized argument", argName);
\r
1644 } else if (ch == '@') {
\r
1645 /* Indirection file */
\r
1646 ad = &argDescriptorIndirection;
\r
1649 /* Positional argument */
\r
1650 ad = &argDescriptors[posarg++];
\r
1651 strcpy(argName, ad->argName);
\r
1654 if (ad->argType == ArgTrue) {
\r
1655 *(Boolean *) ad->argLoc = TRUE;
\r
1658 if (ad->argType == ArgFalse) {
\r
1659 *(Boolean *) ad->argLoc = FALSE;
\r
1663 while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
\r
1664 if (ch == NULLCHAR || ch == '\n') {
\r
1665 ExitArgError("No value provided for argument", argName);
\r
1669 // Quoting with { }. No characters have to (or can) be escaped.
\r
1670 // Thus the string cannot contain a '}' character.
\r
1690 } else if (ch == '\'' || ch == '"') {
\r
1691 // Quoting with ' ' or " ", with \ as escape character.
\r
1692 // Inconvenient for long strings that may contain Windows filenames.
\r
1709 if (ch == start) {
\r
1718 if (ad->argType == ArgFilename
\r
1719 || ad->argType == ArgSettingsFilename) {
\r
1725 ExitArgError("Incomplete \\ escape in value for", argName);
\r
1749 for (i = 0; i < 3; i++) {
\r
1750 if (ch >= '0' && ch <= '7') {
\r
1751 octval = octval*8 + (ch - '0');
\r
1758 *q++ = (char) octval;
\r
1769 while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {
\r
1776 switch (ad->argType) {
\r
1778 *(int *) ad->argLoc = atoi(argValue);
\r
1782 *(int *) ad->argLoc = atoi(argValue) + wpMain.x; // [HGM] placement: translate stored relative to absolute
\r
1786 *(int *) ad->argLoc = atoi(argValue) + wpMain.y; // (this is really kludgey, it should be done where used...)
\r
1790 *(int *) ad->argLoc = atoi(argValue);
\r
1791 EnsureOnScreen(&wpMain.x, &wpMain.y, minX, minY);
\r
1795 *(float *) ad->argLoc = (float) atof(argValue);
\r
1800 *(char **) ad->argLoc = strdup(argValue);
\r
1803 case ArgSettingsFilename:
\r
1805 char fullname[MSG_SIZ];
\r
1806 if (ParseSettingsFile(argValue, fullname)) {
\r
1807 if (ad->argLoc != NULL) {
\r
1808 *(char **) ad->argLoc = strdup(fullname);
\r
1811 if (ad->argLoc != NULL) {
\r
1813 ExitArgError("Failed to open indirection file", argValue);
\r
1820 switch (argValue[0]) {
\r
1823 *(Boolean *) ad->argLoc = TRUE;
\r
1827 *(Boolean *) ad->argLoc = FALSE;
\r
1830 ExitArgError("Unrecognized boolean argument value", argValue);
\r
1836 *(COLORREF *)ad->argLoc = ParseColorName(argValue);
\r
1839 case ArgAttribs: {
\r
1840 ColorClass cc = (ColorClass)ad->argLoc;
\r
1841 ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);
\r
1845 case ArgBoardSize:
\r
1846 *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);
\r
1850 ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);
\r
1853 case ArgCommSettings:
\r
1854 ParseCommSettings(argValue, &dcb);
\r
1858 ExitArgError("Unrecognized argument", argValue);
\r
1867 LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
\r
1869 HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
\r
1870 lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);
\r
1873 lf->lfEscapement = 0;
\r
1874 lf->lfOrientation = 0;
\r
1875 lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;
\r
1876 lf->lfItalic = mfp->italic;
\r
1877 lf->lfUnderline = mfp->underline;
\r
1878 lf->lfStrikeOut = mfp->strikeout;
\r
1879 lf->lfCharSet = mfp->charset;
\r
1880 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
1881 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
1882 lf->lfQuality = DEFAULT_QUALITY;
\r
1883 lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
\r
1884 strcpy(lf->lfFaceName, mfp->faceName);
\r
1888 CreateFontInMF(MyFont *mf)
\r
1890 LFfromMFP(&mf->lf, &mf->mfp);
\r
1891 if (mf->hf) DeleteObject(mf->hf);
\r
1892 mf->hf = CreateFontIndirect(&mf->lf);
\r
1896 SetDefaultTextAttribs()
\r
1899 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1900 ParseAttribs(&textAttribs[cc].color,
\r
1901 &textAttribs[cc].effects,
\r
1902 defaultTextAttribs[cc]);
\r
1907 SetDefaultSounds()
\r
1908 { // [HGM] only sounds for which no option exists
\r
1910 for (cc = ColorNormal; cc < NColorClasses; cc++) {
\r
1911 textAttribs[cc].sound.name = strdup("");
\r
1912 textAttribs[cc].sound.data = NULL;
\r
1918 { // [HGM] import name from appData first
\r
1921 for (cc = (ColorClass)0; cc < ColorNormal; cc++) {
\r
1922 textAttribs[cc].sound.name = strdup((&appData.soundShout)[cc]);
\r
1923 textAttribs[cc].sound.data = NULL;
\r
1924 MyLoadSound(&textAttribs[cc].sound);
\r
1926 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1927 sounds[sc].name = strdup((&appData.soundMove)[sc]);
\r
1928 sounds[sc].data = NULL;
\r
1929 MyLoadSound(&sounds[sc]);
\r
1934 SetDefaultsFromList()
\r
1935 { // [HGM] ini: take defaults from argDescriptor list
\r
1938 for(i=0; argDescriptors[i].argName != NULL; i++) {
\r
1939 if(argDescriptors[i].defaultValue != INVALID)
\r
1940 switch(argDescriptors[i].argType) {
\r
1944 *(Boolean *) argDescriptors[i].argLoc = (int)argDescriptors[i].defaultValue;
\r
1950 *(int *) argDescriptors[i].argLoc = (int)argDescriptors[i].defaultValue;
\r
1954 case ArgSettingsFilename:
\r
1955 *(char **) argDescriptors[i].argLoc = (char *)argDescriptors[i].defaultValue;
\r
1957 case ArgBoardSize:
\r
1958 *(BoardSize *) argDescriptors[i].argLoc = (BoardSize)argDescriptors[i].defaultValue;
\r
1960 case ArgFloat: // floats cannot be casted to int without precision loss
\r
1961 default: ; // some arg types cannot be initialized through table
\r
1967 InitAppData(LPSTR lpCmdLine)
\r
1970 char buf[ARG_MAX], currDir[MSG_SIZ];
\r
1973 programName = szAppName;
\r
1975 /* Initialize to defaults */
\r
1976 SetDefaultsFromList(); // this sets most defaults
\r
1978 // some parameters for which there are no options!
\r
1979 appData.Iconic = FALSE; /*unused*/
\r
1980 appData.cmailGameName = "";
\r
1981 appData.icsEngineAnalyze = FALSE;
\r
1983 // float: casting to int is not harmless, so default cannot be contained in table
\r
1984 appData.timeDelay = TIME_DELAY;
\r
1986 // colors have platform-dependent option format and internal representation
\r
1987 // their setting and parsing must remain in front-end
\r
1988 lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);
\r
1989 darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);
\r
1990 whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);
\r
1991 blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);
\r
1992 highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);
\r
1993 premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);
\r
1994 consoleBackgroundColor = ParseColorName(COLOR_BKGD);
\r
1995 // the following must be moved out of appData to front-end variables
\r
1996 appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );
\r
1997 appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );
\r
1998 appData.highlightArrowColor = ParseColorName( "#FFFF80" );
\r
2000 // some complex, platform-dependent stuff
\r
2001 SetDefaultTextAttribs();
\r
2002 SetDefaultSounds();
\r
2004 memset(&dcb, 0, sizeof(DCB)); // required by VS 2002 +
\r
2005 dcb.DCBlength = sizeof(DCB);
\r
2006 dcb.BaudRate = 9600;
\r
2007 dcb.fBinary = TRUE;
\r
2008 dcb.fParity = FALSE;
\r
2009 dcb.fOutxCtsFlow = FALSE;
\r
2010 dcb.fOutxDsrFlow = FALSE;
\r
2011 dcb.fDtrControl = DTR_CONTROL_ENABLE;
\r
2012 dcb.fDsrSensitivity = FALSE;
\r
2013 dcb.fTXContinueOnXoff = TRUE;
\r
2014 dcb.fOutX = FALSE;
\r
2016 dcb.fNull = FALSE;
\r
2017 dcb.fRtsControl = RTS_CONTROL_ENABLE;
\r
2018 dcb.fAbortOnError = FALSE;
\r
2020 dcb.Parity = SPACEPARITY;
\r
2021 dcb.StopBits = ONESTOPBIT;
\r
2023 /* Point font array elements to structures and
\r
2024 parse default font names */
\r
2025 for (i=0; i<NUM_FONTS; i++) {
\r
2026 for (j=0; j<NUM_SIZES; j++) {
\r
2027 font[j][i] = &fontRec[j][i];
\r
2028 ParseFontName(font[j][i]->def, &font[j][i]->mfp);
\r
2032 /* Parse default settings file if any */
\r
2033 if (ParseSettingsFile(settingsFileName, buf)) {
\r
2034 settingsFileName = strdup(buf);
\r
2037 /* Parse command line */
\r
2038 ParseArgs(StringGet, &lpCmdLine);
\r
2040 /* [HGM] make sure board size is acceptable */
\r
2041 if(appData.NrFiles > BOARD_FILES ||
\r
2042 appData.NrRanks > BOARD_RANKS )
\r
2043 DisplayFatalError("Recompile with BOARD_RANKS or BOARD_FILES, to support this size", 0, 2);
\r
2045 /* [HGM] After parsing the options from the .ini file, and overruling them
\r
2046 * with options from the command line, we now make an even higher priority
\r
2047 * overrule by WB options attached to the engine command line. This so that
\r
2048 * tournament managers can use WB options (such as /timeOdds) that follow
\r
2051 if(appData.firstChessProgram != NULL) {
\r
2052 char *p = StrStr(appData.firstChessProgram, "WBopt");
\r
2053 static char *f = "first";
\r
2054 char buf[MSG_SIZ], *q = buf;
\r
2055 if(p != NULL) { // engine command line contains WinBoard options
\r
2056 sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"
\r
2057 ParseArgs(StringGet, &q);
\r
2058 p[-1] = 0; // cut them offengine command line
\r
2061 // now do same for second chess program
\r
2062 if(appData.secondChessProgram != NULL) {
\r
2063 char *p = StrStr(appData.secondChessProgram, "WBopt");
\r
2064 static char *s = "second";
\r
2065 char buf[MSG_SIZ], *q = buf;
\r
2066 if(p != NULL) { // engine command line contains WinBoard options
\r
2067 sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"
\r
2068 ParseArgs(StringGet, &q);
\r
2069 p[-1] = 0; // cut them offengine command line
\r
2074 /* Propagate options that affect others */
\r
2075 if (appData.matchMode || appData.matchGames) chessProgram = TRUE;
\r
2076 if (appData.icsActive || appData.noChessProgram) {
\r
2077 chessProgram = FALSE; /* not local chess program mode */
\r
2080 /* Open startup dialog if needed */
\r
2081 if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||
\r
2082 (appData.icsActive && *appData.icsHost == NULLCHAR) ||
\r
2083 (chessProgram && (*appData.firstChessProgram == NULLCHAR ||
\r
2084 *appData.secondChessProgram == NULLCHAR))) {
\r
2087 lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);
\r
2088 DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);
\r
2089 FreeProcInstance(lpProc);
\r
2092 /* Make sure save files land in the right (?) directory */
\r
2093 if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {
\r
2094 appData.saveGameFile = strdup(buf);
\r
2096 if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {
\r
2097 appData.savePositionFile = strdup(buf);
\r
2100 /* Finish initialization for fonts and sounds */
\r
2101 for (i=0; i<NUM_FONTS; i++) {
\r
2102 for (j=0; j<NUM_SIZES; j++) {
\r
2103 CreateFontInMF(font[j][i]);
\r
2106 /* xboard, and older WinBoards, controlled the move sound with the
\r
2107 appData.ringBellAfterMoves option. In the current WinBoard, we
\r
2108 always turn the option on (so that the backend will call us),
\r
2109 then let the user turn the sound off by setting it to silence if
\r
2110 desired. To accommodate old winboard.ini files saved by old
\r
2111 versions of WinBoard, we also turn off the sound if the option
\r
2112 was initially set to false. */
\r
2113 if (!appData.ringBellAfterMoves) {
\r
2114 sounds[(int)SoundMove].name = strdup("");
\r
2115 appData.ringBellAfterMoves = TRUE;
\r
2117 GetCurrentDirectory(MSG_SIZ, currDir);
\r
2118 SetCurrentDirectory(installDir);
\r
2120 SetCurrentDirectory(currDir);
\r
2122 p = icsTextMenuString;
\r
2123 if (p[0] == '@') {
\r
2124 FILE* f = fopen(p + 1, "r");
\r
2126 DisplayFatalError(p + 1, errno, 2);
\r
2129 i = fread(buf, 1, sizeof(buf)-1, f);
\r
2131 buf[i] = NULLCHAR;
\r
2134 ParseIcsTextMenu(strdup(p));
\r
2141 HMENU hmenu = GetMenu(hwndMain);
\r
2143 (void) EnableMenuItem(hmenu, IDM_CommPort,
\r
2144 MF_BYCOMMAND|((appData.icsActive &&
\r
2145 *appData.icsCommPort != NULLCHAR) ?
\r
2146 MF_ENABLED : MF_GRAYED));
\r
2147 (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,
\r
2148 MF_BYCOMMAND|(saveSettingsOnExit ?
\r
2149 MF_CHECKED : MF_UNCHECKED));
\r
2152 // [HGM] args: these three cases taken out to stay in front-end
\r
2154 SaveFontArg(FILE *f, ArgDescriptor *ad)
\r
2155 { // in WinBoard every board size has its own font, and the "argLoc" identifies the table,
\r
2156 // while the curent board size determines the element. This system should be ported to XBoard.
\r
2157 // What the table contains pointers to, and how to print the font description, remains platform-dependent
\r
2159 for (bs=0; bs<NUM_SIZES; bs++) {
\r
2160 MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;
\r
2161 fprintf(f, "/size=%s ", sizeInfo[bs].name);
\r
2162 fprintf(f, "/%s=\"%s:%g%s%s%s%s%sc%d\"\n",
\r
2163 ad->argName, mfp->faceName, mfp->pointSize,
\r
2164 mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",
\r
2165 mfp->bold ? "b" : "",
\r
2166 mfp->italic ? "i" : "",
\r
2167 mfp->underline ? "u" : "",
\r
2168 mfp->strikeout ? "s" : "",
\r
2169 (int)mfp->charset);
\r
2175 { // [HGM] copy the names from the internal WB variables to appData
\r
2178 for (cc = (ColorClass)0; cc < ColorNormal; cc++)
\r
2179 (&appData.soundShout)[cc] = textAttribs[cc].sound.name;
\r
2180 for (sc = (SoundClass)0; sc < NSoundClasses; sc++)
\r
2181 (&appData.soundMove)[sc] = sounds[sc].name;
\r
2185 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
\r
2186 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
\r
2187 MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];
\r
2188 fprintf(f, "/%s=\"%s%s%s%s%s#%02lx%02lx%02lx\"\n", ad->argName,
\r
2189 (ta->effects & CFE_BOLD) ? "b" : "",
\r
2190 (ta->effects & CFE_ITALIC) ? "i" : "",
\r
2191 (ta->effects & CFE_UNDERLINE) ? "u" : "",
\r
2192 (ta->effects & CFE_STRIKEOUT) ? "s" : "",
\r
2193 (ta->effects) ? " " : "",
\r
2194 ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);
\r
2198 SaveColor(FILE *f, ArgDescriptor *ad)
\r
2199 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
\r
2200 COLORREF color = *(COLORREF *)ad->argLoc;
\r
2201 fprintf(f, "/%s=#%02lx%02lx%02lx\n", ad->argName,
\r
2202 color&0xff, (color>>8)&0xff, (color>>16)&0xff);
\r
2207 { // [HGM] args: allows testing if main window is realized from back-end
\r
2208 return hwndMain != NULL;
\r
2212 SaveSettings(char* name)
\r
2215 ArgDescriptor *ad;
\r
2216 char dir[MSG_SIZ];
\r
2218 if (!MainWindowUp()) return;
\r
2220 GetCurrentDirectory(MSG_SIZ, dir);
\r
2221 SetCurrentDirectory(installDir);
\r
2222 f = fopen(name, "w");
\r
2223 SetCurrentDirectory(dir);
\r
2225 DisplayError(name, errno);
\r
2228 fprintf(f, ";\n");
\r
2229 fprintf(f, "; %s Save Settings file\n", PACKAGE_STRING);
\r
2230 fprintf(f, ";\n");
\r
2231 fprintf(f, "; You can edit the values of options that are already set in this file,\n");
\r
2232 fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");
\r
2233 fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");
\r
2234 fprintf(f, ";\n");
\r
2236 GetActualPlacement(hwndMain, &wpMain);
\r
2237 GetActualPlacement(hwndConsole, &wpConsole);
\r
2238 GetActualPlacement(commentDialog, &wpComment);
\r
2239 GetActualPlacement(editTagsDialog, &wpTags);
\r
2240 GetActualPlacement(gameListDialog, &wpGameList);
\r
2242 /* [AS] Move history */
\r
2243 wpMoveHistory.visible = MoveHistoryIsUp();
\r
2244 GetActualPlacement(moveHistoryDialog, &wpMoveHistory);
\r
2246 /* [AS] Eval graph */
\r
2247 wpEvalGraph.visible = EvalGraphIsUp();
\r
2248 GetActualPlacement(evalGraphDialog, &wpEvalGraph);
\r
2250 /* [AS] Engine output */
\r
2251 wpEngineOutput.visible = EngineOutputIsUp();
\r
2252 GetActualPlacement(engineOutputDialog, &wpEngineOutput);
\r
2254 // [HGM] in WB we have to copy sound names to appData first
\r
2257 for (ad = argDescriptors; ad->argName != NULL; ad++) {
\r
2258 if (!ad->save) continue;
\r
2259 switch (ad->argType) {
\r
2262 char *p = *(char **)ad->argLoc;
\r
2263 if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {
\r
2264 /* Quote multiline values or \-containing values
\r
2265 with { } if possible */
\r
2266 fprintf(f, "/%s={%s}\n", ad->argName, p);
\r
2268 /* Else quote with " " */
\r
2269 fprintf(f, "/%s=\"", ad->argName);
\r
2271 if (*p == '\n') fprintf(f, "\n");
\r
2272 else if (*p == '\r') fprintf(f, "\\r");
\r
2273 else if (*p == '\t') fprintf(f, "\\t");
\r
2274 else if (*p == '\b') fprintf(f, "\\b");
\r
2275 else if (*p == '\f') fprintf(f, "\\f");
\r
2276 else if (*p < ' ') fprintf(f, "\\%03o", *p);
\r
2277 else if (*p == '\"') fprintf(f, "\\\"");
\r
2278 else if (*p == '\\') fprintf(f, "\\\\");
\r
2282 fprintf(f, "\"\n");
\r
2288 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);
\r
2291 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - wpMain.x); // [HGM] placement: stor relative value
\r
2294 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - wpMain.y);
\r
2297 fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);
\r
2300 fprintf(f, "/%s=%s\n", ad->argName,
\r
2301 (*(Boolean *)ad->argLoc) ? "true" : "false");
\r
2304 if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2307 if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2315 if (strchr(*(char **)ad->argLoc, '\"')) {
\r
2316 fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);
\r
2318 fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);
\r
2321 case ArgBoardSize:
\r
2322 fprintf(f, "/%s=%s\n", ad->argName,
\r
2323 sizeInfo[*(BoardSize *)ad->argLoc].name);
\r
2326 SaveFontArg(f, ad);
\r
2328 case ArgCommSettings:
\r
2329 PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);
\r
2331 case ArgSettingsFilename: ;
\r
2339 /*---------------------------------------------------------------------------*\
\r
2341 * GDI board drawing routines
\r
2343 \*---------------------------------------------------------------------------*/
\r
2345 /* [AS] Draw square using background texture */
\r
2346 static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )
\r
2351 return; /* Should never happen! */
\r
2354 SetGraphicsMode( dst, GM_ADVANCED );
\r
2361 /* X reflection */
\r
2366 x.eDx = (FLOAT) dw + dx - 1;
\r
2369 SetWorldTransform( dst, &x );
\r
2372 /* Y reflection */
\r
2378 x.eDy = (FLOAT) dh + dy - 1;
\r
2380 SetWorldTransform( dst, &x );
\r
2388 x.eDx = (FLOAT) dx;
\r
2389 x.eDy = (FLOAT) dy;
\r
2392 SetWorldTransform( dst, &x );
\r
2396 BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );
\r
2404 SetWorldTransform( dst, &x );
\r
2406 ModifyWorldTransform( dst, 0, MWT_IDENTITY );
\r
2409 /* [AS] [HGM] Make room for more piece types, so all pieces can be different */
\r
2411 PM_WP = (int) WhitePawn,
\r
2412 PM_WN = (int) WhiteKnight,
\r
2413 PM_WB = (int) WhiteBishop,
\r
2414 PM_WR = (int) WhiteRook,
\r
2415 PM_WQ = (int) WhiteQueen,
\r
2416 PM_WF = (int) WhiteFerz,
\r
2417 PM_WW = (int) WhiteWazir,
\r
2418 PM_WE = (int) WhiteAlfil,
\r
2419 PM_WM = (int) WhiteMan,
\r
2420 PM_WO = (int) WhiteCannon,
\r
2421 PM_WU = (int) WhiteUnicorn,
\r
2422 PM_WH = (int) WhiteNightrider,
\r
2423 PM_WA = (int) WhiteAngel,
\r
2424 PM_WC = (int) WhiteMarshall,
\r
2425 PM_WAB = (int) WhiteCardinal,
\r
2426 PM_WD = (int) WhiteDragon,
\r
2427 PM_WL = (int) WhiteLance,
\r
2428 PM_WS = (int) WhiteCobra,
\r
2429 PM_WV = (int) WhiteFalcon,
\r
2430 PM_WSG = (int) WhiteSilver,
\r
2431 PM_WG = (int) WhiteGrasshopper,
\r
2432 PM_WK = (int) WhiteKing,
\r
2433 PM_BP = (int) BlackPawn,
\r
2434 PM_BN = (int) BlackKnight,
\r
2435 PM_BB = (int) BlackBishop,
\r
2436 PM_BR = (int) BlackRook,
\r
2437 PM_BQ = (int) BlackQueen,
\r
2438 PM_BF = (int) BlackFerz,
\r
2439 PM_BW = (int) BlackWazir,
\r
2440 PM_BE = (int) BlackAlfil,
\r
2441 PM_BM = (int) BlackMan,
\r
2442 PM_BO = (int) BlackCannon,
\r
2443 PM_BU = (int) BlackUnicorn,
\r
2444 PM_BH = (int) BlackNightrider,
\r
2445 PM_BA = (int) BlackAngel,
\r
2446 PM_BC = (int) BlackMarshall,
\r
2447 PM_BG = (int) BlackGrasshopper,
\r
2448 PM_BAB = (int) BlackCardinal,
\r
2449 PM_BD = (int) BlackDragon,
\r
2450 PM_BL = (int) BlackLance,
\r
2451 PM_BS = (int) BlackCobra,
\r
2452 PM_BV = (int) BlackFalcon,
\r
2453 PM_BSG = (int) BlackSilver,
\r
2454 PM_BK = (int) BlackKing
\r
2457 static HFONT hPieceFont = NULL;
\r
2458 static HBITMAP hPieceMask[(int) EmptySquare];
\r
2459 static HBITMAP hPieceFace[(int) EmptySquare];
\r
2460 static int fontBitmapSquareSize = 0;
\r
2461 static char pieceToFontChar[(int) EmptySquare] =
\r
2462 { 'p', 'n', 'b', 'r', 'q',
\r
2463 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',
\r
2464 'k', 'o', 'm', 'v', 't', 'w',
\r
2465 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',
\r
2468 extern BOOL SetCharTable( char *table, const char * map );
\r
2469 /* [HGM] moved to backend.c */
\r
2471 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )
\r
2474 BYTE r1 = GetRValue( color );
\r
2475 BYTE g1 = GetGValue( color );
\r
2476 BYTE b1 = GetBValue( color );
\r
2482 /* Create a uniform background first */
\r
2483 hbrush = CreateSolidBrush( color );
\r
2484 SetRect( &rc, 0, 0, squareSize, squareSize );
\r
2485 FillRect( hdc, &rc, hbrush );
\r
2486 DeleteObject( hbrush );
\r
2489 /* Vertical gradient, good for pawn, knight and rook, less for queen and king */
\r
2490 int steps = squareSize / 2;
\r
2493 for( i=0; i<steps; i++ ) {
\r
2494 BYTE r = r1 - (r1-r2) * i / steps;
\r
2495 BYTE g = g1 - (g1-g2) * i / steps;
\r
2496 BYTE b = b1 - (b1-b2) * i / steps;
\r
2498 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2499 SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );
\r
2500 FillRect( hdc, &rc, hbrush );
\r
2501 DeleteObject(hbrush);
\r
2504 else if( mode == 2 ) {
\r
2505 /* Diagonal gradient, good more or less for every piece */
\r
2506 POINT triangle[3];
\r
2507 HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );
\r
2508 HBRUSH hbrush_old;
\r
2509 int steps = squareSize;
\r
2512 triangle[0].x = squareSize - steps;
\r
2513 triangle[0].y = squareSize;
\r
2514 triangle[1].x = squareSize;
\r
2515 triangle[1].y = squareSize;
\r
2516 triangle[2].x = squareSize;
\r
2517 triangle[2].y = squareSize - steps;
\r
2519 for( i=0; i<steps; i++ ) {
\r
2520 BYTE r = r1 - (r1-r2) * i / steps;
\r
2521 BYTE g = g1 - (g1-g2) * i / steps;
\r
2522 BYTE b = b1 - (b1-b2) * i / steps;
\r
2524 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2525 hbrush_old = SelectObject( hdc, hbrush );
\r
2526 Polygon( hdc, triangle, 3 );
\r
2527 SelectObject( hdc, hbrush_old );
\r
2528 DeleteObject(hbrush);
\r
2533 SelectObject( hdc, hpen );
\r
2538 [AS] The method I use to create the bitmaps it a bit tricky, but it
\r
2539 seems to work ok. The main problem here is to find the "inside" of a chess
\r
2540 piece: follow the steps as explained below.
\r
2542 static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
\r
2546 COLORREF chroma = RGB(0xFF,0x00,0xFF);
\r
2550 int backColor = whitePieceColor;
\r
2551 int foreColor = blackPieceColor;
\r
2553 if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {
\r
2554 backColor = appData.fontBackColorWhite;
\r
2555 foreColor = appData.fontForeColorWhite;
\r
2557 else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {
\r
2558 backColor = appData.fontBackColorBlack;
\r
2559 foreColor = appData.fontForeColorBlack;
\r
2563 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2565 hbm_old = SelectObject( hdc, hbm );
\r
2569 rc.right = squareSize;
\r
2570 rc.bottom = squareSize;
\r
2572 /* Step 1: background is now black */
\r
2573 FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );
\r
2575 GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );
\r
2577 pt.x = (squareSize - sz.cx) / 2;
\r
2578 pt.y = (squareSize - sz.cy) / 2;
\r
2580 SetBkMode( hdc, TRANSPARENT );
\r
2581 SetTextColor( hdc, chroma );
\r
2582 /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */
\r
2583 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2585 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
\r
2586 /* Step 3: the area outside the piece is filled with white */
\r
2587 // FloodFill( hdc, 0, 0, chroma );
\r
2588 ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );
\r
2589 ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big
\r
2590 ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );
\r
2591 ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );
\r
2592 SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
\r
2594 Step 4: this is the tricky part, the area inside the piece is filled with black,
\r
2595 but if the start point is not inside the piece we're lost!
\r
2596 There should be a better way to do this... if we could create a region or path
\r
2597 from the fill operation we would be fine for example.
\r
2599 // FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );
\r
2600 ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );
\r
2602 { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */
\r
2603 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2604 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2606 SelectObject( dc2, bm2 );
\r
2607 BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy
\r
2608 BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2609 BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2610 BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2611 BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2614 DeleteObject( bm2 );
\r
2617 SetTextColor( hdc, 0 );
\r
2619 Step 5: some fonts have "disconnected" areas that are skipped by the fill:
\r
2620 draw the piece again in black for safety.
\r
2622 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2624 SelectObject( hdc, hbm_old );
\r
2626 if( hPieceMask[index] != NULL ) {
\r
2627 DeleteObject( hPieceMask[index] );
\r
2630 hPieceMask[index] = hbm;
\r
2633 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2635 SelectObject( hdc, hbm );
\r
2638 HDC dc1 = CreateCompatibleDC( hdc_window );
\r
2639 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2640 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2642 SelectObject( dc1, hPieceMask[index] );
\r
2643 SelectObject( dc2, bm2 );
\r
2644 FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );
\r
2645 BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );
\r
2648 Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves
\r
2649 the piece background and deletes (makes transparent) the rest.
\r
2650 Thanks to that mask, we are free to paint the background with the greates
\r
2651 freedom, as we'll be able to mask off the unwanted parts when finished.
\r
2652 We use this, to make gradients and give the pieces a "roundish" look.
\r
2654 SetPieceBackground( hdc, backColor, 2 );
\r
2655 BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );
\r
2659 DeleteObject( bm2 );
\r
2662 SetTextColor( hdc, foreColor );
\r
2663 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2665 SelectObject( hdc, hbm_old );
\r
2667 if( hPieceFace[index] != NULL ) {
\r
2668 DeleteObject( hPieceFace[index] );
\r
2671 hPieceFace[index] = hbm;
\r
2674 static int TranslatePieceToFontPiece( int piece )
\r
2704 case BlackMarshall:
\r
2708 case BlackNightrider:
\r
2714 case BlackUnicorn:
\r
2718 case BlackGrasshopper:
\r
2730 case BlackCardinal:
\r
2737 case WhiteMarshall:
\r
2741 case WhiteNightrider:
\r
2747 case WhiteUnicorn:
\r
2751 case WhiteGrasshopper:
\r
2763 case WhiteCardinal:
\r
2772 void CreatePiecesFromFont()
\r
2775 HDC hdc_window = NULL;
\r
2781 if( fontBitmapSquareSize < 0 ) {
\r
2782 /* Something went seriously wrong in the past: do not try to recreate fonts! */
\r
2786 if( appData.renderPiecesWithFont == NULL || appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {
\r
2787 fontBitmapSquareSize = -1;
\r
2791 if( fontBitmapSquareSize != squareSize ) {
\r
2792 hdc_window = GetDC( hwndMain );
\r
2793 hdc = CreateCompatibleDC( hdc_window );
\r
2795 if( hPieceFont != NULL ) {
\r
2796 DeleteObject( hPieceFont );
\r
2799 for( i=0; i<=(int)BlackKing; i++ ) {
\r
2800 hPieceMask[i] = NULL;
\r
2801 hPieceFace[i] = NULL;
\r
2807 if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {
\r
2808 fontHeight = appData.fontPieceSize;
\r
2811 fontHeight = (fontHeight * squareSize) / 100;
\r
2813 lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
\r
2815 lf.lfEscapement = 0;
\r
2816 lf.lfOrientation = 0;
\r
2817 lf.lfWeight = FW_NORMAL;
\r
2819 lf.lfUnderline = 0;
\r
2820 lf.lfStrikeOut = 0;
\r
2821 lf.lfCharSet = DEFAULT_CHARSET;
\r
2822 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
2823 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
2824 lf.lfQuality = PROOF_QUALITY;
\r
2825 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
\r
2826 strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );
\r
2827 lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';
\r
2829 hPieceFont = CreateFontIndirect( &lf );
\r
2831 if( hPieceFont == NULL ) {
\r
2832 fontBitmapSquareSize = -2;
\r
2835 /* Setup font-to-piece character table */
\r
2836 if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {
\r
2837 /* No (or wrong) global settings, try to detect the font */
\r
2838 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {
\r
2840 SetCharTable(pieceToFontChar, "phbrqkojntwl");
\r
2842 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {
\r
2843 /* DiagramTT* family */
\r
2844 SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");
\r
2846 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {
\r
2847 /* Fairy symbols */
\r
2848 SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
\r
2850 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {
\r
2851 /* Good Companion (Some characters get warped as literal :-( */
\r
2852 char s[] = "1cmWG0??S??oYI23wgQU";
\r
2853 s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;
\r
2854 SetCharTable(pieceToFontChar, s);
\r
2857 /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */
\r
2858 SetCharTable(pieceToFontChar, "pnbrqkomvtwl");
\r
2862 /* Create bitmaps */
\r
2863 hfont_old = SelectObject( hdc, hPieceFont );
\r
2864 for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */
\r
2865 if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */
\r
2866 CreatePieceMaskFromFont( hdc_window, hdc, i );
\r
2868 SelectObject( hdc, hfont_old );
\r
2870 fontBitmapSquareSize = squareSize;
\r
2874 if( hdc != NULL ) {
\r
2878 if( hdc_window != NULL ) {
\r
2879 ReleaseDC( hwndMain, hdc_window );
\r
2884 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)
\r
2888 sprintf(name, "%s%d%s", piece, squareSize, suffix);
\r
2889 if (gameInfo.event &&
\r
2890 strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&
\r
2891 strcmp(name, "k80s") == 0) {
\r
2892 strcpy(name, "tim");
\r
2894 return LoadBitmap(hinst, name);
\r
2898 /* Insert a color into the program's logical palette
\r
2899 structure. This code assumes the given color is
\r
2900 the result of the RGB or PALETTERGB macro, and it
\r
2901 knows how those macros work (which is documented).
\r
2904 InsertInPalette(COLORREF color)
\r
2906 LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);
\r
2908 if (pLogPal->palNumEntries++ >= PALETTESIZE) {
\r
2909 DisplayFatalError("Too many colors", 0, 1);
\r
2910 pLogPal->palNumEntries--;
\r
2914 pe->peFlags = (char) 0;
\r
2915 pe->peRed = (char) (0xFF & color);
\r
2916 pe->peGreen = (char) (0xFF & (color >> 8));
\r
2917 pe->peBlue = (char) (0xFF & (color >> 16));
\r
2923 InitDrawingColors()
\r
2925 if (pLogPal == NULL) {
\r
2926 /* Allocate enough memory for a logical palette with
\r
2927 * PALETTESIZE entries and set the size and version fields
\r
2928 * of the logical palette structure.
\r
2930 pLogPal = (NPLOGPALETTE)
\r
2931 LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +
\r
2932 (sizeof(PALETTEENTRY) * (PALETTESIZE))));
\r
2933 pLogPal->palVersion = 0x300;
\r
2935 pLogPal->palNumEntries = 0;
\r
2937 InsertInPalette(lightSquareColor);
\r
2938 InsertInPalette(darkSquareColor);
\r
2939 InsertInPalette(whitePieceColor);
\r
2940 InsertInPalette(blackPieceColor);
\r
2941 InsertInPalette(highlightSquareColor);
\r
2942 InsertInPalette(premoveHighlightColor);
\r
2944 /* create a logical color palette according the information
\r
2945 * in the LOGPALETTE structure.
\r
2947 hPal = CreatePalette((LPLOGPALETTE) pLogPal);
\r
2949 lightSquareBrush = CreateSolidBrush(lightSquareColor);
\r
2950 blackSquareBrush = CreateSolidBrush(blackPieceColor);
\r
2951 darkSquareBrush = CreateSolidBrush(darkSquareColor);
\r
2952 whitePieceBrush = CreateSolidBrush(whitePieceColor);
\r
2953 blackPieceBrush = CreateSolidBrush(blackPieceColor);
\r
2954 iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
\r
2955 explodeBrush = CreateSolidBrush(highlightSquareColor); // [HGM] atomic
\r
2956 /* [AS] Force rendering of the font-based pieces */
\r
2957 if( fontBitmapSquareSize > 0 ) {
\r
2958 fontBitmapSquareSize = 0;
\r
2964 BoardWidth(int boardSize, int n)
\r
2965 { /* [HGM] argument n added to allow different width and height */
\r
2966 int lineGap = sizeInfo[boardSize].lineGap;
\r
2968 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
2969 lineGap = appData.overrideLineGap;
\r
2972 return (n + 1) * lineGap +
\r
2973 n * sizeInfo[boardSize].squareSize;
\r
2976 /* Respond to board resize by dragging edge */
\r
2978 ResizeBoard(int newSizeX, int newSizeY, int flags)
\r
2980 BoardSize newSize = NUM_SIZES - 1;
\r
2981 static int recurse = 0;
\r
2982 if (IsIconic(hwndMain)) return;
\r
2983 if (recurse > 0) return;
\r
2985 while (newSize > 0) {
\r
2986 InitDrawingSizes(newSize+1000, 0); // [HGM] kludge to update sizeInfo without visible effects
\r
2987 if(newSizeX >= sizeInfo[newSize].cliWidth &&
\r
2988 newSizeY >= sizeInfo[newSize].cliHeight) break;
\r
2991 boardSize = newSize;
\r
2992 InitDrawingSizes(boardSize, flags);
\r
2999 InitDrawingSizes(BoardSize boardSize, int flags)
\r
3001 int i, boardWidth, boardHeight; /* [HGM] height treated separately */
\r
3002 ChessSquare piece;
\r
3003 static int oldBoardSize = -1, oldTinyLayout = 0;
\r
3005 SIZE clockSize, messageSize;
\r
3007 char buf[MSG_SIZ];
\r
3009 HMENU hmenu = GetMenu(hwndMain);
\r
3010 RECT crect, wrect, oldRect;
\r
3012 LOGBRUSH logbrush;
\r
3014 int suppressVisibleEffects = 0; // [HGM] kludge to request updating sizeInfo only
\r
3015 if((int)boardSize >= 1000 ) { boardSize -= 1000; suppressVisibleEffects = 1; }
\r
3017 /* [HGM] call with -2 uses old size (for if nr of files, ranks changes) */
\r
3018 if(boardSize == (BoardSize)(-2) ) boardSize = oldBoardSize;
\r
3020 oldRect.left = wpMain.x; //[HGM] placement: remember previous window params
\r
3021 oldRect.top = wpMain.y;
\r
3022 oldRect.right = wpMain.x + wpMain.width;
\r
3023 oldRect.bottom = wpMain.y + wpMain.height;
\r
3025 tinyLayout = sizeInfo[boardSize].tinyLayout;
\r
3026 smallLayout = sizeInfo[boardSize].smallLayout;
\r
3027 squareSize = sizeInfo[boardSize].squareSize;
\r
3028 lineGap = sizeInfo[boardSize].lineGap;
\r
3029 minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted */
\r
3031 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3032 lineGap = appData.overrideLineGap;
\r
3035 if (tinyLayout != oldTinyLayout) {
\r
3036 long style = GetWindowLong(hwndMain, GWL_STYLE);
\r
3038 style &= ~WS_SYSMENU;
\r
3039 InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize,
\r
3040 "&Minimize\tCtrl+F4");
\r
3042 style |= WS_SYSMENU;
\r
3043 RemoveMenu(hmenu, IDM_Minimize, MF_BYCOMMAND);
\r
3045 SetWindowLong(hwndMain, GWL_STYLE, style);
\r
3047 for (i=0; menuBarText[tinyLayout][i]; i++) {
\r
3048 ModifyMenu(hmenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP,
\r
3049 (UINT)GetSubMenu(hmenu, i), menuBarText[tinyLayout][i]);
\r
3051 DrawMenuBar(hwndMain);
\r
3054 boardWidth = BoardWidth(boardSize, BOARD_WIDTH);
\r
3055 boardHeight = BoardWidth(boardSize, BOARD_HEIGHT);
\r
3057 /* Get text area sizes */
\r
3058 hdc = GetDC(hwndMain);
\r
3059 if (appData.clockMode) {
\r
3060 sprintf(buf, "White: %s", TimeString(23*60*60*1000L));
\r
3062 sprintf(buf, "White");
\r
3064 oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);
\r
3065 GetTextExtentPoint(hdc, buf, strlen(buf), &clockSize);
\r
3066 SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);
\r
3067 str = "We only care about the height here";
\r
3068 GetTextExtentPoint(hdc, str, strlen(str), &messageSize);
\r
3069 SelectObject(hdc, oldFont);
\r
3070 ReleaseDC(hwndMain, hdc);
\r
3072 /* Compute where everything goes */
\r
3073 if((first.programLogo || second.programLogo) && !tinyLayout) {
\r
3074 /* [HGM] logo: if either logo is on, reserve space for it */
\r
3075 logoHeight = 2*clockSize.cy;
\r
3076 leftLogoRect.left = OUTER_MARGIN;
\r
3077 leftLogoRect.right = leftLogoRect.left + 4*clockSize.cy;
\r
3078 leftLogoRect.top = OUTER_MARGIN;
\r
3079 leftLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3081 rightLogoRect.right = OUTER_MARGIN + boardWidth;
\r
3082 rightLogoRect.left = rightLogoRect.right - 4*clockSize.cy;
\r
3083 rightLogoRect.top = OUTER_MARGIN;
\r
3084 rightLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3087 whiteRect.left = leftLogoRect.right;
\r
3088 whiteRect.right = OUTER_MARGIN + boardWidth/2 - INNER_MARGIN/2;
\r
3089 whiteRect.top = OUTER_MARGIN;
\r
3090 whiteRect.bottom = whiteRect.top + logoHeight;
\r
3092 blackRect.right = rightLogoRect.left;
\r
3093 blackRect.left = whiteRect.right + INNER_MARGIN;
\r
3094 blackRect.top = whiteRect.top;
\r
3095 blackRect.bottom = whiteRect.bottom;
\r
3097 whiteRect.left = OUTER_MARGIN;
\r
3098 whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2;
\r
3099 whiteRect.top = OUTER_MARGIN;
\r
3100 whiteRect.bottom = whiteRect.top + clockSize.cy;
\r
3102 blackRect.left = whiteRect.right + INNER_MARGIN;
\r
3103 blackRect.right = blackRect.left + boardWidth/2 - 1;
\r
3104 blackRect.top = whiteRect.top;
\r
3105 blackRect.bottom = whiteRect.bottom;
\r
3108 messageRect.left = OUTER_MARGIN + MESSAGE_LINE_LEFTMARGIN;
\r
3109 if (appData.showButtonBar) {
\r
3110 messageRect.right = OUTER_MARGIN + boardWidth // [HGM] logo: expressed independent of clock placement
\r
3111 - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN;
\r
3113 messageRect.right = OUTER_MARGIN + boardWidth;
\r
3115 messageRect.top = whiteRect.bottom + INNER_MARGIN;
\r
3116 messageRect.bottom = messageRect.top + messageSize.cy;
\r
3118 boardRect.left = OUTER_MARGIN;
\r
3119 boardRect.right = boardRect.left + boardWidth;
\r
3120 boardRect.top = messageRect.bottom + INNER_MARGIN;
\r
3121 boardRect.bottom = boardRect.top + boardHeight;
\r
3123 sizeInfo[boardSize].cliWidth = boardRect.right + OUTER_MARGIN;
\r
3124 sizeInfo[boardSize].cliHeight = boardRect.bottom + OUTER_MARGIN;
\r
3125 oldBoardSize = boardSize;
\r
3126 oldTinyLayout = tinyLayout;
\r
3127 winW = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN;
\r
3128 winH = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) +
\r
3129 GetSystemMetrics(SM_CYCAPTION) + boardRect.bottom + OUTER_MARGIN;
\r
3130 if(suppressVisibleEffects) return; // [HGM] when called for filling sizeInfo only
\r
3131 wpMain.width = winW; // [HGM] placement: set through temporary which can used by initial sizing choice
\r
3132 wpMain.height = winH; // without disturbing window attachments
\r
3133 GetWindowRect(hwndMain, &wrect);
\r
3134 SetWindowPos(hwndMain, NULL, 0, 0, wpMain.width, wpMain.height,
\r
3135 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3137 // [HGM] placement: let attached windows follow size change.
\r
3138 ReattachAfterSize( &oldRect, wpMain.width, wpMain.height, moveHistoryDialog, &wpMoveHistory );
\r
3139 ReattachAfterSize( &oldRect, wpMain.width, wpMain.height, evalGraphDialog, &wpEvalGraph );
\r
3140 ReattachAfterSize( &oldRect, wpMain.width, wpMain.height, engineOutputDialog, &wpEngineOutput );