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 "winboard.h"
\r
84 #include "frontend.h"
\r
85 #include "backend.h"
\r
87 #include "wclipbrd.h"
\r
88 #include "wgamelist.h"
\r
89 #include "wedittags.h"
\r
90 #include "woptions.h"
\r
91 #include "wsockerr.h"
\r
92 #include "defaults.h"
\r
96 //void InitEngineUCI( const char * iniDir, ChessProgramState * cps );
\r
99 void mysrandom(unsigned int seed);
\r
101 extern int whiteFlag, blackFlag;
\r
102 Boolean flipClock = FALSE;
\r
103 extern HANDLE chatHandle[];
\r
104 extern int ics_type;
\r
106 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);
\r
107 VOID NewVariantPopup(HWND hwnd);
\r
108 int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,
\r
109 /*char*/int promoChar));
\r
110 void AnimateAtomicCapture(int fromX, int fromY, int toX, int toY, int nFrames);
\r
111 void DisplayMove P((int moveNumber));
\r
112 Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen));
\r
113 void ChatPopUp P(());
\r
115 ChessSquare piece;
\r
116 POINT pos; /* window coordinates of current pos */
\r
117 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
118 POINT from; /* board coordinates of the piece's orig pos */
\r
119 POINT to; /* board coordinates of the piece's new pos */
\r
122 static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };
\r
125 POINT start; /* window coordinates of start pos */
\r
126 POINT pos; /* window coordinates of current pos */
\r
127 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
128 POINT from; /* board coordinates of the piece's orig pos */
\r
131 static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} };
\r
134 POINT sq[2]; /* board coordinates of from, to squares */
\r
137 static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} };
\r
138 static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };
\r
140 typedef struct { // [HGM] atomic
\r
141 int fromX, fromY, toX, toY, radius;
\r
144 static ExplodeInfo explodeInfo;
\r
146 /* Window class names */
\r
147 char szAppName[] = "WinBoard";
\r
148 char szConsoleName[] = "WBConsole";
\r
150 /* Title bar text */
\r
151 char szTitle[] = "WinBoard";
\r
152 char szConsoleTitle[] = "I C S Interaction";
\r
155 char *settingsFileName;
\r
156 BOOLEAN saveSettingsOnExit;
\r
157 char installDir[MSG_SIZ];
\r
159 BoardSize boardSize;
\r
160 BOOLEAN chessProgram;
\r
161 static int boardX, boardY;
\r
162 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
\r
163 static int squareSize, lineGap, minorSize;
\r
164 static int winWidth, winHeight, winW, winH;
\r
165 static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo
\r
166 static int logoHeight = 0;
\r
167 static char messageText[MESSAGE_TEXT_MAX];
\r
168 static int clockTimerEvent = 0;
\r
169 static int loadGameTimerEvent = 0;
\r
170 static int analysisTimerEvent = 0;
\r
171 static DelayedEventCallback delayedTimerCallback;
\r
172 static int delayedTimerEvent = 0;
\r
173 static int buttonCount = 2;
\r
174 char *icsTextMenuString;
\r
176 char *firstChessProgramNames;
\r
177 char *secondChessProgramNames;
\r
179 #define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */
\r
181 #define PALETTESIZE 256
\r
183 HINSTANCE hInst; /* current instance */
\r
184 HWND hwndMain = NULL; /* root window*/
\r
185 HWND hwndConsole = NULL;
\r
186 BOOLEAN alwaysOnTop = FALSE;
\r
188 COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
\r
189 blackPieceColor, highlightSquareColor, premoveHighlightColor;
\r
191 ColorClass currentColorClass;
\r
193 HWND hCommPort = NULL; /* currently open comm port */
\r
194 static HWND hwndPause; /* pause button */
\r
195 static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */
\r
196 static HBRUSH lightSquareBrush, darkSquareBrush,
\r
197 blackSquareBrush, /* [HGM] for band between board and holdings */
\r
198 explodeBrush, /* [HGM] atomic */
\r
199 whitePieceBrush, blackPieceBrush, iconBkgndBrush /*, outlineBrush*/;
\r
200 static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];
\r
201 static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];
\r
202 static HPEN gridPen = NULL;
\r
203 static HPEN highlightPen = NULL;
\r
204 static HPEN premovePen = NULL;
\r
205 static NPLOGPALETTE pLogPal;
\r
206 static BOOL paletteChanged = FALSE;
\r
207 static HICON iconWhite, iconBlack, iconCurrent;
\r
208 static int doingSizing = FALSE;
\r
209 static int lastSizing = 0;
\r
210 static int prevStderrPort;
\r
211 static HBITMAP userLogo;
\r
213 /* [AS] Support for background textures */
\r
214 #define BACK_TEXTURE_MODE_DISABLED 0
\r
215 #define BACK_TEXTURE_MODE_PLAIN 1
\r
216 #define BACK_TEXTURE_MODE_FULL_RANDOM 2
\r
218 static HBITMAP liteBackTexture = NULL;
\r
219 static HBITMAP darkBackTexture = NULL;
\r
220 static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
221 static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
222 static int backTextureSquareSize = 0;
\r
223 static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_SIZE][BOARD_SIZE];
\r
225 #if __GNUC__ && !defined(_winmajor)
\r
226 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */
\r
228 #if defined(_winmajor)
\r
229 #define oldDialog (_winmajor < 4)
\r
231 #define oldDialog 0
\r
235 char *defaultTextAttribs[] =
\r
237 COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,
\r
238 COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,
\r
248 int cliWidth, cliHeight;
\r
251 SizeInfo sizeInfo[] =
\r
253 { "tiny", 21, 0, 1, 1, 0, 0 },
\r
254 { "teeny", 25, 1, 1, 1, 0, 0 },
\r
255 { "dinky", 29, 1, 1, 1, 0, 0 },
\r
256 { "petite", 33, 1, 1, 1, 0, 0 },
\r
257 { "slim", 37, 2, 1, 0, 0, 0 },
\r
258 { "small", 40, 2, 1, 0, 0, 0 },
\r
259 { "mediocre", 45, 2, 1, 0, 0, 0 },
\r
260 { "middling", 49, 2, 0, 0, 0, 0 },
\r
261 { "average", 54, 2, 0, 0, 0, 0 },
\r
262 { "moderate", 58, 3, 0, 0, 0, 0 },
\r
263 { "medium", 64, 3, 0, 0, 0, 0 },
\r
264 { "bulky", 72, 3, 0, 0, 0, 0 },
\r
265 { "large", 80, 3, 0, 0, 0, 0 },
\r
266 { "big", 87, 3, 0, 0, 0, 0 },
\r
267 { "huge", 95, 3, 0, 0, 0, 0 },
\r
268 { "giant", 108, 3, 0, 0, 0, 0 },
\r
269 { "colossal", 116, 4, 0, 0, 0, 0 },
\r
270 { "titanic", 129, 4, 0, 0, 0, 0 },
\r
271 { NULL, 0, 0, 0, 0, 0, 0 }
\r
274 #define MF(x) {x, {{0,}, 0. }, {0, }, 0}
\r
275 MyFont fontRec[NUM_SIZES][NUM_FONTS] =
\r
277 { 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
278 { 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
279 { 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
280 { 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
281 { 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
282 { 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
283 { 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
284 { 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
285 { 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
286 { 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
287 { 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
288 { 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
289 { 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
290 { 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
291 { 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
292 { 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
293 { 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
294 { 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
297 MyFont *font[NUM_SIZES][NUM_FONTS];
\r
306 #define BUTTON_WIDTH (tinyLayout ? 16 : 32)
\r
307 #define N_BUTTONS 5
\r
309 MyButtonDesc buttonDesc[N_BUTTONS] =
\r
311 {"<<", IDM_ToStart, NULL, NULL},
\r
312 {"<", IDM_Backward, NULL, NULL},
\r
313 {"P", IDM_Pause, NULL, NULL},
\r
314 {">", IDM_Forward, NULL, NULL},
\r
315 {">>", IDM_ToEnd, NULL, NULL},
\r
318 int tinyLayout = 0, smallLayout = 0;
\r
319 #define MENU_BAR_ITEMS 7
\r
320 char *menuBarText[2][MENU_BAR_ITEMS+1] = {
\r
321 { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },
\r
322 { "&F", "&M", "&A", "&S", "&O", "&H", NULL },
\r
326 MySound sounds[(int)NSoundClasses];
\r
327 MyTextAttribs textAttribs[(int)NColorClasses];
\r
329 MyColorizeAttribs colorizeAttribs[] = {
\r
330 { (COLORREF)0, 0, "Shout Text" },
\r
331 { (COLORREF)0, 0, "SShout/CShout" },
\r
332 { (COLORREF)0, 0, "Channel 1 Text" },
\r
333 { (COLORREF)0, 0, "Channel Text" },
\r
334 { (COLORREF)0, 0, "Kibitz Text" },
\r
335 { (COLORREF)0, 0, "Tell Text" },
\r
336 { (COLORREF)0, 0, "Challenge Text" },
\r
337 { (COLORREF)0, 0, "Request Text" },
\r
338 { (COLORREF)0, 0, "Seek Text" },
\r
339 { (COLORREF)0, 0, "Normal Text" },
\r
340 { (COLORREF)0, 0, "None" }
\r
345 static char *commentTitle;
\r
346 static char *commentText;
\r
347 static int commentIndex;
\r
348 static Boolean editComment = FALSE;
\r
349 HWND commentDialog = NULL;
\r
350 BOOLEAN commentDialogUp = FALSE;
\r
351 static int commentX, commentY, commentH, commentW;
\r
353 static char *analysisTitle;
\r
354 static char *analysisText;
\r
355 HWND analysisDialog = NULL;
\r
356 BOOLEAN analysisDialogUp = FALSE;
\r
357 static int analysisX, analysisY, analysisH, analysisW;
\r
359 char errorTitle[MSG_SIZ];
\r
360 char errorMessage[2*MSG_SIZ];
\r
361 HWND errorDialog = NULL;
\r
362 BOOLEAN moveErrorMessageUp = FALSE;
\r
363 BOOLEAN consoleEcho = TRUE;
\r
364 CHARFORMAT consoleCF;
\r
365 COLORREF consoleBackgroundColor;
\r
367 char *programVersion;
\r
373 typedef int CPKind;
\r
382 SOCKET sock2; /* stderr socket for OpenRcmd */
\r
385 #define INPUT_SOURCE_BUF_SIZE 4096
\r
387 typedef struct _InputSource {
\r
394 char buf[INPUT_SOURCE_BUF_SIZE];
\r
398 InputCallback func;
\r
399 struct _InputSource *second; /* for stderr thread on CPRcmd */
\r
403 InputSource *consoleInputSource;
\r
408 VOID ConsoleOutput(char* data, int length, int forceVisible);
\r
409 VOID ConsoleCreate();
\r
411 ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
412 VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
\r
413 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
\r
414 VOID ParseCommSettings(char *arg, DCB *dcb);
\r
416 StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
417 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
\r
418 void ParseIcsTextMenu(char *icsTextMenuString);
\r
419 VOID PopUpMoveDialog(char firstchar);
\r
420 VOID PopUpNameDialog(char firstchar);
\r
421 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
\r
425 int GameListOptions();
\r
427 HWND moveHistoryDialog = NULL;
\r
428 BOOLEAN moveHistoryDialogUp = FALSE;
\r
430 WindowPlacement wpMoveHistory;
\r
432 HWND evalGraphDialog = NULL;
\r
433 BOOLEAN evalGraphDialogUp = FALSE;
\r
435 WindowPlacement wpEvalGraph;
\r
437 HWND engineOutputDialog = NULL;
\r
438 BOOLEAN engineOutputDialogUp = FALSE;
\r
440 WindowPlacement wpEngineOutput;
\r
441 WindowPlacement wpGameList;
\r
442 WindowPlacement wpConsole;
\r
444 VOID MoveHistoryPopUp();
\r
445 VOID MoveHistoryPopDown();
\r
446 VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
447 BOOL MoveHistoryIsUp();
\r
449 VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
450 VOID EvalGraphPopUp();
\r
451 VOID EvalGraphPopDown();
\r
452 BOOL EvalGraphIsUp();
\r
454 VOID EngineOutputPopUp();
\r
455 VOID EngineOutputPopDown();
\r
456 BOOL EngineOutputIsUp();
\r
457 VOID EngineOutputUpdate( FrontEndProgramStats * stats );
\r
459 VOID EngineOptionsPopup(); // [HGM] settings
\r
461 VOID GothicPopUp(char *title, VariantClass variant);
\r
463 * Setting "frozen" should disable all user input other than deleting
\r
464 * the window. We do this while engines are initializing themselves.
\r
466 static int frozen = 0;
\r
467 static int oldMenuItemState[MENU_BAR_ITEMS];
\r
473 if (frozen) return;
\r
475 hmenu = GetMenu(hwndMain);
\r
476 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
477 oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
\r
479 DrawMenuBar(hwndMain);
\r
482 /* Undo a FreezeUI */
\r
488 if (!frozen) return;
\r
490 hmenu = GetMenu(hwndMain);
\r
491 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
492 EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
\r
494 DrawMenuBar(hwndMain);
\r
497 static int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them
\r
499 /* JAWS preparation patch (WinBoard for the sight impaired). Define required insertions as empty */
\r
505 #define JAWS_ALT_INTERCEPT
\r
506 #define JAWS_KB_NAVIGATION
\r
507 #define JAWS_MENU_ITEMS
\r
508 #define JAWS_SILENCE
\r
509 #define JAWS_REPLAY
\r
511 #define JAWS_COPYRIGHT
\r
512 #define JAWS_DELETE(X) X
\r
513 #define SAYMACHINEMOVE()
\r
517 /*---------------------------------------------------------------------------*\
\r
521 \*---------------------------------------------------------------------------*/
\r
524 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
\r
525 LPSTR lpCmdLine, int nCmdShow)
\r
528 HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
\r
529 // INITCOMMONCONTROLSEX ex;
\r
533 LoadLibrary("RICHED32.DLL");
\r
534 consoleCF.cbSize = sizeof(CHARFORMAT);
\r
536 if (!InitApplication(hInstance)) {
\r
539 if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
\r
545 // InitCommonControlsEx(&ex);
\r
546 InitCommonControls();
\r
548 hAccelMain = LoadAccelerators (hInstance, szAppName);
\r
549 hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
\r
550 hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
\r
552 /* Acquire and dispatch messages until a WM_QUIT message is received. */
\r
554 while (GetMessage(&msg, /* message structure */
\r
555 NULL, /* handle of window receiving the message */
\r
556 0, /* lowest message to examine */
\r
557 0)) /* highest message to examine */
\r
560 if(msg.message == WM_CHAR && msg.wParam == '\t') {
\r
561 // [HGM] navigate: switch between all windows with tab
\r
562 HWND e1 = NULL, e2 = NULL, mh = NULL, hInput = NULL, hText = NULL;
\r
563 int i, currentElement = 0;
\r
565 // first determine what element of the chain we come from (if any)
\r
566 if(appData.icsActive) {
\r
567 hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);
\r
568 hText = GetDlgItem(hwndConsole, OPT_ConsoleText);
\r
570 if(engineOutputDialog && EngineOutputIsUp()) {
\r
571 e1 = GetDlgItem(engineOutputDialog, IDC_EngineMemo1);
\r
572 e2 = GetDlgItem(engineOutputDialog, IDC_EngineMemo2);
\r
574 if(moveHistoryDialog && MoveHistoryIsUp()) {
\r
575 mh = GetDlgItem(moveHistoryDialog, IDC_MoveHistory);
\r
577 if(msg.hwnd == hwndMain) currentElement = 7 ; else
\r
578 if(msg.hwnd == engineOutputDialog) currentElement = 2; else
\r
579 if(msg.hwnd == e1) currentElement = 2; else
\r
580 if(msg.hwnd == e2) currentElement = 3; else
\r
581 if(msg.hwnd == moveHistoryDialog) currentElement = 4; else
\r
582 if(msg.hwnd == mh) currentElement = 4; else
\r
583 if(msg.hwnd == evalGraphDialog) currentElement = 6; else
\r
584 if(msg.hwnd == hText) currentElement = 5; else
\r
585 if(msg.hwnd == hInput) currentElement = 6; else
\r
586 for (i = 0; i < N_BUTTONS; i++) {
\r
587 if (buttonDesc[i].hwnd == msg.hwnd) { currentElement = 1; break; }
\r
590 // determine where to go to
\r
591 if(currentElement) { HWND h = NULL; int direction = GetKeyState(VK_SHIFT) < 0 ? -1 : 1;
\r
593 currentElement = (currentElement + direction) % 7;
\r
594 switch(currentElement) {
\r
596 h = hwndMain; break; // passing this case always makes the loop exit
\r
598 h = buttonDesc[0].hwnd; break; // could be NULL
\r
600 if(!EngineOutputIsUp()) continue; // skip closed auxiliary windows
\r
603 if(!EngineOutputIsUp()) continue;
\r
606 if(!MoveHistoryIsUp()) continue;
\r
608 // case 6: // input to eval graph does not seem to get here!
\r
609 // if(!EvalGraphIsUp()) continue;
\r
610 // h = evalGraphDialog; break;
\r
612 if(!appData.icsActive) continue;
\r
616 if(!appData.icsActive) continue;
\r
622 if(currentElement > 4 && IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);
\r
623 if(currentElement < 5 && IsIconic(hwndMain)) ShowWindow(hwndMain, SW_RESTORE); // all open together
\r
626 continue; // this message now has been processed
\r
630 if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
\r
631 !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
\r
632 !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
\r
633 !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
\r
634 !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
\r
635 !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
\r
636 !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
\r
637 !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) && JAWS_ACCEL
\r
638 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
\r
639 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
\r
640 int done = 0, i; // [HGM] chat: dispatch cat-box messages
\r
641 for(i=0; i<MAX_CHAT; i++)
\r
642 if(chatHandle[i] && IsDialogMessage(chatHandle[i], &msg)) {
\r
645 if(done) continue; // [HGM] chat: end patch
\r
646 TranslateMessage(&msg); /* Translates virtual key codes */
\r
647 DispatchMessage(&msg); /* Dispatches message to window */
\r
652 return (msg.wParam); /* Returns the value from PostQuitMessage */
\r
655 /*---------------------------------------------------------------------------*\
\r
657 * Initialization functions
\r
659 \*---------------------------------------------------------------------------*/
\r
663 { // update user logo if necessary
\r
664 static char oldUserName[MSG_SIZ], *curName;
\r
666 if(appData.autoLogo) {
\r
667 curName = UserName();
\r
668 if(strcmp(curName, oldUserName)) {
\r
669 sprintf(oldUserName, "logos\\%s.bmp", curName);
\r
670 userLogo = LoadImage( 0, oldUserName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
671 strcpy(oldUserName, curName);
\r
677 InitApplication(HINSTANCE hInstance)
\r
681 /* Fill in window class structure with parameters that describe the */
\r
684 wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
\r
685 wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
\r
686 wc.cbClsExtra = 0; /* No per-class extra data. */
\r
687 wc.cbWndExtra = 0; /* No per-window extra data. */
\r
688 wc.hInstance = hInstance; /* Owner of this class */
\r
689 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
690 wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
\r
691 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
\r
692 wc.lpszMenuName = szAppName; /* Menu name from .RC */
\r
693 wc.lpszClassName = szAppName; /* Name to register as */
\r
695 /* Register the window class and return success/failure code. */
\r
696 if (!RegisterClass(&wc)) return FALSE;
\r
698 wc.style = CS_HREDRAW | CS_VREDRAW;
\r
699 wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
\r
701 wc.cbWndExtra = DLGWINDOWEXTRA;
\r
702 wc.hInstance = hInstance;
\r
703 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
704 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
\r
705 wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
\r
706 wc.lpszMenuName = NULL;
\r
707 wc.lpszClassName = szConsoleName;
\r
709 if (!RegisterClass(&wc)) return FALSE;
\r
714 /* Set by InitInstance, used by EnsureOnScreen */
\r
715 int screenHeight, screenWidth;
\r
718 EnsureOnScreen(int *x, int *y, int minX, int minY)
\r
720 // int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
\r
721 /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
\r
722 if (*x > screenWidth - 32) *x = 0;
\r
723 if (*y > screenHeight - 32) *y = 0;
\r
724 if (*x < minX) *x = minX;
\r
725 if (*y < minY) *y = minY;
\r
729 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
\r
731 HWND hwnd; /* Main window handle. */
\r
733 WINDOWPLACEMENT wp;
\r
736 hInst = hInstance; /* Store instance handle in our global variable */
\r
738 if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
\r
739 *filepart = NULLCHAR;
\r
741 GetCurrentDirectory(MSG_SIZ, installDir);
\r
743 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise
\r
744 screenWidth = screenHeight = 1000; // [HGM] placement: kludge to allow calling EnsureOnScreen from InitAppData
\r
745 InitAppData(lpCmdLine); /* Get run-time parameters */
\r
746 if (appData.debugMode) {
\r
747 debugFP = fopen(appData.nameOfDebugFile, "w");
\r
748 setbuf(debugFP, NULL);
\r
753 // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()
\r
754 // InitEngineUCI( installDir, &second );
\r
756 /* Create a main window for this application instance. */
\r
757 hwnd = CreateWindow(szAppName, szTitle,
\r
758 (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
\r
759 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
\r
760 NULL, NULL, hInstance, NULL);
\r
763 /* If window could not be created, return "failure" */
\r
768 /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */
\r
769 if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {
\r
770 first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
772 if (first.programLogo == NULL && appData.debugMode) {
\r
773 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );
\r
775 } else if(appData.autoLogo) {
\r
776 if(appData.firstDirectory && appData.firstDirectory[0]) {
\r
778 sprintf(buf, "%s/logo.bmp", appData.firstDirectory);
\r
779 first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
783 if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {
\r
784 second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
786 if (second.programLogo == NULL && appData.debugMode) {
\r
787 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );
\r
789 } else if(appData.autoLogo) {
\r
791 if(appData.icsActive) { // [HGM] logo: in ICS mode second can be used for ICS
\r
792 sprintf(buf, "logos\\%s.bmp", appData.icsHost);
\r
793 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
795 if(appData.secondDirectory && appData.secondDirectory[0]) {
\r
796 sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);
\r
797 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
803 iconWhite = LoadIcon(hInstance, "icon_white");
\r
804 iconBlack = LoadIcon(hInstance, "icon_black");
\r
805 iconCurrent = iconWhite;
\r
806 InitDrawingColors();
\r
807 screenHeight = GetSystemMetrics(SM_CYSCREEN);
\r
808 screenWidth = GetSystemMetrics(SM_CXSCREEN);
\r
809 for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
\r
810 /* Compute window size for each board size, and use the largest
\r
811 size that fits on this screen as the default. */
\r
812 InitDrawingSizes((BoardSize)(ibs+1000), 0);
\r
813 if (boardSize == (BoardSize)-1 &&
\r
814 winH <= screenHeight
\r
815 - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10
\r
816 && winW <= screenWidth) {
\r
817 boardSize = (BoardSize)ibs;
\r
821 InitDrawingSizes(boardSize, 0);
\r
823 buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
\r
825 /* [AS] Load textures if specified */
\r
826 ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );
\r
828 if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {
\r
829 liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
830 liteBackTextureMode = appData.liteBackTextureMode;
\r
832 if (liteBackTexture == NULL && appData.debugMode) {
\r
833 fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );
\r
837 if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {
\r
838 darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
839 darkBackTextureMode = appData.darkBackTextureMode;
\r
841 if (darkBackTexture == NULL && appData.debugMode) {
\r
842 fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );
\r
846 mysrandom( (unsigned) time(NULL) );
\r
848 /* [AS] Restore layout */
\r
849 if( wpMoveHistory.visible ) {
\r
850 MoveHistoryPopUp();
\r
853 if( wpEvalGraph.visible ) {
\r
857 if( wpEngineOutput.visible ) {
\r
858 EngineOutputPopUp();
\r
863 /* Make the window visible; update its client area; and return "success" */
\r
864 EnsureOnScreen(&boardX, &boardY, minX, minY);
\r
865 wp.length = sizeof(WINDOWPLACEMENT);
\r
867 wp.showCmd = nCmdShow;
\r
868 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
\r
869 wp.rcNormalPosition.left = boardX;
\r
870 wp.rcNormalPosition.right = boardX + winWidth;
\r
871 wp.rcNormalPosition.top = boardY;
\r
872 wp.rcNormalPosition.bottom = boardY + winHeight;
\r
873 SetWindowPlacement(hwndMain, &wp);
\r
875 if(!appData.noGUI) SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
876 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
880 SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
881 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
883 ShowWindow(hwndConsole, nCmdShow);
\r
885 if(!appData.noGUI) UpdateWindow(hwnd); else ShowWindow(hwnd, SW_MINIMIZE);
\r
886 if(gameListDialog) SetFocus(gameListDialog); // [HGM] jaws: for if we clicked multi-game game file
\r
894 ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
\r
895 ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
\r
896 ArgSettingsFilename,
\r
897 ArgX, ArgY, ArgZ // [HGM] placement: for window-placement options stored relative to main window
\r
905 String *pString; // ArgString
\r
906 int *pInt; // ArgInt
\r
907 float *pFloat; // ArgFloat
\r
908 Boolean *pBoolean; // ArgBoolean
\r
909 COLORREF *pColor; // ArgColor
\r
910 ColorClass cc; // ArgAttribs
\r
911 String *pFilename; // ArgFilename
\r
912 BoardSize *pBoardSize; // ArgBoardSize
\r
913 int whichFont; // ArgFont
\r
914 DCB *pDCB; // ArgCommSettings
\r
915 String *pFilename; // ArgSettingsFilename
\r
923 ArgDescriptor argDescriptors[] = {
\r
924 /* positional arguments */
\r
925 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
926 { "", ArgNone, NULL },
\r
927 /* keyword arguments */
\r
929 { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },
\r
930 { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },
\r
931 { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },
\r
932 { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },
\r
933 { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },
\r
934 { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },
\r
935 { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },
\r
936 { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },
\r
937 { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },
\r
938 { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },
\r
939 { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },
\r
940 { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },
\r
941 { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },
\r
942 { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },
\r
943 { "initString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
944 { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
945 { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },
\r
946 { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,
\r
948 { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,
\r
950 { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,
\r
952 { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },
\r
953 { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,
\r
955 { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },
\r
956 { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
957 { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
958 { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
959 { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
960 { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },
\r
961 { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },
\r
962 { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
963 { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
964 { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
965 { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
966 { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
967 { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
968 { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
969 { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
970 { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
971 { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
972 /*!!bitmapDirectory?*/
\r
973 { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
974 { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
975 { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
976 { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
977 { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },
\r
978 { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },
\r
979 { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },
\r
980 { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },
\r
981 { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },
\r
982 { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },
\r
983 { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },
\r
984 { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },
\r
985 { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
986 { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
987 { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
988 { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
989 { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
990 { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
991 { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
992 { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
993 { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
994 { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
995 { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
996 { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
997 { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },
\r
998 { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },
\r
999 { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
1000 { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
1001 { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },
\r
1002 { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },
\r
1003 { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },
\r
1004 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
1005 { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
1006 { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
1007 { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
1008 { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },
\r
1009 { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },
\r
1010 { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },
\r
1011 { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },
\r
1012 { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
1013 { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
1014 { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
1015 { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
1016 { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
1017 { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
1018 { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
1019 { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
1020 { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },
\r
1021 { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },
\r
1022 { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
1023 { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
1024 { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
1025 { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
1026 { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },
\r
1027 { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },
\r
1028 { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
1029 { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
1030 { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },
\r
1031 { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },
\r
1032 { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
1033 { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
1034 { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },
\r
1035 { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },
\r
1036 { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
1037 { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
1038 { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
1039 { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
1040 { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
1041 { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
1042 { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },
\r
1043 { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },
\r
1044 { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
1045 { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
1046 { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },
\r
1047 { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },
\r
1048 { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
1049 { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
1050 { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },
\r
1051 { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1052 { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1053 { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1054 { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },
\r
1055 { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1056 { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1057 { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1058 { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },
\r
1059 { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1060 { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1061 { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1062 { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },
\r
1063 { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1064 { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1065 { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1066 { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors,
\r
1067 FALSE }, /* only so that old WinBoard.ini files from betas can be read */
\r
1068 { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },
\r
1069 { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },
\r
1070 { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },
\r
1071 { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },
\r
1072 { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },
\r
1073 { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },
\r
1074 { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE }, /* [AS] */
\r
1075 { "boardSize", ArgBoardSize, (LPVOID) &boardSize,
\r
1076 TRUE }, /* must come after all fonts */
\r
1077 { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },
\r
1078 { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,
\r
1079 FALSE }, /* historical; kept only so old winboard.ini files will parse */
\r
1080 { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },
\r
1081 { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },
\r
1082 { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
1083 { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
1084 { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },
\r
1085 { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1086 { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1087 { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1088 { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },
\r
1089 { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },
\r
1090 { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
1091 { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
1092 { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },
\r
1093 { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },
\r
1094 { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
1095 { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
1096 { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },
\r
1097 { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },
\r
1098 { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
1099 { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
1100 { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },
\r
1101 { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },
\r
1102 { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
1103 { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
1104 { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },
\r
1105 { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1106 { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1107 { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1109 { "cmailGameName", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
1110 { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
1112 { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },
\r
1113 { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1114 { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1115 { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1116 { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },
\r
1117 { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1118 { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1119 { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1120 { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },
\r
1121 { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },
\r
1122 { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
1123 { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
1124 { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },
\r
1125 { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },
\r
1126 { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
1127 { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
1128 { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },
\r
1129 { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },
\r
1130 { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
1131 { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
1132 { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },
\r
1133 { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },
\r
1134 { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
1135 { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
1136 { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },
\r
1137 { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },
\r
1138 { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
1139 { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
1140 { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },
\r
1141 { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },
\r
1142 { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },
\r
1143 { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1144 { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1145 { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },
\r
1146 { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},
\r
1147 { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},
\r
1148 { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1149 { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1150 { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},
\r
1151 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1152 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1153 { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },
\r
1154 { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1155 { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1156 { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },
\r
1157 { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },
\r
1158 { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1159 { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1160 { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },
\r
1161 { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },
\r
1162 { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },
\r
1163 { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1164 { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1165 { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },
\r
1166 { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },
\r
1167 { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1168 { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1169 { "highlightLastMove", ArgBoolean,
\r
1170 (LPVOID) &appData.highlightLastMove, TRUE },
\r
1171 { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1172 { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1173 { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1174 { "highlightDragging", ArgBoolean,
\r
1175 (LPVOID) &appData.highlightDragging, TRUE },
\r
1176 { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },
\r
1177 { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1178 { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1179 { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },
\r
1180 { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },
\r
1181 { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1182 { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1183 { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },
\r
1184 { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },
\r
1185 { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },
\r
1186 { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },
\r
1187 { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },
\r
1188 { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },
\r
1189 { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },
\r
1190 { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },
\r
1191 { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },
\r
1192 { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },
\r
1193 { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },
\r
1194 { "soundShout", ArgFilename,
\r
1195 (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },
\r
1196 { "soundSShout", ArgFilename,
\r
1197 (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },
\r
1198 { "soundChannel1", ArgFilename,
\r
1199 (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },
\r
1200 { "soundChannel", ArgFilename,
\r
1201 (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },
\r
1202 { "soundKibitz", ArgFilename,
\r
1203 (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },
\r
1204 { "soundTell", ArgFilename,
\r
1205 (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },
\r
1206 { "soundChallenge", ArgFilename,
\r
1207 (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },
\r
1208 { "soundRequest", ArgFilename,
\r
1209 (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },
\r
1210 { "soundSeek", ArgFilename,
\r
1211 (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },
\r
1212 { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },
\r
1213 { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },
\r
1214 { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },
\r
1215 { "soundIcsLoss", ArgFilename,
\r
1216 (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },
\r
1217 { "soundIcsDraw", ArgFilename,
\r
1218 (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },
\r
1219 { "soundIcsUnfinished", ArgFilename,
\r
1220 (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},
\r
1221 { "soundIcsAlarm", ArgFilename,
\r
1222 (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },
\r
1223 { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },
\r
1224 { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },
\r
1225 { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1226 { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1227 { "reuseChessPrograms", ArgBoolean,
\r
1228 (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */
\r
1229 { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },
\r
1230 { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },
\r
1231 { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1232 { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1233 { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },
\r
1234 { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1235 { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1236 { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },
\r
1237 { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },
\r
1238 { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },
\r
1239 { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1240 { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1241 { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },
\r
1242 { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },
\r
1243 { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,
\r
1245 { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,
\r
1247 { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1248 { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1249 { "variant", ArgString, (LPVOID) &appData.variant, FALSE },
\r
1250 { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion, FALSE },
\r
1251 { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,FALSE },
\r
1252 { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },
\r
1253 { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },
\r
1254 { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1255 { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1256 /* [AS] New features */
\r
1257 { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE },
\r
1258 { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE },
\r
1259 { "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE },
\r
1260 { "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE },
\r
1261 { "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE },
\r
1262 { "darkBackTextureFile", ArgString, (LPVOID) &appData.darkBackTextureFile, TRUE },
\r
1263 { "liteBackTextureMode", ArgInt, (LPVOID) &appData.liteBackTextureMode, TRUE },
\r
1264 { "darkBackTextureMode", ArgInt, (LPVOID) &appData.darkBackTextureMode, TRUE },
\r
1265 { "renderPiecesWithFont", ArgString, (LPVOID) &appData.renderPiecesWithFont, TRUE },
\r
1266 { "fontPieceToCharTable", ArgString, (LPVOID) &appData.fontToPieceTable, TRUE },
\r
1267 { "fontPieceBackColorWhite", ArgColor, (LPVOID) &appData.fontBackColorWhite, TRUE },
\r
1268 { "fontPieceForeColorWhite", ArgColor, (LPVOID) &appData.fontForeColorWhite, TRUE },
\r
1269 { "fontPieceBackColorBlack", ArgColor, (LPVOID) &appData.fontBackColorBlack, TRUE },
\r
1270 { "fontPieceForeColorBlack", ArgColor, (LPVOID) &appData.fontForeColorBlack, TRUE },
\r
1271 { "fontPieceSize", ArgInt, (LPVOID) &appData.fontPieceSize, TRUE },
\r
1272 { "overrideLineGap", ArgInt, (LPVOID) &appData.overrideLineGap, TRUE },
\r
1273 { "adjudicateLossThreshold", ArgInt, (LPVOID) &appData.adjudicateLossThreshold, TRUE },
\r
1274 { "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE },
\r
1275 { "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE },
\r
1276 { "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1277 { "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1278 { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },
\r
1279 { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE },
\r
1280 { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE },
\r
1281 { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE },
\r
1282 { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE },
\r
1283 { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE },
\r
1284 { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE },
\r
1285 { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE },
\r
1286 { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE },
\r
1287 { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE },
\r
1288 { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE },
\r
1289 { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE },
\r
1290 { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE },
\r
1291 { "firstIsUCI", ArgBoolean, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1292 { "fUCI", ArgTrue, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1293 { "secondIsUCI", ArgBoolean, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1294 { "sUCI", ArgTrue, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1295 { "firstHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1296 { "fNoOwnBookUCI", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1297 { "firstXBook", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1298 { "secondHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1299 { "sNoOwnBookUCI", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1300 { "secondXBook", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1301 { "polyglotDir", ArgFilename, (LPVOID) &appData.polyglotDir, TRUE },
\r
1302 { "usePolyglotBook", ArgBoolean, (LPVOID) &appData.usePolyglotBook, TRUE },
\r
1303 { "polyglotBook", ArgFilename, (LPVOID) &appData.polyglotBook, TRUE },
\r
1304 { "defaultHashSize", ArgInt, (LPVOID) &appData.defaultHashSize, TRUE },
\r
1305 { "defaultCacheSizeEGTB", ArgInt, (LPVOID) &appData.defaultCacheSizeEGTB, TRUE },
\r
1306 { "defaultPathEGTB", ArgFilename, (LPVOID) &appData.defaultPathEGTB, TRUE },
\r
1308 /* [HGM] board-size, adjudication and misc. options */
\r
1309 { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE },
\r
1310 { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE },
\r
1311 { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE },
\r
1312 { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE },
\r
1313 { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE },
\r
1314 { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE },
\r
1315 { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE },
\r
1316 { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE },
\r
1317 { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE },
\r
1318 { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE },
\r
1319 { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE },
\r
1320 { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE },
\r
1321 { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE },
\r
1322 { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE },
\r
1323 { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE },
\r
1324 { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE },
\r
1325 { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE },
\r
1326 { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE },
\r
1327 { "userName", ArgString, (LPVOID) &appData.userName, FALSE },
\r
1328 { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE },
\r
1329 { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE },
\r
1330 { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE },
\r
1331 { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE },
\r
1332 { "niceEngines", ArgInt, (LPVOID) &appData.niceEngines, TRUE },
\r
1333 { "firstLogo", ArgFilename, (LPVOID) &appData.firstLogo, FALSE },
\r
1334 { "secondLogo", ArgFilename, (LPVOID) &appData.secondLogo, FALSE },
\r
1335 { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE },
\r
1336 { "firstOptions", ArgString, (LPVOID) &appData.firstOptions, FALSE },
\r
1337 { "secondOptions", ArgString, (LPVOID) &appData.secondOptions, FALSE },
\r
1338 { "firstNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride1, FALSE },
\r
1339 { "secondNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride2, FALSE },
\r
1340 { "keepAlive", ArgInt, (LPVOID) &appData.keepAlive, FALSE },
\r
1341 { "icstype", ArgInt, (LPVOID) &ics_type, FALSE },
\r
1342 { "forceIllegalMoves", ArgTrue, (LPVOID) &appData.forceIllegal, FALSE },
\r
1345 { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },
\r
1346 { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },
\r
1347 { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1348 { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1349 { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },
\r
1350 { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },
\r
1351 { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1352 { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1353 { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },
\r
1354 { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },
\r
1355 { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },
\r
1356 { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE },
\r
1357 { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,
\r
1359 { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE },
\r
1360 { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE },
\r
1361 { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE },
\r
1362 { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1363 { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1364 { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE },
\r
1365 { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,
\r
1367 { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1368 { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1369 { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1370 { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE },
\r
1371 { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE },
\r
1372 { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1373 { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1374 { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1375 { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1376 { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE },
\r
1377 { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE },
\r
1378 { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1379 { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1380 { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },
\r
1381 { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },
\r
1382 { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },
\r
1383 { "zippyShortGame", ArgInt, (LPVOID)&appData.zippyShortGame, FALSE },
\r
1384 /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */
\r
1385 { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },
\r
1387 /* [HGM] options for broadcasting and time odds */
\r
1388 { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },
\r
1389 { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },
\r
1390 { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },
\r
1391 { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },
\r
1392 { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },
\r
1393 { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },
\r
1394 { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },
\r
1395 { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },
\r
1396 { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },
\r
1397 { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },
\r
1398 { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE },
\r
1400 // [HGM] placement: put all window layouts last in ini file, but man X,Y before all others
\r
1401 { "minX", ArgZ, (LPVOID) &minX, FALSE }, // [HGM] placement: to make suer auxialary windows can be placed
\r
1402 { "minY", ArgZ, (LPVOID) &minY, FALSE },
\r
1403 { "winWidth", ArgInt, (LPVOID) &winWidth, TRUE }, // [HGM] placement: dummies to remember right & bottom
\r
1404 { "winHeight", ArgInt, (LPVOID) &winHeight, TRUE }, // for attaching auxiliary windows to them
\r
1405 { "x", ArgInt, (LPVOID) &boardX, TRUE },
\r
1406 { "y", ArgInt, (LPVOID) &boardY, TRUE },
\r
1407 { "icsX", ArgX, (LPVOID) &wpConsole.x, TRUE },
\r
1408 { "icsY", ArgY, (LPVOID) &wpConsole.y, TRUE },
\r
1409 { "icsW", ArgInt, (LPVOID) &wpConsole.width, TRUE },
\r
1410 { "icsH", ArgInt, (LPVOID) &wpConsole.height, TRUE },
\r
1411 { "analysisX", ArgX, (LPVOID) &analysisX, FALSE }, // [HGM] placement: analysis window no longer exists
\r
1412 { "analysisY", ArgY, (LPVOID) &analysisY, FALSE }, // provided for compatibility with old ini files
\r
1413 { "analysisW", ArgInt, (LPVOID) &analysisW, FALSE },
\r
1414 { "analysisH", ArgInt, (LPVOID) &analysisH, FALSE },
\r
1415 { "commentX", ArgX, (LPVOID) &commentX, TRUE },
\r
1416 { "commentY", ArgY, (LPVOID) &commentY, TRUE },
\r
1417 { "commentW", ArgInt, (LPVOID) &commentW, TRUE },
\r
1418 { "commentH", ArgInt, (LPVOID) &commentH, TRUE },
\r
1419 { "tagsX", ArgX, (LPVOID) &editTagsX, TRUE },
\r
1420 { "tagsY", ArgY, (LPVOID) &editTagsY, TRUE },
\r
1421 { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },
\r
1422 { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },
\r
1423 { "gameListX", ArgX, (LPVOID) &wpGameList.x, TRUE },
\r
1424 { "gameListY", ArgY, (LPVOID) &wpGameList.y, TRUE },
\r
1425 { "gameListW", ArgInt, (LPVOID) &wpGameList.width, TRUE },
\r
1426 { "gameListH", ArgInt, (LPVOID) &wpGameList.height, TRUE },
\r
1427 /* [AS] Layout stuff */
\r
1428 { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },
\r
1429 { "moveHistoryX", ArgX, (LPVOID) &wpMoveHistory.x, TRUE },
\r
1430 { "moveHistoryY", ArgY, (LPVOID) &wpMoveHistory.y, TRUE },
\r
1431 { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },
\r
1432 { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },
\r
1434 { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },
\r
1435 { "evalGraphX", ArgX, (LPVOID) &wpEvalGraph.x, TRUE },
\r
1436 { "evalGraphY", ArgY, (LPVOID) &wpEvalGraph.y, TRUE },
\r
1437 { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },
\r
1438 { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },
\r
1440 { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },
\r
1441 { "engineOutputX", ArgX, (LPVOID) &wpEngineOutput.x, TRUE },
\r
1442 { "engineOutputY", ArgY, (LPVOID) &wpEngineOutput.y, TRUE },
\r
1443 { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },
\r
1444 { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },
\r
1446 { NULL, ArgNone, NULL, FALSE }
\r
1450 /* Kludge for indirection files on command line */
\r
1451 char* lastIndirectionFilename;
\r
1452 ArgDescriptor argDescriptorIndirection =
\r
1453 { "", ArgSettingsFilename, (LPVOID) NULL, FALSE };
\r
1457 ExitArgError(char *msg, char *badArg)
\r
1459 char buf[MSG_SIZ];
\r
1461 sprintf(buf, "%s %s", msg, badArg);
\r
1462 DisplayFatalError(buf, 0, 2);
\r
1466 /* Command line font name parser. NULL name means do nothing.
\r
1467 Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"
\r
1468 For backward compatibility, syntax without the colon is also
\r
1469 accepted, but font names with digits in them won't work in that case.
\r
1472 ParseFontName(char *name, MyFontParams *mfp)
\r
1475 if (name == NULL) return;
\r
1477 q = strchr(p, ':');
\r
1479 if (q - p >= sizeof(mfp->faceName))
\r
1480 ExitArgError("Font name too long:", name);
\r
1481 memcpy(mfp->faceName, p, q - p);
\r
1482 mfp->faceName[q - p] = NULLCHAR;
\r
1485 q = mfp->faceName;
\r
1486 while (*p && !isdigit(*p)) {
\r
1488 if (q - mfp->faceName >= sizeof(mfp->faceName))
\r
1489 ExitArgError("Font name too long:", name);
\r
1491 while (q > mfp->faceName && q[-1] == ' ') q--;
\r
1494 if (!*p) ExitArgError("Font point size missing:", name);
\r
1495 mfp->pointSize = (float) atof(p);
\r
1496 mfp->bold = (strchr(p, 'b') != NULL);
\r
1497 mfp->italic = (strchr(p, 'i') != NULL);
\r
1498 mfp->underline = (strchr(p, 'u') != NULL);
\r
1499 mfp->strikeout = (strchr(p, 's') != NULL);
\r
1502 /* Color name parser.
\r
1503 X version accepts X color names, but this one
\r
1504 handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */
\r
1506 ParseColorName(char *name)
\r
1508 int red, green, blue, count;
\r
1509 char buf[MSG_SIZ];
\r
1511 count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);
\r
1513 count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d",
\r
1514 &red, &green, &blue);
\r
1517 sprintf(buf, "Can't parse color name %s", name);
\r
1518 DisplayError(buf, 0);
\r
1519 return RGB(0, 0, 0);
\r
1521 return PALETTERGB(red, green, blue);
\r
1525 void ParseAttribs(COLORREF *color, int *effects, char* argValue)
\r
1527 char *e = argValue;
\r
1531 if (*e == 'b') eff |= CFE_BOLD;
\r
1532 else if (*e == 'i') eff |= CFE_ITALIC;
\r
1533 else if (*e == 'u') eff |= CFE_UNDERLINE;
\r
1534 else if (*e == 's') eff |= CFE_STRIKEOUT;
\r
1535 else if (*e == '#' || isdigit(*e)) break;
\r
1539 *color = ParseColorName(e);
\r
1544 ParseBoardSize(char *name)
\r
1546 BoardSize bs = SizeTiny;
\r
1547 while (sizeInfo[bs].name != NULL) {
\r
1548 if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;
\r
1551 ExitArgError("Unrecognized board size value", name);
\r
1552 return bs; /* not reached */
\r
1557 StringGet(void *getClosure)
\r
1559 char **p = (char **) getClosure;
\r
1564 FileGet(void *getClosure)
\r
1567 FILE* f = (FILE*) getClosure;
\r
1570 if (c == '\r') c = getc(f); // work around DOS format files by bypassing the '\r' completely
\r
1577 /* Parse settings file named "name". If file found, return the
\r
1578 full name in fullname and return TRUE; else return FALSE */
\r
1580 ParseSettingsFile(char *name, char fullname[MSG_SIZ])
\r
1584 int ok; char buf[MSG_SIZ];
\r
1586 ok = SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy);
\r
1587 if(!ok && strchr(name, '.') == NULL) { // [HGM] append default file-name extension '.ini' when needed
\r
1588 sprintf(buf, "%s.ini", name);
\r
1589 ok = SearchPath(installDir, buf, NULL, MSG_SIZ, fullname, &dummy);
\r
1592 f = fopen(fullname, "r");
\r
1594 ParseArgs(FileGet, f);
\r
1603 ParseArgs(GetFunc get, void *cl)
\r
1605 char argName[ARG_MAX];
\r
1606 char argValue[ARG_MAX];
\r
1607 ArgDescriptor *ad;
\r
1616 while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);
\r
1617 if (ch == NULLCHAR) break;
\r
1619 /* Comment to end of line */
\r
1621 while (ch != '\n' && ch != NULLCHAR) ch = get(cl);
\r
1623 } else if (ch == '/' || ch == '-') {
\r
1626 while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&
\r
1627 ch != '\n' && ch != '\t') {
\r
1633 for (ad = argDescriptors; ad->argName != NULL; ad++)
\r
1634 if (strcmp(ad->argName, argName + 1) == 0) break;
\r
1636 if (ad->argName == NULL)
\r
1637 ExitArgError("Unrecognized argument", argName);
\r
1639 } else if (ch == '@') {
\r
1640 /* Indirection file */
\r
1641 ad = &argDescriptorIndirection;
\r
1644 /* Positional argument */
\r
1645 ad = &argDescriptors[posarg++];
\r
1646 strcpy(argName, ad->argName);
\r
1649 if (ad->argType == ArgTrue) {
\r
1650 *(Boolean *) ad->argLoc = TRUE;
\r
1653 if (ad->argType == ArgFalse) {
\r
1654 *(Boolean *) ad->argLoc = FALSE;
\r
1658 while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
\r
1659 if (ch == NULLCHAR || ch == '\n') {
\r
1660 ExitArgError("No value provided for argument", argName);
\r
1664 // Quoting with { }. No characters have to (or can) be escaped.
\r
1665 // Thus the string cannot contain a '}' character.
\r
1685 } else if (ch == '\'' || ch == '"') {
\r
1686 // Quoting with ' ' or " ", with \ as escape character.
\r
1687 // Inconvenient for long strings that may contain Windows filenames.
\r
1704 if (ch == start) {
\r
1713 if (ad->argType == ArgFilename
\r
1714 || ad->argType == ArgSettingsFilename) {
\r
1720 ExitArgError("Incomplete \\ escape in value for", argName);
\r
1744 for (i = 0; i < 3; i++) {
\r
1745 if (ch >= '0' && ch <= '7') {
\r
1746 octval = octval*8 + (ch - '0');
\r
1753 *q++ = (char) octval;
\r
1764 while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {
\r
1771 switch (ad->argType) {
\r
1773 *(int *) ad->argLoc = atoi(argValue);
\r
1777 *(int *) ad->argLoc = atoi(argValue) + boardX; // [HGM] placement: translate stored relative to absolute
\r
1781 *(int *) ad->argLoc = atoi(argValue) + boardY; // (this is really kludgey, it should be done where used...)
\r
1785 *(int *) ad->argLoc = atoi(argValue);
\r
1786 EnsureOnScreen(&boardX, &boardY, minX, minY);
\r
1790 *(float *) ad->argLoc = (float) atof(argValue);
\r
1795 *(char **) ad->argLoc = strdup(argValue);
\r
1798 case ArgSettingsFilename:
\r
1800 char fullname[MSG_SIZ];
\r
1801 if (ParseSettingsFile(argValue, fullname)) {
\r
1802 if (ad->argLoc != NULL) {
\r
1803 *(char **) ad->argLoc = strdup(fullname);
\r
1806 if (ad->argLoc != NULL) {
\r
1808 ExitArgError("Failed to open indirection file", argValue);
\r
1815 switch (argValue[0]) {
\r
1818 *(Boolean *) ad->argLoc = TRUE;
\r
1822 *(Boolean *) ad->argLoc = FALSE;
\r
1825 ExitArgError("Unrecognized boolean argument value", argValue);
\r
1831 *(COLORREF *)ad->argLoc = ParseColorName(argValue);
\r
1834 case ArgAttribs: {
\r
1835 ColorClass cc = (ColorClass)ad->argLoc;
\r
1836 ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);
\r
1840 case ArgBoardSize:
\r
1841 *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);
\r
1845 ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);
\r
1848 case ArgCommSettings:
\r
1849 ParseCommSettings(argValue, &dcb);
\r
1853 ExitArgError("Unrecognized argument", argValue);
\r
1862 LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
\r
1864 HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
\r
1865 lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);
\r
1868 lf->lfEscapement = 0;
\r
1869 lf->lfOrientation = 0;
\r
1870 lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;
\r
1871 lf->lfItalic = mfp->italic;
\r
1872 lf->lfUnderline = mfp->underline;
\r
1873 lf->lfStrikeOut = mfp->strikeout;
\r
1874 lf->lfCharSet = DEFAULT_CHARSET;
\r
1875 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
1876 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
1877 lf->lfQuality = DEFAULT_QUALITY;
\r
1878 lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
\r
1879 strcpy(lf->lfFaceName, mfp->faceName);
\r
1883 CreateFontInMF(MyFont *mf)
\r
1885 LFfromMFP(&mf->lf, &mf->mfp);
\r
1886 if (mf->hf) DeleteObject(mf->hf);
\r
1887 mf->hf = CreateFontIndirect(&mf->lf);
\r
1891 SetDefaultTextAttribs()
\r
1894 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1895 ParseAttribs(&textAttribs[cc].color,
\r
1896 &textAttribs[cc].effects,
\r
1897 defaultTextAttribs[cc]);
\r
1902 SetDefaultSounds()
\r
1906 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1907 textAttribs[cc].sound.name = strdup("");
\r
1908 textAttribs[cc].sound.data = NULL;
\r
1910 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1911 sounds[sc].name = strdup("");
\r
1912 sounds[sc].data = NULL;
\r
1914 sounds[(int)SoundBell].name = strdup(SOUND_BELL);
\r
1922 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1923 MyLoadSound(&textAttribs[cc].sound);
\r
1925 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1926 MyLoadSound(&sounds[sc]);
\r
1931 InitAppData(LPSTR lpCmdLine)
\r
1934 char buf[ARG_MAX], currDir[MSG_SIZ];
\r
1937 programName = szAppName;
\r
1939 /* Initialize to defaults */
\r
1940 lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);
\r
1941 darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);
\r
1942 whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);
\r
1943 blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);
\r
1944 highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);
\r
1945 premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);
\r
1946 consoleBackgroundColor = ParseColorName(COLOR_BKGD);
\r
1947 SetDefaultTextAttribs();
\r
1948 SetDefaultSounds();
\r
1949 appData.movesPerSession = MOVES_PER_SESSION;
\r
1950 appData.initString = INIT_STRING;
\r
1951 appData.secondInitString = INIT_STRING;
\r
1952 appData.firstComputerString = COMPUTER_STRING;
\r
1953 appData.secondComputerString = COMPUTER_STRING;
\r
1954 appData.firstChessProgram = FIRST_CHESS_PROGRAM;
\r
1955 appData.secondChessProgram = SECOND_CHESS_PROGRAM;
\r
1956 appData.firstPlaysBlack = FALSE;
\r
1957 appData.noChessProgram = FALSE;
\r
1958 chessProgram = FALSE;
\r
1959 appData.firstHost = FIRST_HOST;
\r
1960 appData.secondHost = SECOND_HOST;
\r
1961 appData.firstDirectory = FIRST_DIRECTORY;
\r
1962 appData.secondDirectory = SECOND_DIRECTORY;
\r
1963 appData.bitmapDirectory = "";
\r
1964 appData.remoteShell = REMOTE_SHELL;
\r
1965 appData.remoteUser = "";
\r
1966 appData.timeDelay = TIME_DELAY;
\r
1967 appData.timeControl = TIME_CONTROL;
\r
1968 appData.timeIncrement = TIME_INCREMENT;
\r
1969 appData.icsActive = FALSE;
\r
1970 appData.icsHost = "";
\r
1971 appData.icsPort = ICS_PORT;
\r
1972 appData.icsCommPort = ICS_COMM_PORT;
\r
1973 appData.icsLogon = ICS_LOGON;
\r
1974 appData.icsHelper = "";
\r
1975 appData.useTelnet = FALSE;
\r
1976 appData.telnetProgram = TELNET_PROGRAM;
\r
1977 appData.gateway = "";
\r
1978 appData.loadGameFile = "";
\r
1979 appData.loadGameIndex = 0;
\r
1980 appData.saveGameFile = "";
\r
1981 appData.autoSaveGames = FALSE;
\r
1982 appData.loadPositionFile = "";
\r
1983 appData.loadPositionIndex = 1;
\r
1984 appData.savePositionFile = "";
\r
1985 appData.matchMode = FALSE;
\r
1986 appData.matchGames = 0;
\r
1987 appData.monoMode = FALSE;
\r
1988 appData.debugMode = FALSE;
\r
1989 appData.clockMode = TRUE;
\r
1990 boardSize = (BoardSize) -1; /* determine by screen size */
\r
1991 appData.Iconic = FALSE; /*unused*/
\r
1992 appData.searchTime = "";
\r
1993 appData.searchDepth = 0;
\r
1994 appData.showCoords = FALSE;
\r
1995 appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/
\r
1996 appData.autoCallFlag = FALSE;
\r
1997 appData.flipView = FALSE;
\r
1998 appData.autoFlipView = TRUE;
\r
1999 appData.cmailGameName = "";
\r
2000 appData.alwaysPromoteToQueen = FALSE;
\r
2001 appData.oldSaveStyle = FALSE;
\r
2002 appData.quietPlay = FALSE;
\r
2003 appData.showThinking = FALSE;
\r
2004 appData.ponderNextMove = TRUE;
\r
2005 appData.periodicUpdates = TRUE;
\r
2006 appData.popupExitMessage = TRUE;
\r
2007 appData.popupMoveErrors = FALSE;
\r
2008 appData.autoObserve = FALSE;
\r
2009 appData.autoComment = FALSE;
\r
2010 appData.animate = TRUE;
\r
2011 appData.animSpeed = 10;
\r
2012 appData.animateDragging = TRUE;
\r
2013 appData.highlightLastMove = TRUE;
\r
2014 appData.getMoveList = TRUE;
\r
2015 appData.testLegality = TRUE;
\r
2016 appData.premove = TRUE;
\r
2017 appData.premoveWhite = FALSE;
\r
2018 appData.premoveWhiteText = "";
\r
2019 appData.premoveBlack = FALSE;
\r
2020 appData.premoveBlackText = "";
\r
2021 appData.icsAlarm = TRUE;
\r
2022 appData.icsAlarmTime = 5000;
\r
2023 appData.autoRaiseBoard = TRUE;
\r
2024 appData.localLineEditing = TRUE;
\r
2025 appData.colorize = TRUE;
\r
2026 appData.reuseFirst = TRUE;
\r
2027 appData.reuseSecond = TRUE;
\r
2028 appData.blindfold = FALSE;
\r
2029 appData.icsEngineAnalyze = FALSE;
\r
2030 memset(&dcb, 0, sizeof(DCB)); // required by VS 2002 +
\r
2031 dcb.DCBlength = sizeof(DCB);
\r
2032 dcb.BaudRate = 9600;
\r
2033 dcb.fBinary = TRUE;
\r
2034 dcb.fParity = FALSE;
\r
2035 dcb.fOutxCtsFlow = FALSE;
\r
2036 dcb.fOutxDsrFlow = FALSE;
\r
2037 dcb.fDtrControl = DTR_CONTROL_ENABLE;
\r
2038 dcb.fDsrSensitivity = FALSE;
\r
2039 dcb.fTXContinueOnXoff = TRUE;
\r
2040 dcb.fOutX = FALSE;
\r
2042 dcb.fNull = FALSE;
\r
2043 dcb.fRtsControl = RTS_CONTROL_ENABLE;
\r
2044 dcb.fAbortOnError = FALSE;
\r
2046 dcb.Parity = SPACEPARITY;
\r
2047 dcb.StopBits = ONESTOPBIT;
\r
2048 settingsFileName = SETTINGS_FILE;
\r
2049 saveSettingsOnExit = TRUE;
\r
2050 boardX = CW_USEDEFAULT;
\r
2051 boardY = CW_USEDEFAULT;
\r
2052 analysisX = CW_USEDEFAULT;
\r
2053 analysisY = CW_USEDEFAULT;
\r
2054 analysisW = CW_USEDEFAULT;
\r
2055 analysisH = CW_USEDEFAULT;
\r
2056 commentX = CW_USEDEFAULT;
\r
2057 commentY = CW_USEDEFAULT;
\r
2058 commentW = CW_USEDEFAULT;
\r
2059 commentH = CW_USEDEFAULT;
\r
2060 editTagsX = CW_USEDEFAULT;
\r
2061 editTagsY = CW_USEDEFAULT;
\r
2062 editTagsW = CW_USEDEFAULT;
\r
2063 editTagsH = CW_USEDEFAULT;
\r
2064 icsTextMenuString = ICS_TEXT_MENU_DEFAULT;
\r
2065 icsNames = ICS_NAMES;
\r
2066 firstChessProgramNames = FCP_NAMES;
\r
2067 secondChessProgramNames = SCP_NAMES;
\r
2068 appData.initialMode = "";
\r
2069 appData.variant = "normal";
\r
2070 appData.firstProtocolVersion = PROTOVER;
\r
2071 appData.secondProtocolVersion = PROTOVER;
\r
2072 appData.showButtonBar = TRUE;
\r
2074 /* [AS] New properties (see comments in header file) */
\r
2075 appData.firstScoreIsAbsolute = FALSE;
\r
2076 appData.secondScoreIsAbsolute = FALSE;
\r
2077 appData.saveExtendedInfoInPGN = FALSE;
\r
2078 appData.hideThinkingFromHuman = FALSE;
\r
2079 appData.liteBackTextureFile = "";
\r
2080 appData.liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
2081 appData.darkBackTextureFile = "";
\r
2082 appData.darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
2083 appData.renderPiecesWithFont = "";
\r
2084 appData.fontToPieceTable = "";
\r
2085 appData.fontBackColorWhite = 0;
\r
2086 appData.fontForeColorWhite = 0;
\r
2087 appData.fontBackColorBlack = 0;
\r
2088 appData.fontForeColorBlack = 0;
\r
2089 appData.fontPieceSize = 80;
\r
2090 appData.overrideLineGap = 1;
\r
2091 appData.adjudicateLossThreshold = 0;
\r
2092 appData.delayBeforeQuit = 0;
\r
2093 appData.delayAfterQuit = 0;
\r
2094 appData.nameOfDebugFile = "winboard.debug";
\r
2095 appData.pgnEventHeader = "Computer Chess Game";
\r
2096 appData.defaultFrcPosition = -1;
\r
2097 appData.gameListTags = GLT_DEFAULT_TAGS;
\r
2098 appData.saveOutOfBookInfo = TRUE;
\r
2099 appData.showEvalInMoveHistory = TRUE;
\r
2100 appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );
\r
2101 appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );
\r
2102 appData.highlightMoveWithArrow = FALSE;
\r
2103 appData.highlightArrowColor = ParseColorName( "#FFFF80" );
\r
2104 appData.useStickyWindows = TRUE;
\r
2105 appData.adjudicateDrawMoves = 0;
\r
2106 appData.autoDisplayComment = TRUE;
\r
2107 appData.autoDisplayTags = TRUE;
\r
2108 appData.firstIsUCI = FALSE;
\r
2109 appData.secondIsUCI = FALSE;
\r
2110 appData.firstHasOwnBookUCI = TRUE;
\r
2111 appData.secondHasOwnBookUCI = TRUE;
\r
2112 appData.polyglotDir = "";
\r
2113 appData.usePolyglotBook = FALSE;
\r
2114 appData.polyglotBook = "";
\r
2115 appData.defaultHashSize = 64;
\r
2116 appData.defaultCacheSizeEGTB = 4;
\r
2117 appData.defaultPathEGTB = "c:\\egtb";
\r
2118 appData.firstOptions = "";
\r
2119 appData.secondOptions = "";
\r
2121 InitWindowPlacement( &wpGameList );
\r
2122 InitWindowPlacement( &wpMoveHistory );
\r
2123 InitWindowPlacement( &wpEvalGraph );
\r
2124 InitWindowPlacement( &wpEngineOutput );
\r
2125 InitWindowPlacement( &wpConsole );
\r
2127 /* [HGM] User-selectable board size, adjudication control, miscellaneous */
\r
2128 appData.NrFiles = -1;
\r
2129 appData.NrRanks = -1;
\r
2130 appData.holdingsSize = -1;
\r
2131 appData.testClaims = FALSE;
\r
2132 appData.checkMates = FALSE;
\r
2133 appData.materialDraws= FALSE;
\r
2134 appData.trivialDraws = FALSE;
\r
2135 appData.ruleMoves = 51;
\r
2136 appData.drawRepeats = 6;
\r
2137 appData.matchPause = 10000;
\r
2138 appData.alphaRank = FALSE;
\r
2139 appData.allWhite = FALSE;
\r
2140 appData.upsideDown = FALSE;
\r
2141 appData.serverPause = 15;
\r
2142 appData.serverMovesName = NULL;
\r
2143 appData.suppressLoadMoves = FALSE;
\r
2144 appData.firstTimeOdds = 1;
\r
2145 appData.secondTimeOdds = 1;
\r
2146 appData.firstAccumulateTC = 1; // combine previous and current sessions
\r
2147 appData.secondAccumulateTC = 1;
\r
2148 appData.firstNPS = -1; // [HGM] nps: use wall-clock time
\r
2149 appData.secondNPS = -1;
\r
2150 appData.engineComments = 1;
\r
2151 appData.smpCores = 1; // [HGM] SMP: max nr of cores
\r
2152 appData.egtFormats = "";
\r
2155 appData.zippyTalk = ZIPPY_TALK;
\r
2156 appData.zippyPlay = ZIPPY_PLAY;
\r
2157 appData.zippyLines = ZIPPY_LINES;
\r
2158 appData.zippyPinhead = ZIPPY_PINHEAD;
\r
2159 appData.zippyPassword = ZIPPY_PASSWORD;
\r
2160 appData.zippyPassword2 = ZIPPY_PASSWORD2;
\r
2161 appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;
\r
2162 appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;
\r
2163 appData.zippyUseI = ZIPPY_USE_I;
\r
2164 appData.zippyBughouse = ZIPPY_BUGHOUSE;
\r
2165 appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;
\r
2166 appData.zippyGameEnd = ZIPPY_GAME_END;
\r
2167 appData.zippyGameStart = ZIPPY_GAME_START;
\r
2168 appData.zippyAdjourn = ZIPPY_ADJOURN;
\r
2169 appData.zippyAbort = ZIPPY_ABORT;
\r
2170 appData.zippyVariants = ZIPPY_VARIANTS;
\r
2171 appData.zippyMaxGames = ZIPPY_MAX_GAMES;
\r
2172 appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;
\r
2175 /* Point font array elements to structures and
\r
2176 parse default font names */
\r
2177 for (i=0; i<NUM_FONTS; i++) {
\r
2178 for (j=0; j<NUM_SIZES; j++) {
\r
2179 font[j][i] = &fontRec[j][i];
\r
2180 ParseFontName(font[j][i]->def, &font[j][i]->mfp);
\r
2184 /* Parse default settings file if any */
\r
2185 if (ParseSettingsFile(settingsFileName, buf)) {
\r
2186 settingsFileName = strdup(buf);
\r
2189 /* Parse command line */
\r
2190 ParseArgs(StringGet, &lpCmdLine);
\r
2192 /* [HGM] make sure board size is acceptable */
\r
2193 if(appData.NrFiles > BOARD_SIZE ||
\r
2194 appData.NrRanks > BOARD_SIZE )
\r
2195 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
2197 /* [HGM] After parsing the options from the .ini file, and overruling them
\r
2198 * with options from the command line, we now make an even higher priority
\r
2199 * overrule by WB options attached to the engine command line. This so that
\r
2200 * tournament managers can use WB options (such as /timeOdds) that follow
\r
2203 if(appData.firstChessProgram != NULL) {
\r
2204 char *p = StrStr(appData.firstChessProgram, "WBopt");
\r
2205 static char *f = "first";
\r
2206 char buf[MSG_SIZ], *q = buf;
\r
2207 if(p != NULL) { // engine command line contains WinBoard options
\r
2208 sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"
\r
2209 ParseArgs(StringGet, &q);
\r
2210 p[-1] = 0; // cut them offengine command line
\r
2213 // now do same for second chess program
\r
2214 if(appData.secondChessProgram != NULL) {
\r
2215 char *p = StrStr(appData.secondChessProgram, "WBopt");
\r
2216 static char *s = "second";
\r
2217 char buf[MSG_SIZ], *q = buf;
\r
2218 if(p != NULL) { // engine command line contains WinBoard options
\r
2219 sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"
\r
2220 ParseArgs(StringGet, &q);
\r
2221 p[-1] = 0; // cut them offengine command line
\r
2226 /* Propagate options that affect others */
\r
2227 if (appData.matchMode || appData.matchGames) chessProgram = TRUE;
\r
2228 if (appData.icsActive || appData.noChessProgram) {
\r
2229 chessProgram = FALSE; /* not local chess program mode */
\r
2232 /* Open startup dialog if needed */
\r
2233 if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||
\r
2234 (appData.icsActive && *appData.icsHost == NULLCHAR) ||
\r
2235 (chessProgram && (*appData.firstChessProgram == NULLCHAR ||
\r
2236 *appData.secondChessProgram == NULLCHAR))) {
\r
2239 lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);
\r
2240 DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);
\r
2241 FreeProcInstance(lpProc);
\r
2244 /* Make sure save files land in the right (?) directory */
\r
2245 if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {
\r
2246 appData.saveGameFile = strdup(buf);
\r
2248 if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {
\r
2249 appData.savePositionFile = strdup(buf);
\r
2252 /* Finish initialization for fonts and sounds */
\r
2253 for (i=0; i<NUM_FONTS; i++) {
\r
2254 for (j=0; j<NUM_SIZES; j++) {
\r
2255 CreateFontInMF(font[j][i]);
\r
2258 /* xboard, and older WinBoards, controlled the move sound with the
\r
2259 appData.ringBellAfterMoves option. In the current WinBoard, we
\r
2260 always turn the option on (so that the backend will call us),
\r
2261 then let the user turn the sound off by setting it to silence if
\r
2262 desired. To accommodate old winboard.ini files saved by old
\r
2263 versions of WinBoard, we also turn off the sound if the option
\r
2264 was initially set to false. */
\r
2265 if (!appData.ringBellAfterMoves) {
\r
2266 sounds[(int)SoundMove].name = strdup("");
\r
2267 appData.ringBellAfterMoves = TRUE;
\r
2269 GetCurrentDirectory(MSG_SIZ, currDir);
\r
2270 SetCurrentDirectory(installDir);
\r
2272 SetCurrentDirectory(currDir);
\r
2274 p = icsTextMenuString;
\r
2275 if (p[0] == '@') {
\r
2276 FILE* f = fopen(p + 1, "r");
\r
2278 DisplayFatalError(p + 1, errno, 2);
\r
2281 i = fread(buf, 1, sizeof(buf)-1, f);
\r
2283 buf[i] = NULLCHAR;
\r
2286 ParseIcsTextMenu(strdup(p));
\r
2293 HMENU hmenu = GetMenu(hwndMain);
\r
2295 (void) EnableMenuItem(hmenu, IDM_CommPort,
\r
2296 MF_BYCOMMAND|((appData.icsActive &&
\r
2297 *appData.icsCommPort != NULLCHAR) ?
\r
2298 MF_ENABLED : MF_GRAYED));
\r
2299 (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,
\r
2300 MF_BYCOMMAND|(saveSettingsOnExit ?
\r
2301 MF_CHECKED : MF_UNCHECKED));
\r
2306 SaveSettings(char* name)
\r
2309 ArgDescriptor *ad;
\r
2310 WINDOWPLACEMENT wp;
\r
2311 char dir[MSG_SIZ];
\r
2313 if (!hwndMain) return;
\r
2315 GetCurrentDirectory(MSG_SIZ, dir);
\r
2316 SetCurrentDirectory(installDir);
\r
2317 f = fopen(name, "w");
\r
2318 SetCurrentDirectory(dir);
\r
2320 DisplayError(name, errno);
\r
2323 fprintf(f, ";\n");
\r
2324 fprintf(f, "; %s Save Settings file\n", PACKAGE_STRING);
\r
2325 fprintf(f, ";\n");
\r
2326 fprintf(f, "; You can edit the values of options that are already set in this file,\n");
\r
2327 fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");
\r
2328 fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");
\r
2329 fprintf(f, ";\n");
\r
2331 wp.length = sizeof(WINDOWPLACEMENT);
\r
2332 GetWindowPlacement(hwndMain, &wp);
\r
2333 boardX = wp.rcNormalPosition.left;
\r
2334 boardY = wp.rcNormalPosition.top;
\r
2336 if (hwndConsole) {
\r
2337 GetWindowPlacement(hwndConsole, &wp);
\r
2338 wpConsole.x = wp.rcNormalPosition.left;
\r
2339 wpConsole.y = wp.rcNormalPosition.top;
\r
2340 wpConsole.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2341 wpConsole.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2344 if (analysisDialog) {
\r
2345 GetWindowPlacement(analysisDialog, &wp);
\r
2346 analysisX = wp.rcNormalPosition.left;
\r
2347 analysisY = wp.rcNormalPosition.top;
\r
2348 analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2349 analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2352 if (commentDialog) {
\r
2353 GetWindowPlacement(commentDialog, &wp);
\r
2354 commentX = wp.rcNormalPosition.left;
\r
2355 commentY = wp.rcNormalPosition.top;
\r
2356 commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2357 commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2360 if (editTagsDialog) {
\r
2361 GetWindowPlacement(editTagsDialog, &wp);
\r
2362 editTagsX = wp.rcNormalPosition.left;
\r
2363 editTagsY = wp.rcNormalPosition.top;
\r
2364 editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2365 editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2368 if (gameListDialog) {
\r
2369 GetWindowPlacement(gameListDialog, &wp);
\r
2370 wpGameList.x = wp.rcNormalPosition.left;
\r
2371 wpGameList.y = wp.rcNormalPosition.top;
\r
2372 wpGameList.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2373 wpGameList.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2376 /* [AS] Move history */
\r
2377 wpMoveHistory.visible = MoveHistoryIsUp();
\r
2379 if( moveHistoryDialog ) {
\r
2380 GetWindowPlacement(moveHistoryDialog, &wp);
\r
2381 wpMoveHistory.x = wp.rcNormalPosition.left;
\r
2382 wpMoveHistory.y = wp.rcNormalPosition.top;
\r
2383 wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2384 wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2387 /* [AS] Eval graph */
\r
2388 wpEvalGraph.visible = EvalGraphIsUp();
\r
2390 if( evalGraphDialog ) {
\r
2391 GetWindowPlacement(evalGraphDialog, &wp);
\r
2392 wpEvalGraph.x = wp.rcNormalPosition.left;
\r
2393 wpEvalGraph.y = wp.rcNormalPosition.top;
\r
2394 wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2395 wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2398 /* [AS] Engine output */
\r
2399 wpEngineOutput.visible = EngineOutputIsUp();
\r
2401 if( engineOutputDialog ) {
\r
2402 GetWindowPlacement(engineOutputDialog, &wp);
\r
2403 wpEngineOutput.x = wp.rcNormalPosition.left;
\r
2404 wpEngineOutput.y = wp.rcNormalPosition.top;
\r
2405 wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2406 wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2409 for (ad = argDescriptors; ad->argName != NULL; ad++) {
\r
2410 if (!ad->save) continue;
\r
2411 switch (ad->argType) {
\r
2414 char *p = *(char **)ad->argLoc;
\r
2415 if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {
\r
2416 /* Quote multiline values or \-containing values
\r
2417 with { } if possible */
\r
2418 fprintf(f, "/%s={%s}\n", ad->argName, p);
\r
2420 /* Else quote with " " */
\r
2421 fprintf(f, "/%s=\"", ad->argName);
\r
2423 if (*p == '\n') fprintf(f, "\n");
\r
2424 else if (*p == '\r') fprintf(f, "\\r");
\r
2425 else if (*p == '\t') fprintf(f, "\\t");
\r
2426 else if (*p == '\b') fprintf(f, "\\b");
\r
2427 else if (*p == '\f') fprintf(f, "\\f");
\r
2428 else if (*p < ' ') fprintf(f, "\\%03o", *p);
\r
2429 else if (*p == '\"') fprintf(f, "\\\"");
\r
2430 else if (*p == '\\') fprintf(f, "\\\\");
\r
2434 fprintf(f, "\"\n");
\r
2440 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);
\r
2443 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardX); // [HGM] placement: stor relative value
\r
2446 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardY);
\r
2449 fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);
\r
2452 fprintf(f, "/%s=%s\n", ad->argName,
\r
2453 (*(Boolean *)ad->argLoc) ? "true" : "false");
\r
2456 if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2459 if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2463 COLORREF color = *(COLORREF *)ad->argLoc;
\r
2464 fprintf(f, "/%s=#%02lx%02lx%02lx\n", ad->argName,
\r
2465 color&0xff, (color>>8)&0xff, (color>>16)&0xff);
\r
2470 MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];
\r
2471 fprintf(f, "/%s=\"%s%s%s%s%s#%02lx%02lx%02lx\"\n", ad->argName,
\r
2472 (ta->effects & CFE_BOLD) ? "b" : "",
\r
2473 (ta->effects & CFE_ITALIC) ? "i" : "",
\r
2474 (ta->effects & CFE_UNDERLINE) ? "u" : "",
\r
2475 (ta->effects & CFE_STRIKEOUT) ? "s" : "",
\r
2476 (ta->effects) ? " " : "",
\r
2477 ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);
\r
2481 if (strchr(*(char **)ad->argLoc, '\"')) {
\r
2482 fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);
\r
2484 fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);
\r
2487 case ArgBoardSize:
\r
2488 fprintf(f, "/%s=%s\n", ad->argName,
\r
2489 sizeInfo[*(BoardSize *)ad->argLoc].name);
\r
2494 for (bs=0; bs<NUM_SIZES; bs++) {
\r
2495 MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;
\r
2496 fprintf(f, "/size=%s ", sizeInfo[bs].name);
\r
2497 fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n",
\r
2498 ad->argName, mfp->faceName, mfp->pointSize,
\r
2499 mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",
\r
2500 mfp->bold ? "b" : "",
\r
2501 mfp->italic ? "i" : "",
\r
2502 mfp->underline ? "u" : "",
\r
2503 mfp->strikeout ? "s" : "");
\r
2507 case ArgCommSettings:
\r
2508 PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);
\r
2510 case ArgSettingsFilename: ;
\r
2518 /*---------------------------------------------------------------------------*\
\r
2520 * GDI board drawing routines
\r
2522 \*---------------------------------------------------------------------------*/
\r
2524 /* [AS] Draw square using background texture */
\r
2525 static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )
\r
2530 return; /* Should never happen! */
\r
2533 SetGraphicsMode( dst, GM_ADVANCED );
\r
2540 /* X reflection */
\r
2545 x.eDx = (FLOAT) dw + dx - 1;
\r
2548 SetWorldTransform( dst, &x );
\r
2551 /* Y reflection */
\r
2557 x.eDy = (FLOAT) dh + dy - 1;
\r
2559 SetWorldTransform( dst, &x );
\r
2567 x.eDx = (FLOAT) dx;
\r
2568 x.eDy = (FLOAT) dy;
\r
2571 SetWorldTransform( dst, &x );
\r
2575 BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );
\r
2583 SetWorldTransform( dst, &x );
\r
2585 ModifyWorldTransform( dst, 0, MWT_IDENTITY );
\r
2588 /* [AS] [HGM] Make room for more piece types, so all pieces can be different */
\r
2590 PM_WP = (int) WhitePawn,
\r
2591 PM_WN = (int) WhiteKnight,
\r
2592 PM_WB = (int) WhiteBishop,
\r
2593 PM_WR = (int) WhiteRook,
\r
2594 PM_WQ = (int) WhiteQueen,
\r
2595 PM_WF = (int) WhiteFerz,
\r
2596 PM_WW = (int) WhiteWazir,
\r
2597 PM_WE = (int) WhiteAlfil,
\r
2598 PM_WM = (int) WhiteMan,
\r
2599 PM_WO = (int) WhiteCannon,
\r
2600 PM_WU = (int) WhiteUnicorn,
\r
2601 PM_WH = (int) WhiteNightrider,
\r
2602 PM_WA = (int) WhiteAngel,
\r
2603 PM_WC = (int) WhiteMarshall,
\r
2604 PM_WAB = (int) WhiteCardinal,
\r
2605 PM_WD = (int) WhiteDragon,
\r
2606 PM_WL = (int) WhiteLance,
\r
2607 PM_WS = (int) WhiteCobra,
\r
2608 PM_WV = (int) WhiteFalcon,
\r
2609 PM_WSG = (int) WhiteSilver,
\r
2610 PM_WG = (int) WhiteGrasshopper,
\r
2611 PM_WK = (int) WhiteKing,
\r
2612 PM_BP = (int) BlackPawn,
\r
2613 PM_BN = (int) BlackKnight,
\r
2614 PM_BB = (int) BlackBishop,
\r
2615 PM_BR = (int) BlackRook,
\r
2616 PM_BQ = (int) BlackQueen,
\r
2617 PM_BF = (int) BlackFerz,
\r
2618 PM_BW = (int) BlackWazir,
\r
2619 PM_BE = (int) BlackAlfil,
\r
2620 PM_BM = (int) BlackMan,
\r
2621 PM_BO = (int) BlackCannon,
\r
2622 PM_BU = (int) BlackUnicorn,
\r
2623 PM_BH = (int) BlackNightrider,
\r
2624 PM_BA = (int) BlackAngel,
\r
2625 PM_BC = (int) BlackMarshall,
\r
2626 PM_BG = (int) BlackGrasshopper,
\r
2627 PM_BAB = (int) BlackCardinal,
\r
2628 PM_BD = (int) BlackDragon,
\r
2629 PM_BL = (int) BlackLance,
\r
2630 PM_BS = (int) BlackCobra,
\r
2631 PM_BV = (int) BlackFalcon,
\r
2632 PM_BSG = (int) BlackSilver,
\r
2633 PM_BK = (int) BlackKing
\r
2636 static HFONT hPieceFont = NULL;
\r
2637 static HBITMAP hPieceMask[(int) EmptySquare];
\r
2638 static HBITMAP hPieceFace[(int) EmptySquare];
\r
2639 static int fontBitmapSquareSize = 0;
\r
2640 static char pieceToFontChar[(int) EmptySquare] =
\r
2641 { 'p', 'n', 'b', 'r', 'q',
\r
2642 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',
\r
2643 'k', 'o', 'm', 'v', 't', 'w',
\r
2644 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',
\r
2647 extern BOOL SetCharTable( char *table, const char * map );
\r
2648 /* [HGM] moved to backend.c */
\r
2650 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )
\r
2653 BYTE r1 = GetRValue( color );
\r
2654 BYTE g1 = GetGValue( color );
\r
2655 BYTE b1 = GetBValue( color );
\r
2661 /* Create a uniform background first */
\r
2662 hbrush = CreateSolidBrush( color );
\r
2663 SetRect( &rc, 0, 0, squareSize, squareSize );
\r
2664 FillRect( hdc, &rc, hbrush );
\r
2665 DeleteObject( hbrush );
\r
2668 /* Vertical gradient, good for pawn, knight and rook, less for queen and king */
\r
2669 int steps = squareSize / 2;
\r
2672 for( i=0; i<steps; i++ ) {
\r
2673 BYTE r = r1 - (r1-r2) * i / steps;
\r
2674 BYTE g = g1 - (g1-g2) * i / steps;
\r
2675 BYTE b = b1 - (b1-b2) * i / steps;
\r
2677 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2678 SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );
\r
2679 FillRect( hdc, &rc, hbrush );
\r
2680 DeleteObject(hbrush);
\r
2683 else if( mode == 2 ) {
\r
2684 /* Diagonal gradient, good more or less for every piece */
\r
2685 POINT triangle[3];
\r
2686 HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );
\r
2687 HBRUSH hbrush_old;
\r
2688 int steps = squareSize;
\r
2691 triangle[0].x = squareSize - steps;
\r
2692 triangle[0].y = squareSize;
\r
2693 triangle[1].x = squareSize;
\r
2694 triangle[1].y = squareSize;
\r
2695 triangle[2].x = squareSize;
\r
2696 triangle[2].y = squareSize - steps;
\r
2698 for( i=0; i<steps; i++ ) {
\r
2699 BYTE r = r1 - (r1-r2) * i / steps;
\r
2700 BYTE g = g1 - (g1-g2) * i / steps;
\r
2701 BYTE b = b1 - (b1-b2) * i / steps;
\r
2703 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2704 hbrush_old = SelectObject( hdc, hbrush );
\r
2705 Polygon( hdc, triangle, 3 );
\r
2706 SelectObject( hdc, hbrush_old );
\r
2707 DeleteObject(hbrush);
\r
2712 SelectObject( hdc, hpen );
\r
2717 [AS] The method I use to create the bitmaps it a bit tricky, but it
\r
2718 seems to work ok. The main problem here is to find the "inside" of a chess
\r
2719 piece: follow the steps as explained below.
\r
2721 static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
\r
2725 COLORREF chroma = RGB(0xFF,0x00,0xFF);
\r
2729 int backColor = whitePieceColor;
\r
2730 int foreColor = blackPieceColor;
\r
2732 if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {
\r
2733 backColor = appData.fontBackColorWhite;
\r
2734 foreColor = appData.fontForeColorWhite;
\r
2736 else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {
\r
2737 backColor = appData.fontBackColorBlack;
\r
2738 foreColor = appData.fontForeColorBlack;
\r
2742 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2744 hbm_old = SelectObject( hdc, hbm );
\r
2748 rc.right = squareSize;
\r
2749 rc.bottom = squareSize;
\r
2751 /* Step 1: background is now black */
\r
2752 FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );
\r
2754 GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );
\r
2756 pt.x = (squareSize - sz.cx) / 2;
\r
2757 pt.y = (squareSize - sz.cy) / 2;
\r
2759 SetBkMode( hdc, TRANSPARENT );
\r
2760 SetTextColor( hdc, chroma );
\r
2761 /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */
\r
2762 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2764 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
\r
2765 /* Step 3: the area outside the piece is filled with white */
\r
2766 // FloodFill( hdc, 0, 0, chroma );
\r
2767 ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );
\r
2768 ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big
\r
2769 ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );
\r
2770 ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );
\r
2771 SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
\r
2773 Step 4: this is the tricky part, the area inside the piece is filled with black,
\r
2774 but if the start point is not inside the piece we're lost!
\r
2775 There should be a better way to do this... if we could create a region or path
\r
2776 from the fill operation we would be fine for example.
\r
2778 // FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );
\r
2779 ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );
\r
2781 { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */
\r
2782 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2783 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2785 SelectObject( dc2, bm2 );
\r
2786 BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy
\r
2787 BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2788 BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2789 BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2790 BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2793 DeleteObject( bm2 );
\r
2796 SetTextColor( hdc, 0 );
\r
2798 Step 5: some fonts have "disconnected" areas that are skipped by the fill:
\r
2799 draw the piece again in black for safety.
\r
2801 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2803 SelectObject( hdc, hbm_old );
\r
2805 if( hPieceMask[index] != NULL ) {
\r
2806 DeleteObject( hPieceMask[index] );
\r
2809 hPieceMask[index] = hbm;
\r
2812 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2814 SelectObject( hdc, hbm );
\r
2817 HDC dc1 = CreateCompatibleDC( hdc_window );
\r
2818 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2819 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2821 SelectObject( dc1, hPieceMask[index] );
\r
2822 SelectObject( dc2, bm2 );
\r
2823 FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );
\r
2824 BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );
\r
2827 Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves
\r
2828 the piece background and deletes (makes transparent) the rest.
\r
2829 Thanks to that mask, we are free to paint the background with the greates
\r
2830 freedom, as we'll be able to mask off the unwanted parts when finished.
\r
2831 We use this, to make gradients and give the pieces a "roundish" look.
\r
2833 SetPieceBackground( hdc, backColor, 2 );
\r
2834 BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );
\r
2838 DeleteObject( bm2 );
\r
2841 SetTextColor( hdc, foreColor );
\r
2842 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2844 SelectObject( hdc, hbm_old );
\r
2846 if( hPieceFace[index] != NULL ) {
\r
2847 DeleteObject( hPieceFace[index] );
\r
2850 hPieceFace[index] = hbm;
\r
2853 static int TranslatePieceToFontPiece( int piece )
\r
2883 case BlackMarshall:
\r
2887 case BlackNightrider:
\r
2893 case BlackUnicorn:
\r
2897 case BlackGrasshopper:
\r
2909 case BlackCardinal:
\r
2916 case WhiteMarshall:
\r
2920 case WhiteNightrider:
\r
2926 case WhiteUnicorn:
\r
2930 case WhiteGrasshopper:
\r
2942 case WhiteCardinal:
\r
2951 void CreatePiecesFromFont()
\r
2954 HDC hdc_window = NULL;
\r
2960 if( fontBitmapSquareSize < 0 ) {
\r
2961 /* Something went seriously wrong in the past: do not try to recreate fonts! */
\r
2965 if( appData.renderPiecesWithFont == NULL || appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {
\r
2966 fontBitmapSquareSize = -1;
\r
2970 if( fontBitmapSquareSize != squareSize ) {
\r
2971 hdc_window = GetDC( hwndMain );
\r
2972 hdc = CreateCompatibleDC( hdc_window );
\r
2974 if( hPieceFont != NULL ) {
\r
2975 DeleteObject( hPieceFont );
\r
2978 for( i=0; i<=(int)BlackKing; i++ ) {
\r
2979 hPieceMask[i] = NULL;
\r
2980 hPieceFace[i] = NULL;
\r
2986 if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {
\r
2987 fontHeight = appData.fontPieceSize;
\r
2990 fontHeight = (fontHeight * squareSize) / 100;
\r
2992 lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
\r
2994 lf.lfEscapement = 0;
\r
2995 lf.lfOrientation = 0;
\r
2996 lf.lfWeight = FW_NORMAL;
\r
2998 lf.lfUnderline = 0;
\r
2999 lf.lfStrikeOut = 0;
\r
3000 lf.lfCharSet = DEFAULT_CHARSET;
\r
3001 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
3002 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
3003 lf.lfQuality = PROOF_QUALITY;
\r
3004 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
\r
3005 strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );
\r
3006 lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';
\r
3008 hPieceFont = CreateFontIndirect( &lf );
\r
3010 if( hPieceFont == NULL ) {
\r
3011 fontBitmapSquareSize = -2;
\r
3014 /* Setup font-to-piece character table */
\r
3015 if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {
\r
3016 /* No (or wrong) global settings, try to detect the font */
\r
3017 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {
\r
3019 SetCharTable(pieceToFontChar, "phbrqkojntwl");
\r
3021 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {
\r
3022 /* DiagramTT* family */
\r
3023 SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");
\r
3025 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {
\r
3026 /* Fairy symbols */
\r
3027 SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
\r
3029 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {
\r
3030 /* Good Companion (Some characters get warped as literal :-( */
\r
3031 char s[] = "1cmWG0ñueOS¯®oYI23wgQU";
\r
3032 s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;
\r
3033 SetCharTable(pieceToFontChar, s);
\r
3036 /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */
\r
3037 SetCharTable(pieceToFontChar, "pnbrqkomvtwl");
\r
3041 /* Create bitmaps */
\r
3042 hfont_old = SelectObject( hdc, hPieceFont );
\r
3044 CreatePieceMaskFromFont( hdc_window, hdc, PM_WP );
\r
3045 CreatePieceMaskFromFont( hdc_window, hdc, PM_WN );
\r
3046 CreatePieceMaskFromFont( hdc_window, hdc, PM_WB );
\r
3047 CreatePieceMaskFromFont( hdc_window, hdc, PM_WR );
\r
3048 CreatePieceMaskFromFont( hdc_window, hdc, PM_WQ );
\r
3049 CreatePieceMaskFromFont( hdc_window, hdc, PM_WK );
\r
3050 CreatePieceMaskFromFont( hdc_window, hdc, PM_BP );
\r
3051 CreatePieceMaskFromFont( hdc_window, hdc, PM_BN );
\r
3052 CreatePieceMaskFromFont( hdc_window, hdc, PM_BB );
\r
3053 CreatePieceMaskFromFont( hdc_window, hdc, PM_BR );
\r
3054 CreatePieceMaskFromFont( hdc_window, hdc, PM_BQ );
\r
3055 CreatePieceMaskFromFont( hdc_window, hdc, PM_BK );
\r
3057 CreatePieceMaskFromFont( hdc_window, hdc, PM_WA );
\r
3058 CreatePieceMaskFromFont( hdc_window, hdc, PM_WC );
\r
3059 CreatePieceMaskFromFont( hdc_window, hdc, PM_WF );
\r
3060 CreatePieceMaskFromFont( hdc_window, hdc, PM_WH );
\r
3061 CreatePieceMaskFromFont( hdc_window, hdc, PM_WE );
\r
3062 CreatePieceMaskFromFont( hdc_window, hdc, PM_WW );
\r
3063 CreatePieceMaskFromFont( hdc_window, hdc, PM_WU );
\r
3064 CreatePieceMaskFromFont( hdc_window, hdc, PM_WO );
\r
3065 CreatePieceMaskFromFont( hdc_window, hdc, PM_WG );
\r
3066 CreatePieceMaskFromFont( hdc_window, hdc, PM_WM );
\r
3067 CreatePieceMaskFromFont( hdc_window, hdc, PM_WSG );
\r
3068 CreatePieceMaskFromFont( hdc_window, hdc, PM_WV );
\r
3069 CreatePieceMaskFromFont( hdc_window, hdc, PM_WAB );
\r
3070 CreatePieceMaskFromFont( hdc_window, hdc, PM_WD );
\r
3071 CreatePieceMaskFromFont( hdc_window, hdc, PM_WL );
\r
3072 CreatePieceMaskFromFont( hdc_window, hdc, PM_WS );
\r
3073 CreatePieceMaskFromFont( hdc_window, hdc, PM_BA );
\r
3074 CreatePieceMaskFromFont( hdc_window, hdc, PM_BC );
\r
3075 CreatePieceMaskFromFont( hdc_window, hdc, PM_BF );
\r
3076 CreatePieceMaskFromFont( hdc_window, hdc, PM_BH );
\r
3077 CreatePieceMaskFromFont( hdc_window, hdc, PM_BE );
\r
3078 CreatePieceMaskFromFont( hdc_window, hdc, PM_BW );
\r
3079 CreatePieceMaskFromFont( hdc_window, hdc, PM_BU );
\r
3080 CreatePieceMaskFromFont( hdc_window, hdc, PM_BO );
\r
3081 CreatePieceMaskFromFont( hdc_window, hdc, PM_BG );
\r
3082 CreatePieceMaskFromFont( hdc_window, hdc, PM_BM );
\r
3083 CreatePieceMaskFromFont( hdc_window, hdc, PM_BSG );
\r
3084 CreatePieceMaskFromFont( hdc_window, hdc, PM_BV );
\r
3085 CreatePieceMaskFromFont( hdc_window, hdc, PM_BAB );
\r
3086 CreatePieceMaskFromFont( hdc_window, hdc, PM_BD );
\r
3087 CreatePieceMaskFromFont( hdc_window, hdc, PM_BL );
\r
3088 CreatePieceMaskFromFont( hdc_window, hdc, PM_BS );
\r
3090 for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */
\r
3091 if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */
\r
3092 CreatePieceMaskFromFont( hdc_window, hdc, i );
\r
3094 SelectObject( hdc, hfont_old );
\r
3096 fontBitmapSquareSize = squareSize;
\r
3100 if( hdc != NULL ) {
\r
3104 if( hdc_window != NULL ) {
\r
3105 ReleaseDC( hwndMain, hdc_window );
\r
3110 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)
\r
3114 sprintf(name, "%s%d%s", piece, squareSize, suffix);
\r
3115 if (gameInfo.event &&
\r
3116 strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&
\r
3117 strcmp(name, "k80s") == 0) {
\r
3118 strcpy(name, "tim");
\r
3120 return LoadBitmap(hinst, name);
\r
3124 /* Insert a color into the program's logical palette
\r
3125 structure. This code assumes the given color is
\r
3126 the result of the RGB or PALETTERGB macro, and it
\r
3127 knows how those macros work (which is documented).
\r
3130 InsertInPalette(COLORREF color)
\r
3132 LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);
\r
3134 if (pLogPal->palNumEntries++ >= PALETTESIZE) {
\r
3135 DisplayFatalError("Too many colors", 0, 1);
\r
3136 pLogPal->palNumEntries--;
\r
3140 pe->peFlags = (char) 0;
\r
3141 pe->peRed = (char) (0xFF & color);
\r
3142 pe->peGreen = (char) (0xFF & (color >> 8));
\r
3143 pe->peBlue = (char) (0xFF & (color >> 16));
\r
3149 InitDrawingColors()
\r
3151 if (pLogPal == NULL) {
\r
3152 /* Allocate enough memory for a logical palette with
\r
3153 * PALETTESIZE entries and set the size and version fields
\r
3154 * of the logical palette structure.
\r
3156 pLogPal = (NPLOGPALETTE)
\r
3157 LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +
\r
3158 (sizeof(PALETTEENTRY) * (PALETTESIZE))));
\r
3159 pLogPal->palVersion = 0x300;
\r
3161 pLogPal->palNumEntries = 0;
\r
3163 InsertInPalette(lightSquareColor);
\r
3164 InsertInPalette(darkSquareColor);
\r
3165 InsertInPalette(whitePieceColor);
\r
3166 InsertInPalette(blackPieceColor);
\r
3167 InsertInPalette(highlightSquareColor);
\r
3168 InsertInPalette(premoveHighlightColor);
\r
3170 /* create a logical color palette according the information
\r
3171 * in the LOGPALETTE structure.
\r
3173 hPal = CreatePalette((LPLOGPALETTE) pLogPal);
\r
3175 lightSquareBrush = CreateSolidBrush(lightSquareColor);
\r
3176 blackSquareBrush = CreateSolidBrush(blackPieceColor);
\r
3177 darkSquareBrush = CreateSolidBrush(darkSquareColor);
\r
3178 whitePieceBrush = CreateSolidBrush(whitePieceColor);
\r
3179 blackPieceBrush = CreateSolidBrush(blackPieceColor);
\r
3180 iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
\r
3181 explodeBrush = CreateSolidBrush(highlightSquareColor); // [HGM] atomic
\r
3182 /* [AS] Force rendering of the font-based pieces */
\r
3183 if( fontBitmapSquareSize > 0 ) {
\r