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 #define oldDialog (_winmajor < 4)
\r
231 char *defaultTextAttribs[] =
\r
233 COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,
\r
234 COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,
\r
244 int cliWidth, cliHeight;
\r
247 SizeInfo sizeInfo[] =
\r
249 { "tiny", 21, 0, 1, 1, 0, 0 },
\r
250 { "teeny", 25, 1, 1, 1, 0, 0 },
\r
251 { "dinky", 29, 1, 1, 1, 0, 0 },
\r
252 { "petite", 33, 1, 1, 1, 0, 0 },
\r
253 { "slim", 37, 2, 1, 0, 0, 0 },
\r
254 { "small", 40, 2, 1, 0, 0, 0 },
\r
255 { "mediocre", 45, 2, 1, 0, 0, 0 },
\r
256 { "middling", 49, 2, 0, 0, 0, 0 },
\r
257 { "average", 54, 2, 0, 0, 0, 0 },
\r
258 { "moderate", 58, 3, 0, 0, 0, 0 },
\r
259 { "medium", 64, 3, 0, 0, 0, 0 },
\r
260 { "bulky", 72, 3, 0, 0, 0, 0 },
\r
261 { "large", 80, 3, 0, 0, 0, 0 },
\r
262 { "big", 87, 3, 0, 0, 0, 0 },
\r
263 { "huge", 95, 3, 0, 0, 0, 0 },
\r
264 { "giant", 108, 3, 0, 0, 0, 0 },
\r
265 { "colossal", 116, 4, 0, 0, 0, 0 },
\r
266 { "titanic", 129, 4, 0, 0, 0, 0 },
\r
267 { NULL, 0, 0, 0, 0, 0, 0 }
\r
270 #define MF(x) {x, {{0,}, 0. }, {0, }, 0}
\r
271 MyFont fontRec[NUM_SIZES][NUM_FONTS] =
\r
273 { MF(CLOCK_FONT_TINY), MF(MESSAGE_FONT_TINY), MF(COORD_FONT_TINY), MF(CONSOLE_FONT_TINY), MF(COMMENT_FONT_TINY), MF(EDITTAGS_FONT_TINY), MF(MOVEHISTORY_FONT_ALL) },
\r
274 { MF(CLOCK_FONT_TEENY), MF(MESSAGE_FONT_TEENY), MF(COORD_FONT_TEENY), MF(CONSOLE_FONT_TEENY), MF(COMMENT_FONT_TEENY), MF(EDITTAGS_FONT_TEENY), MF(MOVEHISTORY_FONT_ALL) },
\r
275 { MF(CLOCK_FONT_DINKY), MF(MESSAGE_FONT_DINKY), MF(COORD_FONT_DINKY), MF(CONSOLE_FONT_DINKY), MF(COMMENT_FONT_DINKY), MF(EDITTAGS_FONT_DINKY), MF(MOVEHISTORY_FONT_ALL) },
\r
276 { MF(CLOCK_FONT_PETITE), MF(MESSAGE_FONT_PETITE), MF(COORD_FONT_PETITE), MF(CONSOLE_FONT_PETITE), MF(COMMENT_FONT_PETITE), MF(EDITTAGS_FONT_PETITE), MF(MOVEHISTORY_FONT_ALL) },
\r
277 { MF(CLOCK_FONT_SLIM), MF(MESSAGE_FONT_SLIM), MF(COORD_FONT_SLIM), MF(CONSOLE_FONT_SLIM), MF(COMMENT_FONT_SLIM), MF(EDITTAGS_FONT_SLIM), MF(MOVEHISTORY_FONT_ALL) },
\r
278 { MF(CLOCK_FONT_SMALL), MF(MESSAGE_FONT_SMALL), MF(COORD_FONT_SMALL), MF(CONSOLE_FONT_SMALL), MF(COMMENT_FONT_SMALL), MF(EDITTAGS_FONT_SMALL), MF(MOVEHISTORY_FONT_ALL) },
\r
279 { MF(CLOCK_FONT_MEDIOCRE), MF(MESSAGE_FONT_MEDIOCRE), MF(COORD_FONT_MEDIOCRE), MF(CONSOLE_FONT_MEDIOCRE), MF(COMMENT_FONT_MEDIOCRE), MF(EDITTAGS_FONT_MEDIOCRE), MF(MOVEHISTORY_FONT_ALL) },
\r
280 { MF(CLOCK_FONT_MIDDLING), MF(MESSAGE_FONT_MIDDLING), MF(COORD_FONT_MIDDLING), MF(CONSOLE_FONT_MIDDLING), MF(COMMENT_FONT_MIDDLING), MF(EDITTAGS_FONT_MIDDLING), MF(MOVEHISTORY_FONT_ALL) },
\r
281 { MF(CLOCK_FONT_AVERAGE), MF(MESSAGE_FONT_AVERAGE), MF(COORD_FONT_AVERAGE), MF(CONSOLE_FONT_AVERAGE), MF(COMMENT_FONT_AVERAGE), MF(EDITTAGS_FONT_AVERAGE), MF(MOVEHISTORY_FONT_ALL) },
\r
282 { MF(CLOCK_FONT_MODERATE), MF(MESSAGE_FONT_MODERATE), MF(COORD_FONT_MODERATE), MF(CONSOLE_FONT_MODERATE), MF(COMMENT_FONT_MODERATE), MF(EDITTAGS_FONT_MODERATE), MF(MOVEHISTORY_FONT_ALL) },
\r
283 { MF(CLOCK_FONT_MEDIUM), MF(MESSAGE_FONT_MEDIUM), MF(COORD_FONT_MEDIUM), MF(CONSOLE_FONT_MEDIUM), MF(COMMENT_FONT_MEDIUM), MF(EDITTAGS_FONT_MEDIUM), MF(MOVEHISTORY_FONT_ALL) },
\r
284 { MF(CLOCK_FONT_BULKY), MF(MESSAGE_FONT_BULKY), MF(COORD_FONT_BULKY), MF(CONSOLE_FONT_BULKY), MF(COMMENT_FONT_BULKY), MF(EDITTAGS_FONT_BULKY), MF(MOVEHISTORY_FONT_ALL) },
\r
285 { MF(CLOCK_FONT_LARGE), MF(MESSAGE_FONT_LARGE), MF(COORD_FONT_LARGE), MF(CONSOLE_FONT_LARGE), MF(COMMENT_FONT_LARGE), MF(EDITTAGS_FONT_LARGE), MF(MOVEHISTORY_FONT_ALL) },
\r
286 { MF(CLOCK_FONT_BIG), MF(MESSAGE_FONT_BIG), MF(COORD_FONT_BIG), MF(CONSOLE_FONT_BIG), MF(COMMENT_FONT_BIG), MF(EDITTAGS_FONT_BIG), MF(MOVEHISTORY_FONT_ALL) },
\r
287 { MF(CLOCK_FONT_HUGE), MF(MESSAGE_FONT_HUGE), MF(COORD_FONT_HUGE), MF(CONSOLE_FONT_HUGE), MF(COMMENT_FONT_HUGE), MF(EDITTAGS_FONT_HUGE), MF(MOVEHISTORY_FONT_ALL) },
\r
288 { MF(CLOCK_FONT_GIANT), MF(MESSAGE_FONT_GIANT), MF(COORD_FONT_GIANT), MF(CONSOLE_FONT_GIANT), MF(COMMENT_FONT_GIANT), MF(EDITTAGS_FONT_GIANT), MF(MOVEHISTORY_FONT_ALL) },
\r
289 { MF(CLOCK_FONT_COLOSSAL), MF(MESSAGE_FONT_COLOSSAL), MF(COORD_FONT_COLOSSAL), MF(CONSOLE_FONT_COLOSSAL), MF(COMMENT_FONT_COLOSSAL), MF(EDITTAGS_FONT_COLOSSAL), MF(MOVEHISTORY_FONT_ALL) },
\r
290 { MF(CLOCK_FONT_TITANIC), MF(MESSAGE_FONT_TITANIC), MF(COORD_FONT_TITANIC), MF(CONSOLE_FONT_TITANIC), MF(COMMENT_FONT_TITANIC), MF(EDITTAGS_FONT_TITANIC), MF(MOVEHISTORY_FONT_ALL) },
\r
293 MyFont *font[NUM_SIZES][NUM_FONTS];
\r
302 #define BUTTON_WIDTH (tinyLayout ? 16 : 32)
\r
303 #define N_BUTTONS 5
\r
305 MyButtonDesc buttonDesc[N_BUTTONS] =
\r
307 {"<<", IDM_ToStart, NULL, NULL},
\r
308 {"<", IDM_Backward, NULL, NULL},
\r
309 {"P", IDM_Pause, NULL, NULL},
\r
310 {">", IDM_Forward, NULL, NULL},
\r
311 {">>", IDM_ToEnd, NULL, NULL},
\r
314 int tinyLayout = 0, smallLayout = 0;
\r
315 #define MENU_BAR_ITEMS 7
\r
316 char *menuBarText[2][MENU_BAR_ITEMS+1] = {
\r
317 { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },
\r
318 { "&F", "&M", "&A", "&S", "&O", "&H", NULL },
\r
322 MySound sounds[(int)NSoundClasses];
\r
323 MyTextAttribs textAttribs[(int)NColorClasses];
\r
325 MyColorizeAttribs colorizeAttribs[] = {
\r
326 { (COLORREF)0, 0, "Shout Text" },
\r
327 { (COLORREF)0, 0, "SShout/CShout" },
\r
328 { (COLORREF)0, 0, "Channel 1 Text" },
\r
329 { (COLORREF)0, 0, "Channel Text" },
\r
330 { (COLORREF)0, 0, "Kibitz Text" },
\r
331 { (COLORREF)0, 0, "Tell Text" },
\r
332 { (COLORREF)0, 0, "Challenge Text" },
\r
333 { (COLORREF)0, 0, "Request Text" },
\r
334 { (COLORREF)0, 0, "Seek Text" },
\r
335 { (COLORREF)0, 0, "Normal Text" },
\r
336 { (COLORREF)0, 0, "None" }
\r
341 static char *commentTitle;
\r
342 static char *commentText;
\r
343 static int commentIndex;
\r
344 static Boolean editComment = FALSE;
\r
345 HWND commentDialog = NULL;
\r
346 BOOLEAN commentDialogUp = FALSE;
\r
347 static int commentX, commentY, commentH, commentW;
\r
349 static char *analysisTitle;
\r
350 static char *analysisText;
\r
351 HWND analysisDialog = NULL;
\r
352 BOOLEAN analysisDialogUp = FALSE;
\r
353 static int analysisX, analysisY, analysisH, analysisW;
\r
355 char errorTitle[MSG_SIZ];
\r
356 char errorMessage[2*MSG_SIZ];
\r
357 HWND errorDialog = NULL;
\r
358 BOOLEAN moveErrorMessageUp = FALSE;
\r
359 BOOLEAN consoleEcho = TRUE;
\r
360 CHARFORMAT consoleCF;
\r
361 COLORREF consoleBackgroundColor;
\r
363 char *programVersion;
\r
369 typedef int CPKind;
\r
378 SOCKET sock2; /* stderr socket for OpenRcmd */
\r
381 #define INPUT_SOURCE_BUF_SIZE 4096
\r
383 typedef struct _InputSource {
\r
390 char buf[INPUT_SOURCE_BUF_SIZE];
\r
394 InputCallback func;
\r
395 struct _InputSource *second; /* for stderr thread on CPRcmd */
\r
399 InputSource *consoleInputSource;
\r
404 VOID ConsoleOutput(char* data, int length, int forceVisible);
\r
405 VOID ConsoleCreate();
\r
407 ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
408 VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
\r
409 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
\r
410 VOID ParseCommSettings(char *arg, DCB *dcb);
\r
412 StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
413 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
\r
414 void ParseIcsTextMenu(char *icsTextMenuString);
\r
415 VOID PopUpMoveDialog(char firstchar);
\r
416 VOID PopUpNameDialog(char firstchar);
\r
417 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
\r
421 int GameListOptions();
\r
423 HWND moveHistoryDialog = NULL;
\r
424 BOOLEAN moveHistoryDialogUp = FALSE;
\r
426 WindowPlacement wpMoveHistory;
\r
428 HWND evalGraphDialog = NULL;
\r
429 BOOLEAN evalGraphDialogUp = FALSE;
\r
431 WindowPlacement wpEvalGraph;
\r
433 HWND engineOutputDialog = NULL;
\r
434 BOOLEAN engineOutputDialogUp = FALSE;
\r
436 WindowPlacement wpEngineOutput;
\r
437 WindowPlacement wpGameList;
\r
438 WindowPlacement wpConsole;
\r
440 VOID MoveHistoryPopUp();
\r
441 VOID MoveHistoryPopDown();
\r
442 VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
443 BOOL MoveHistoryIsUp();
\r
445 VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
446 VOID EvalGraphPopUp();
\r
447 VOID EvalGraphPopDown();
\r
448 BOOL EvalGraphIsUp();
\r
450 VOID EngineOutputPopUp();
\r
451 VOID EngineOutputPopDown();
\r
452 BOOL EngineOutputIsUp();
\r
453 VOID EngineOutputUpdate( FrontEndProgramStats * stats );
\r
455 VOID EngineOptionsPopup(); // [HGM] settings
\r
457 VOID GothicPopUp(char *title, VariantClass variant);
\r
459 * Setting "frozen" should disable all user input other than deleting
\r
460 * the window. We do this while engines are initializing themselves.
\r
462 static int frozen = 0;
\r
463 static int oldMenuItemState[MENU_BAR_ITEMS];
\r
469 if (frozen) return;
\r
471 hmenu = GetMenu(hwndMain);
\r
472 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
473 oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
\r
475 DrawMenuBar(hwndMain);
\r
478 /* Undo a FreezeUI */
\r
484 if (!frozen) return;
\r
486 hmenu = GetMenu(hwndMain);
\r
487 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
488 EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
\r
490 DrawMenuBar(hwndMain);
\r
493 static int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them
\r
495 /* JAWS preparation patch (WinBoard for the sight impaired). Define required insertions as empty */
\r
501 #define JAWS_ALT_INTERCEPT
\r
502 #define JAWS_KB_NAVIGATION
\r
503 #define JAWS_MENU_ITEMS
\r
504 #define JAWS_SILENCE
\r
505 #define JAWS_REPLAY
\r
507 #define JAWS_COPYRIGHT
\r
508 #define JAWS_DELETE(X) X
\r
509 #define SAYMACHINEMOVE()
\r
513 /*---------------------------------------------------------------------------*\
\r
517 \*---------------------------------------------------------------------------*/
\r
520 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
\r
521 LPSTR lpCmdLine, int nCmdShow)
\r
524 HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
\r
525 // INITCOMMONCONTROLSEX ex;
\r
529 LoadLibrary("RICHED32.DLL");
\r
530 consoleCF.cbSize = sizeof(CHARFORMAT);
\r
532 if (!InitApplication(hInstance)) {
\r
535 if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
\r
541 // InitCommonControlsEx(&ex);
\r
542 InitCommonControls();
\r
544 hAccelMain = LoadAccelerators (hInstance, szAppName);
\r
545 hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
\r
546 hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
\r
548 /* Acquire and dispatch messages until a WM_QUIT message is received. */
\r
550 while (GetMessage(&msg, /* message structure */
\r
551 NULL, /* handle of window receiving the message */
\r
552 0, /* lowest message to examine */
\r
553 0)) /* highest message to examine */
\r
556 if(msg.message == WM_CHAR && msg.wParam == '\t') {
\r
557 // [HGM] navigate: switch between all windows with tab
\r
558 HWND e1 = NULL, e2 = NULL, mh = NULL, hInput = NULL, hText = NULL;
\r
559 int i, currentElement = 0;
\r
561 // first determine what element of the chain we come from (if any)
\r
562 if(appData.icsActive) {
\r
563 hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);
\r
564 hText = GetDlgItem(hwndConsole, OPT_ConsoleText);
\r
566 if(engineOutputDialog && EngineOutputIsUp()) {
\r
567 e1 = GetDlgItem(engineOutputDialog, IDC_EngineMemo1);
\r
568 e2 = GetDlgItem(engineOutputDialog, IDC_EngineMemo2);
\r
570 if(moveHistoryDialog && MoveHistoryIsUp()) {
\r
571 mh = GetDlgItem(moveHistoryDialog, IDC_MoveHistory);
\r
573 if(msg.hwnd == hwndMain) currentElement = 7 ; else
\r
574 if(msg.hwnd == engineOutputDialog) currentElement = 2; else
\r
575 if(msg.hwnd == e1) currentElement = 2; else
\r
576 if(msg.hwnd == e2) currentElement = 3; else
\r
577 if(msg.hwnd == moveHistoryDialog) currentElement = 4; else
\r
578 if(msg.hwnd == mh) currentElement = 4; else
\r
579 if(msg.hwnd == evalGraphDialog) currentElement = 6; else
\r
580 if(msg.hwnd == hText) currentElement = 5; else
\r
581 if(msg.hwnd == hInput) currentElement = 6; else
\r
582 for (i = 0; i < N_BUTTONS; i++) {
\r
583 if (buttonDesc[i].hwnd == msg.hwnd) { currentElement = 1; break; }
\r
586 // determine where to go to
\r
587 if(currentElement) { HWND h = NULL; int direction = GetKeyState(VK_SHIFT) < 0 ? -1 : 1;
\r
589 currentElement = (currentElement + direction) % 7;
\r
590 switch(currentElement) {
\r
592 h = hwndMain; break; // passing this case always makes the loop exit
\r
594 h = buttonDesc[0].hwnd; break; // could be NULL
\r
596 if(!EngineOutputIsUp()) continue; // skip closed auxiliary windows
\r
599 if(!EngineOutputIsUp()) continue;
\r
602 if(!MoveHistoryIsUp()) continue;
\r
604 // case 6: // input to eval graph does not seem to get here!
\r
605 // if(!EvalGraphIsUp()) continue;
\r
606 // h = evalGraphDialog; break;
\r
608 if(!appData.icsActive) continue;
\r
612 if(!appData.icsActive) continue;
\r
618 if(currentElement > 4 && IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);
\r
619 if(currentElement < 5 && IsIconic(hwndMain)) ShowWindow(hwndMain, SW_RESTORE); // all open together
\r
622 continue; // this message now has been processed
\r
626 if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
\r
627 !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
\r
628 !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
\r
629 !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
\r
630 !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
\r
631 !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
\r
632 !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
\r
633 !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) && JAWS_ACCEL
\r
634 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
\r
635 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
\r
636 int done = 0, i; // [HGM] chat: dispatch cat-box messages
\r
637 for(i=0; i<MAX_CHAT; i++)
\r
638 if(chatHandle[i] && IsDialogMessage(chatHandle[i], &msg)) {
\r
641 if(done) continue; // [HGM] chat: end patch
\r
642 TranslateMessage(&msg); /* Translates virtual key codes */
\r
643 DispatchMessage(&msg); /* Dispatches message to window */
\r
648 return (msg.wParam); /* Returns the value from PostQuitMessage */
\r
651 /*---------------------------------------------------------------------------*\
\r
653 * Initialization functions
\r
655 \*---------------------------------------------------------------------------*/
\r
659 { // update user logo if necessary
\r
660 static char oldUserName[MSG_SIZ], *curName;
\r
662 if(appData.autoLogo) {
\r
663 curName = UserName();
\r
664 if(strcmp(curName, oldUserName)) {
\r
665 sprintf(oldUserName, "logos\\%s.bmp", curName);
\r
666 userLogo = LoadImage( 0, oldUserName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
667 strcpy(oldUserName, curName);
\r
673 InitApplication(HINSTANCE hInstance)
\r
677 /* Fill in window class structure with parameters that describe the */
\r
680 wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
\r
681 wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
\r
682 wc.cbClsExtra = 0; /* No per-class extra data. */
\r
683 wc.cbWndExtra = 0; /* No per-window extra data. */
\r
684 wc.hInstance = hInstance; /* Owner of this class */
\r
685 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
686 wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
\r
687 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
\r
688 wc.lpszMenuName = szAppName; /* Menu name from .RC */
\r
689 wc.lpszClassName = szAppName; /* Name to register as */
\r
691 /* Register the window class and return success/failure code. */
\r
692 if (!RegisterClass(&wc)) return FALSE;
\r
694 wc.style = CS_HREDRAW | CS_VREDRAW;
\r
695 wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
\r
697 wc.cbWndExtra = DLGWINDOWEXTRA;
\r
698 wc.hInstance = hInstance;
\r
699 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
700 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
\r
701 wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
\r
702 wc.lpszMenuName = NULL;
\r
703 wc.lpszClassName = szConsoleName;
\r
705 if (!RegisterClass(&wc)) return FALSE;
\r
710 /* Set by InitInstance, used by EnsureOnScreen */
\r
711 int screenHeight, screenWidth;
\r
714 EnsureOnScreen(int *x, int *y, int minX, int minY)
\r
716 // int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
\r
717 /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
\r
718 if (*x > screenWidth - 32) *x = 0;
\r
719 if (*y > screenHeight - 32) *y = 0;
\r
720 if (*x < minX) *x = minX;
\r
721 if (*y < minY) *y = minY;
\r
725 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
\r
727 HWND hwnd; /* Main window handle. */
\r
729 WINDOWPLACEMENT wp;
\r
732 hInst = hInstance; /* Store instance handle in our global variable */
\r
734 if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
\r
735 *filepart = NULLCHAR;
\r
737 GetCurrentDirectory(MSG_SIZ, installDir);
\r
739 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise
\r
740 screenWidth = screenHeight = 1000; // [HGM] placement: kludge to allow calling EnsureOnScreen from InitAppData
\r
741 InitAppData(lpCmdLine); /* Get run-time parameters */
\r
742 if (appData.debugMode) {
\r
743 debugFP = fopen(appData.nameOfDebugFile, "w");
\r
744 setbuf(debugFP, NULL);
\r
749 // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()
\r
750 // InitEngineUCI( installDir, &second );
\r
752 /* Create a main window for this application instance. */
\r
753 hwnd = CreateWindow(szAppName, szTitle,
\r
754 (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
\r
755 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
\r
756 NULL, NULL, hInstance, NULL);
\r
759 /* If window could not be created, return "failure" */
\r
764 /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */
\r
765 if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {
\r
766 first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
768 if (first.programLogo == NULL && appData.debugMode) {
\r
769 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );
\r
771 } else if(appData.autoLogo) {
\r
772 if(appData.firstDirectory && appData.firstDirectory[0]) {
\r
774 sprintf(buf, "%s/logo.bmp", appData.firstDirectory);
\r
775 first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
779 if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {
\r
780 second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
782 if (second.programLogo == NULL && appData.debugMode) {
\r
783 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );
\r
785 } else if(appData.autoLogo) {
\r
787 if(appData.icsActive) { // [HGM] logo: in ICS mode second can be used for ICS
\r
788 sprintf(buf, "logos\\%s.bmp", appData.icsHost);
\r
789 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
791 if(appData.secondDirectory && appData.secondDirectory[0]) {
\r
792 sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);
\r
793 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
799 iconWhite = LoadIcon(hInstance, "icon_white");
\r
800 iconBlack = LoadIcon(hInstance, "icon_black");
\r
801 iconCurrent = iconWhite;
\r
802 InitDrawingColors();
\r
803 screenHeight = GetSystemMetrics(SM_CYSCREEN);
\r
804 screenWidth = GetSystemMetrics(SM_CXSCREEN);
\r
805 for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
\r
806 /* Compute window size for each board size, and use the largest
\r
807 size that fits on this screen as the default. */
\r
808 InitDrawingSizes((BoardSize)(ibs+1000), 0);
\r
809 if (boardSize == (BoardSize)-1 &&
\r
810 winH <= screenHeight
\r
811 - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10
\r
812 && winW <= screenWidth) {
\r
813 boardSize = (BoardSize)ibs;
\r
817 InitDrawingSizes(boardSize, 0);
\r
819 buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
\r
821 /* [AS] Load textures if specified */
\r
822 ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );
\r
824 if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {
\r
825 liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
826 liteBackTextureMode = appData.liteBackTextureMode;
\r
828 if (liteBackTexture == NULL && appData.debugMode) {
\r
829 fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );
\r
833 if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {
\r
834 darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
835 darkBackTextureMode = appData.darkBackTextureMode;
\r
837 if (darkBackTexture == NULL && appData.debugMode) {
\r
838 fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );
\r
842 mysrandom( (unsigned) time(NULL) );
\r
844 /* [AS] Restore layout */
\r
845 if( wpMoveHistory.visible ) {
\r
846 MoveHistoryPopUp();
\r
849 if( wpEvalGraph.visible ) {
\r
853 if( wpEngineOutput.visible ) {
\r
854 EngineOutputPopUp();
\r
859 /* Make the window visible; update its client area; and return "success" */
\r
860 EnsureOnScreen(&boardX, &boardY, minX, minY);
\r
861 wp.length = sizeof(WINDOWPLACEMENT);
\r
863 wp.showCmd = nCmdShow;
\r
864 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
\r
865 wp.rcNormalPosition.left = boardX;
\r
866 wp.rcNormalPosition.right = boardX + winWidth;
\r
867 wp.rcNormalPosition.top = boardY;
\r
868 wp.rcNormalPosition.bottom = boardY + winHeight;
\r
869 SetWindowPlacement(hwndMain, &wp);
\r
871 if(!appData.noGUI) SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
872 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
876 SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
877 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
879 ShowWindow(hwndConsole, nCmdShow);
\r
881 if(!appData.noGUI) UpdateWindow(hwnd); else ShowWindow(hwnd, SW_MINIMIZE);
\r
889 ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
\r
890 ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
\r
891 ArgSettingsFilename,
\r
892 ArgX, ArgY, ArgZ // [HGM] placement: for window-placement options stored relative to main window
\r
900 String *pString; // ArgString
\r
901 int *pInt; // ArgInt
\r
902 float *pFloat; // ArgFloat
\r
903 Boolean *pBoolean; // ArgBoolean
\r
904 COLORREF *pColor; // ArgColor
\r
905 ColorClass cc; // ArgAttribs
\r
906 String *pFilename; // ArgFilename
\r
907 BoardSize *pBoardSize; // ArgBoardSize
\r
908 int whichFont; // ArgFont
\r
909 DCB *pDCB; // ArgCommSettings
\r
910 String *pFilename; // ArgSettingsFilename
\r
918 ArgDescriptor argDescriptors[] = {
\r
919 /* positional arguments */
\r
920 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
921 { "", ArgNone, NULL },
\r
922 /* keyword arguments */
\r
924 { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },
\r
925 { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },
\r
926 { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },
\r
927 { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },
\r
928 { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },
\r
929 { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },
\r
930 { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },
\r
931 { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },
\r
932 { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },
\r
933 { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },
\r
934 { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },
\r
935 { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },
\r
936 { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },
\r
937 { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },
\r
938 { "initString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
939 { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
940 { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },
\r
941 { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,
\r
943 { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,
\r
945 { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,
\r
947 { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },
\r
948 { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,
\r
950 { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },
\r
951 { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
952 { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
953 { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
954 { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
955 { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },
\r
956 { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },
\r
957 { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
958 { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
959 { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
960 { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
961 { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
962 { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
963 { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
964 { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
965 { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
966 { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
967 /*!!bitmapDirectory?*/
\r
968 { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
969 { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
970 { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
971 { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
972 { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },
\r
973 { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },
\r
974 { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },
\r
975 { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },
\r
976 { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },
\r
977 { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },
\r
978 { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },
\r
979 { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },
\r
980 { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
981 { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
982 { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
983 { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
984 { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
985 { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
986 { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
987 { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
988 { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
989 { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
990 { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
991 { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
992 { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },
\r
993 { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },
\r
994 { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
995 { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
996 { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },
\r
997 { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },
\r
998 { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },
\r
999 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
1000 { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
1001 { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
1002 { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
1003 { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },
\r
1004 { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },
\r
1005 { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },
\r
1006 { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },
\r
1007 { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
1008 { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
1009 { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
1010 { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
1011 { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
1012 { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
1013 { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
1014 { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
1015 { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },
\r
1016 { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },
\r
1017 { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
1018 { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
1019 { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
1020 { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
1021 { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },
\r
1022 { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },
\r
1023 { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
1024 { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
1025 { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },
\r
1026 { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },
\r
1027 { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
1028 { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
1029 { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },
\r
1030 { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },
\r
1031 { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
1032 { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
1033 { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
1034 { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
1035 { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
1036 { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
1037 { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },
\r
1038 { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },
\r
1039 { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
1040 { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
1041 { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },
\r
1042 { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },
\r
1043 { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
1044 { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
1045 { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },
\r
1046 { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1047 { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1048 { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1049 { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },
\r
1050 { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1051 { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1052 { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1053 { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },
\r
1054 { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1055 { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1056 { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1057 { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },
\r
1058 { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1059 { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1060 { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1061 { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors,
\r
1062 FALSE }, /* only so that old WinBoard.ini files from betas can be read */
\r
1063 { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },
\r
1064 { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },
\r
1065 { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },
\r
1066 { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },
\r
1067 { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },
\r
1068 { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },
\r
1069 { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE }, /* [AS] */
\r
1070 { "boardSize", ArgBoardSize, (LPVOID) &boardSize,
\r
1071 TRUE }, /* must come after all fonts */
\r
1072 { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },
\r
1073 { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,
\r
1074 FALSE }, /* historical; kept only so old winboard.ini files will parse */
\r
1075 { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },
\r
1076 { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },
\r
1077 { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
1078 { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
1079 { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },
\r
1080 { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1081 { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1082 { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1083 { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },
\r
1084 { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },
\r
1085 { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
1086 { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
1087 { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },
\r
1088 { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },
\r
1089 { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
1090 { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
1091 { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },
\r
1092 { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },
\r
1093 { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
1094 { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
1095 { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },
\r
1096 { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },
\r
1097 { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
1098 { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
1099 { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },
\r
1100 { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1101 { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1102 { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1104 { "cmailGameName", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
1105 { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
1107 { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },
\r
1108 { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1109 { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1110 { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1111 { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },
\r
1112 { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1113 { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1114 { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1115 { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },
\r
1116 { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },
\r
1117 { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
1118 { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
1119 { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },
\r
1120 { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },
\r
1121 { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
1122 { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
1123 { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },
\r
1124 { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },
\r
1125 { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
1126 { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
1127 { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },
\r
1128 { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },
\r
1129 { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
1130 { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
1131 { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },
\r
1132 { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },
\r
1133 { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
1134 { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
1135 { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },
\r
1136 { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },
\r
1137 { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },
\r
1138 { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1139 { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1140 { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },
\r
1141 { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},
\r
1142 { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},
\r
1143 { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1144 { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1145 { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},
\r
1146 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1147 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1148 { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },
\r
1149 { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1150 { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1151 { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },
\r
1152 { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },
\r
1153 { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1154 { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1155 { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },
\r
1156 { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },
\r
1157 { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },
\r
1158 { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1159 { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1160 { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },
\r
1161 { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },
\r
1162 { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1163 { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1164 { "highlightLastMove", ArgBoolean,
\r
1165 (LPVOID) &appData.highlightLastMove, TRUE },
\r
1166 { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1167 { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1168 { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1169 { "highlightDragging", ArgBoolean,
\r
1170 (LPVOID) &appData.highlightDragging, TRUE },
\r
1171 { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },
\r
1172 { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1173 { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1174 { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },
\r
1175 { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },
\r
1176 { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1177 { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1178 { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },
\r
1179 { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },
\r
1180 { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },
\r
1181 { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },
\r
1182 { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },
\r
1183 { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },
\r
1184 { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },
\r
1185 { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },
\r
1186 { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },
\r
1187 { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },
\r
1188 { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },
\r
1189 { "soundShout", ArgFilename,
\r
1190 (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },
\r
1191 { "soundSShout", ArgFilename,
\r
1192 (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },
\r
1193 { "soundChannel1", ArgFilename,
\r
1194 (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },
\r
1195 { "soundChannel", ArgFilename,
\r
1196 (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },
\r
1197 { "soundKibitz", ArgFilename,
\r
1198 (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },
\r
1199 { "soundTell", ArgFilename,
\r
1200 (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },
\r
1201 { "soundChallenge", ArgFilename,
\r
1202 (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },
\r
1203 { "soundRequest", ArgFilename,
\r
1204 (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },
\r
1205 { "soundSeek", ArgFilename,
\r
1206 (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },
\r
1207 { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },
\r
1208 { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },
\r
1209 { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },
\r
1210 { "soundIcsLoss", ArgFilename,
\r
1211 (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },
\r
1212 { "soundIcsDraw", ArgFilename,
\r
1213 (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },
\r
1214 { "soundIcsUnfinished", ArgFilename,
\r
1215 (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},
\r
1216 { "soundIcsAlarm", ArgFilename,
\r
1217 (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },
\r
1218 { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },
\r
1219 { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },
\r
1220 { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1221 { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1222 { "reuseChessPrograms", ArgBoolean,
\r
1223 (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */
\r
1224 { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },
\r
1225 { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },
\r
1226 { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1227 { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1228 { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },
\r
1229 { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1230 { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1231 { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },
\r
1232 { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },
\r
1233 { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },
\r
1234 { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1235 { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1236 { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },
\r
1237 { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },
\r
1238 { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,
\r
1240 { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,
\r
1242 { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1243 { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1244 { "variant", ArgString, (LPVOID) &appData.variant, FALSE },
\r
1245 { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion, FALSE },
\r
1246 { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,FALSE },
\r
1247 { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },
\r
1248 { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },
\r
1249 { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1250 { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1251 /* [AS] New features */
\r
1252 { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE },
\r
1253 { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE },
\r
1254 { "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE },
\r
1255 { "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE },
\r
1256 { "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE },
\r
1257 { "darkBackTextureFile", ArgString, (LPVOID) &appData.darkBackTextureFile, TRUE },
\r
1258 { "liteBackTextureMode", ArgInt, (LPVOID) &appData.liteBackTextureMode, TRUE },
\r
1259 { "darkBackTextureMode", ArgInt, (LPVOID) &appData.darkBackTextureMode, TRUE },
\r
1260 { "renderPiecesWithFont", ArgString, (LPVOID) &appData.renderPiecesWithFont, TRUE },
\r
1261 { "fontPieceToCharTable", ArgString, (LPVOID) &appData.fontToPieceTable, TRUE },
\r
1262 { "fontPieceBackColorWhite", ArgColor, (LPVOID) &appData.fontBackColorWhite, TRUE },
\r
1263 { "fontPieceForeColorWhite", ArgColor, (LPVOID) &appData.fontForeColorWhite, TRUE },
\r
1264 { "fontPieceBackColorBlack", ArgColor, (LPVOID) &appData.fontBackColorBlack, TRUE },
\r
1265 { "fontPieceForeColorBlack", ArgColor, (LPVOID) &appData.fontForeColorBlack, TRUE },
\r
1266 { "fontPieceSize", ArgInt, (LPVOID) &appData.fontPieceSize, TRUE },
\r
1267 { "overrideLineGap", ArgInt, (LPVOID) &appData.overrideLineGap, TRUE },
\r
1268 { "adjudicateLossThreshold", ArgInt, (LPVOID) &appData.adjudicateLossThreshold, TRUE },
\r
1269 { "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE },
\r
1270 { "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE },
\r
1271 { "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1272 { "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1273 { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },
\r
1274 { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE },
\r
1275 { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE },
\r
1276 { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE },
\r
1277 { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE },
\r
1278 { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE },
\r
1279 { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE },
\r
1280 { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE },
\r
1281 { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE },
\r
1282 { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE },
\r
1283 { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE },
\r
1284 { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE },
\r
1285 { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE },
\r
1286 { "firstIsUCI", ArgBoolean, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1287 { "fUCI", ArgTrue, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1288 { "secondIsUCI", ArgBoolean, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1289 { "sUCI", ArgTrue, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1290 { "firstHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1291 { "fNoOwnBookUCI", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1292 { "firstXBook", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1293 { "secondHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1294 { "sNoOwnBookUCI", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1295 { "secondXBook", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1296 { "polyglotDir", ArgFilename, (LPVOID) &appData.polyglotDir, TRUE },
\r
1297 { "usePolyglotBook", ArgBoolean, (LPVOID) &appData.usePolyglotBook, TRUE },
\r
1298 { "polyglotBook", ArgFilename, (LPVOID) &appData.polyglotBook, TRUE },
\r
1299 { "defaultHashSize", ArgInt, (LPVOID) &appData.defaultHashSize, TRUE },
\r
1300 { "defaultCacheSizeEGTB", ArgInt, (LPVOID) &appData.defaultCacheSizeEGTB, TRUE },
\r
1301 { "defaultPathEGTB", ArgFilename, (LPVOID) &appData.defaultPathEGTB, TRUE },
\r
1303 /* [HGM] board-size, adjudication and misc. options */
\r
1304 { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE },
\r
1305 { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE },
\r
1306 { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE },
\r
1307 { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE },
\r
1308 { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE },
\r
1309 { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE },
\r
1310 { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE },
\r
1311 { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE },
\r
1312 { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE },
\r
1313 { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE },
\r
1314 { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE },
\r
1315 { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE },
\r
1316 { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE },
\r
1317 { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE },
\r
1318 { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE },
\r
1319 { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE },
\r
1320 { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE },
\r
1321 { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE },
\r
1322 { "userName", ArgString, (LPVOID) &appData.userName, FALSE },
\r
1323 { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE },
\r
1324 { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE },
\r
1325 { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE },
\r
1326 { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE },
\r
1327 { "niceEngines", ArgInt, (LPVOID) &appData.niceEngines, TRUE },
\r
1328 { "firstLogo", ArgFilename, (LPVOID) &appData.firstLogo, FALSE },
\r
1329 { "secondLogo", ArgFilename, (LPVOID) &appData.secondLogo, FALSE },
\r
1330 { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE },
\r
1331 { "firstOptions", ArgString, (LPVOID) &appData.firstOptions, FALSE },
\r
1332 { "secondOptions", ArgString, (LPVOID) &appData.secondOptions, FALSE },
\r
1333 { "firstNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride1, FALSE },
\r
1334 { "secondNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride2, FALSE },
\r
1335 { "keepAlive", ArgInt, (LPVOID) &appData.keepAlive, FALSE },
\r
1336 { "icstype", ArgInt, (LPVOID) &ics_type, FALSE },
\r
1339 { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },
\r
1340 { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },
\r
1341 { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1342 { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1343 { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },
\r
1344 { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },
\r
1345 { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1346 { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1347 { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },
\r
1348 { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },
\r
1349 { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },
\r
1350 { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE },
\r
1351 { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,
\r
1353 { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE },
\r
1354 { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE },
\r
1355 { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE },
\r
1356 { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1357 { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1358 { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE },
\r
1359 { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,
\r
1361 { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1362 { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1363 { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1364 { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE },
\r
1365 { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE },
\r
1366 { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1367 { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1368 { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1369 { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1370 { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE },
\r
1371 { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE },
\r
1372 { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1373 { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1374 { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },
\r
1375 { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },
\r
1376 { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },
\r
1377 { "zippyShortGame", ArgInt, (LPVOID)&appData.zippyShortGame, FALSE },
\r
1378 /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */
\r
1379 { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },
\r
1381 /* [HGM] options for broadcasting and time odds */
\r
1382 { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },
\r
1383 { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },
\r
1384 { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },
\r
1385 { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },
\r
1386 { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },
\r
1387 { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },
\r
1388 { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },
\r
1389 { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },
\r
1390 { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },
\r
1391 { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },
\r
1392 { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE },
\r
1394 // [HGM] placement: put all window layouts last in ini file, but man X,Y before all others
\r
1395 { "minX", ArgZ, (LPVOID) &minX, FALSE }, // [HGM] placement: to make suer auxialary windows can be placed
\r
1396 { "minY", ArgZ, (LPVOID) &minY, FALSE },
\r
1397 { "winWidth", ArgInt, (LPVOID) &winWidth, TRUE }, // [HGM] placement: dummies to remember right & bottom
\r
1398 { "winHeight", ArgInt, (LPVOID) &winHeight, TRUE }, // for attaching auxiliary windows to them
\r
1399 { "x", ArgInt, (LPVOID) &boardX, TRUE },
\r
1400 { "y", ArgInt, (LPVOID) &boardY, TRUE },
\r
1401 { "icsX", ArgX, (LPVOID) &wpConsole.x, TRUE },
\r
1402 { "icsY", ArgY, (LPVOID) &wpConsole.y, TRUE },
\r
1403 { "icsW", ArgInt, (LPVOID) &wpConsole.width, TRUE },
\r
1404 { "icsH", ArgInt, (LPVOID) &wpConsole.height, TRUE },
\r
1405 { "analysisX", ArgX, (LPVOID) &analysisX, FALSE }, // [HGM] placement: analysis window no longer exists
\r
1406 { "analysisY", ArgY, (LPVOID) &analysisY, FALSE }, // provided for compatibility with old ini files
\r
1407 { "analysisW", ArgInt, (LPVOID) &analysisW, FALSE },
\r
1408 { "analysisH", ArgInt, (LPVOID) &analysisH, FALSE },
\r
1409 { "commentX", ArgX, (LPVOID) &commentX, TRUE },
\r
1410 { "commentY", ArgY, (LPVOID) &commentY, TRUE },
\r
1411 { "commentW", ArgInt, (LPVOID) &commentW, TRUE },
\r
1412 { "commentH", ArgInt, (LPVOID) &commentH, TRUE },
\r
1413 { "tagsX", ArgX, (LPVOID) &editTagsX, TRUE },
\r
1414 { "tagsY", ArgY, (LPVOID) &editTagsY, TRUE },
\r
1415 { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },
\r
1416 { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },
\r
1417 { "gameListX", ArgX, (LPVOID) &wpGameList.x, TRUE },
\r
1418 { "gameListY", ArgY, (LPVOID) &wpGameList.y, TRUE },
\r
1419 { "gameListW", ArgInt, (LPVOID) &wpGameList.width, TRUE },
\r
1420 { "gameListH", ArgInt, (LPVOID) &wpGameList.height, TRUE },
\r
1421 /* [AS] Layout stuff */
\r
1422 { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },
\r
1423 { "moveHistoryX", ArgX, (LPVOID) &wpMoveHistory.x, TRUE },
\r
1424 { "moveHistoryY", ArgY, (LPVOID) &wpMoveHistory.y, TRUE },
\r
1425 { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },
\r
1426 { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },
\r
1428 { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },
\r
1429 { "evalGraphX", ArgX, (LPVOID) &wpEvalGraph.x, TRUE },
\r
1430 { "evalGraphY", ArgY, (LPVOID) &wpEvalGraph.y, TRUE },
\r
1431 { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },
\r
1432 { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },
\r
1434 { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },
\r
1435 { "engineOutputX", ArgX, (LPVOID) &wpEngineOutput.x, TRUE },
\r
1436 { "engineOutputY", ArgY, (LPVOID) &wpEngineOutput.y, TRUE },
\r
1437 { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },
\r
1438 { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },
\r
1440 { NULL, ArgNone, NULL, FALSE }
\r
1444 /* Kludge for indirection files on command line */
\r
1445 char* lastIndirectionFilename;
\r
1446 ArgDescriptor argDescriptorIndirection =
\r
1447 { "", ArgSettingsFilename, (LPVOID) NULL, FALSE };
\r
1451 ExitArgError(char *msg, char *badArg)
\r
1453 char buf[MSG_SIZ];
\r
1455 sprintf(buf, "%s %s", msg, badArg);
\r
1456 DisplayFatalError(buf, 0, 2);
\r
1460 /* Command line font name parser. NULL name means do nothing.
\r
1461 Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"
\r
1462 For backward compatibility, syntax without the colon is also
\r
1463 accepted, but font names with digits in them won't work in that case.
\r
1466 ParseFontName(char *name, MyFontParams *mfp)
\r
1469 if (name == NULL) return;
\r
1471 q = strchr(p, ':');
\r
1473 if (q - p >= sizeof(mfp->faceName))
\r
1474 ExitArgError("Font name too long:", name);
\r
1475 memcpy(mfp->faceName, p, q - p);
\r
1476 mfp->faceName[q - p] = NULLCHAR;
\r
1479 q = mfp->faceName;
\r
1480 while (*p && !isdigit(*p)) {
\r
1482 if (q - mfp->faceName >= sizeof(mfp->faceName))
\r
1483 ExitArgError("Font name too long:", name);
\r
1485 while (q > mfp->faceName && q[-1] == ' ') q--;
\r
1488 if (!*p) ExitArgError("Font point size missing:", name);
\r
1489 mfp->pointSize = (float) atof(p);
\r
1490 mfp->bold = (strchr(p, 'b') != NULL);
\r
1491 mfp->italic = (strchr(p, 'i') != NULL);
\r
1492 mfp->underline = (strchr(p, 'u') != NULL);
\r
1493 mfp->strikeout = (strchr(p, 's') != NULL);
\r
1496 /* Color name parser.
\r
1497 X version accepts X color names, but this one
\r
1498 handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */
\r
1500 ParseColorName(char *name)
\r
1502 int red, green, blue, count;
\r
1503 char buf[MSG_SIZ];
\r
1505 count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);
\r
1507 count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d",
\r
1508 &red, &green, &blue);
\r
1511 sprintf(buf, "Can't parse color name %s", name);
\r
1512 DisplayError(buf, 0);
\r
1513 return RGB(0, 0, 0);
\r
1515 return PALETTERGB(red, green, blue);
\r
1519 void ParseAttribs(COLORREF *color, int *effects, char* argValue)
\r
1521 char *e = argValue;
\r
1525 if (*e == 'b') eff |= CFE_BOLD;
\r
1526 else if (*e == 'i') eff |= CFE_ITALIC;
\r
1527 else if (*e == 'u') eff |= CFE_UNDERLINE;
\r
1528 else if (*e == 's') eff |= CFE_STRIKEOUT;
\r
1529 else if (*e == '#' || isdigit(*e)) break;
\r
1533 *color = ParseColorName(e);
\r
1538 ParseBoardSize(char *name)
\r
1540 BoardSize bs = SizeTiny;
\r
1541 while (sizeInfo[bs].name != NULL) {
\r
1542 if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;
\r
1545 ExitArgError("Unrecognized board size value", name);
\r
1546 return bs; /* not reached */
\r
1551 StringGet(void *getClosure)
\r
1553 char **p = (char **) getClosure;
\r
1558 FileGet(void *getClosure)
\r
1561 FILE* f = (FILE*) getClosure;
\r
1564 if (c == '\r') c = getc(f); // work around DOS format files by bypassing the '\r' completely
\r
1571 /* Parse settings file named "name". If file found, return the
\r
1572 full name in fullname and return TRUE; else return FALSE */
\r
1574 ParseSettingsFile(char *name, char fullname[MSG_SIZ])
\r
1578 int ok; char buf[MSG_SIZ];
\r
1580 ok = SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy);
\r
1581 if(!ok && strchr(name, '.') == NULL) { // [HGM] append default file-name extension '.ini' when needed
\r
1582 sprintf(buf, "%s.ini", name);
\r
1583 ok = SearchPath(installDir, buf, NULL, MSG_SIZ, fullname, &dummy);
\r
1586 f = fopen(fullname, "r");
\r
1588 ParseArgs(FileGet, f);
\r
1597 ParseArgs(GetFunc get, void *cl)
\r
1599 char argName[ARG_MAX];
\r
1600 char argValue[ARG_MAX];
\r
1601 ArgDescriptor *ad;
\r
1610 while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);
\r
1611 if (ch == NULLCHAR) break;
\r
1613 /* Comment to end of line */
\r
1615 while (ch != '\n' && ch != NULLCHAR) ch = get(cl);
\r
1617 } else if (ch == '/' || ch == '-') {
\r
1620 while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&
\r
1621 ch != '\n' && ch != '\t') {
\r
1627 for (ad = argDescriptors; ad->argName != NULL; ad++)
\r
1628 if (strcmp(ad->argName, argName + 1) == 0) break;
\r
1630 if (ad->argName == NULL)
\r
1631 ExitArgError("Unrecognized argument", argName);
\r
1633 } else if (ch == '@') {
\r
1634 /* Indirection file */
\r
1635 ad = &argDescriptorIndirection;
\r
1638 /* Positional argument */
\r
1639 ad = &argDescriptors[posarg++];
\r
1640 strcpy(argName, ad->argName);
\r
1643 if (ad->argType == ArgTrue) {
\r
1644 *(Boolean *) ad->argLoc = TRUE;
\r
1647 if (ad->argType == ArgFalse) {
\r
1648 *(Boolean *) ad->argLoc = FALSE;
\r
1652 while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
\r
1653 if (ch == NULLCHAR || ch == '\n') {
\r
1654 ExitArgError("No value provided for argument", argName);
\r
1658 // Quoting with { }. No characters have to (or can) be escaped.
\r
1659 // Thus the string cannot contain a '}' character.
\r
1679 } else if (ch == '\'' || ch == '"') {
\r
1680 // Quoting with ' ' or " ", with \ as escape character.
\r
1681 // Inconvenient for long strings that may contain Windows filenames.
\r
1698 if (ch == start) {
\r
1707 if (ad->argType == ArgFilename
\r
1708 || ad->argType == ArgSettingsFilename) {
\r
1714 ExitArgError("Incomplete \\ escape in value for", argName);
\r
1738 for (i = 0; i < 3; i++) {
\r
1739 if (ch >= '0' && ch <= '7') {
\r
1740 octval = octval*8 + (ch - '0');
\r
1747 *q++ = (char) octval;
\r
1758 while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {
\r
1765 switch (ad->argType) {
\r
1767 *(int *) ad->argLoc = atoi(argValue);
\r
1771 *(int *) ad->argLoc = atoi(argValue) + boardX; // [HGM] placement: translate stored relative to absolute
\r
1775 *(int *) ad->argLoc = atoi(argValue) + boardY; // (this is really kludgey, it should be done where used...)
\r
1779 *(int *) ad->argLoc = atoi(argValue);
\r
1780 EnsureOnScreen(&boardX, &boardY, minX, minY);
\r
1784 *(float *) ad->argLoc = (float) atof(argValue);
\r
1789 *(char **) ad->argLoc = strdup(argValue);
\r
1792 case ArgSettingsFilename:
\r
1794 char fullname[MSG_SIZ];
\r
1795 if (ParseSettingsFile(argValue, fullname)) {
\r
1796 if (ad->argLoc != NULL) {
\r
1797 *(char **) ad->argLoc = strdup(fullname);
\r
1800 if (ad->argLoc != NULL) {
\r
1802 ExitArgError("Failed to open indirection file", argValue);
\r
1809 switch (argValue[0]) {
\r
1812 *(Boolean *) ad->argLoc = TRUE;
\r
1816 *(Boolean *) ad->argLoc = FALSE;
\r
1819 ExitArgError("Unrecognized boolean argument value", argValue);
\r
1825 *(COLORREF *)ad->argLoc = ParseColorName(argValue);
\r
1828 case ArgAttribs: {
\r
1829 ColorClass cc = (ColorClass)ad->argLoc;
\r
1830 ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);
\r
1834 case ArgBoardSize:
\r
1835 *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);
\r
1839 ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);
\r
1842 case ArgCommSettings:
\r
1843 ParseCommSettings(argValue, &dcb);
\r
1847 ExitArgError("Unrecognized argument", argValue);
\r
1856 LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
\r
1858 HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
\r
1859 lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);
\r
1862 lf->lfEscapement = 0;
\r
1863 lf->lfOrientation = 0;
\r
1864 lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;
\r
1865 lf->lfItalic = mfp->italic;
\r
1866 lf->lfUnderline = mfp->underline;
\r
1867 lf->lfStrikeOut = mfp->strikeout;
\r
1868 lf->lfCharSet = DEFAULT_CHARSET;
\r
1869 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
1870 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
1871 lf->lfQuality = DEFAULT_QUALITY;
\r
1872 lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
\r
1873 strcpy(lf->lfFaceName, mfp->faceName);
\r
1877 CreateFontInMF(MyFont *mf)
\r
1879 LFfromMFP(&mf->lf, &mf->mfp);
\r
1880 if (mf->hf) DeleteObject(mf->hf);
\r
1881 mf->hf = CreateFontIndirect(&mf->lf);
\r
1885 SetDefaultTextAttribs()
\r
1888 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1889 ParseAttribs(&textAttribs[cc].color,
\r
1890 &textAttribs[cc].effects,
\r
1891 defaultTextAttribs[cc]);
\r
1896 SetDefaultSounds()
\r
1900 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1901 textAttribs[cc].sound.name = strdup("");
\r
1902 textAttribs[cc].sound.data = NULL;
\r
1904 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1905 sounds[sc].name = strdup("");
\r
1906 sounds[sc].data = NULL;
\r
1908 sounds[(int)SoundBell].name = strdup(SOUND_BELL);
\r
1916 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1917 MyLoadSound(&textAttribs[cc].sound);
\r
1919 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1920 MyLoadSound(&sounds[sc]);
\r
1925 InitAppData(LPSTR lpCmdLine)
\r
1928 char buf[ARG_MAX], currDir[MSG_SIZ];
\r
1931 programName = szAppName;
\r
1933 /* Initialize to defaults */
\r
1934 lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);
\r
1935 darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);
\r
1936 whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);
\r
1937 blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);
\r
1938 highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);
\r
1939 premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);
\r
1940 consoleBackgroundColor = ParseColorName(COLOR_BKGD);
\r
1941 SetDefaultTextAttribs();
\r
1942 SetDefaultSounds();
\r
1943 appData.movesPerSession = MOVES_PER_SESSION;
\r
1944 appData.initString = INIT_STRING;
\r
1945 appData.secondInitString = INIT_STRING;
\r
1946 appData.firstComputerString = COMPUTER_STRING;
\r
1947 appData.secondComputerString = COMPUTER_STRING;
\r
1948 appData.firstChessProgram = FIRST_CHESS_PROGRAM;
\r
1949 appData.secondChessProgram = SECOND_CHESS_PROGRAM;
\r
1950 appData.firstPlaysBlack = FALSE;
\r
1951 appData.noChessProgram = FALSE;
\r
1952 chessProgram = FALSE;
\r
1953 appData.firstHost = FIRST_HOST;
\r
1954 appData.secondHost = SECOND_HOST;
\r
1955 appData.firstDirectory = FIRST_DIRECTORY;
\r
1956 appData.secondDirectory = SECOND_DIRECTORY;
\r
1957 appData.bitmapDirectory = "";
\r
1958 appData.remoteShell = REMOTE_SHELL;
\r
1959 appData.remoteUser = "";
\r
1960 appData.timeDelay = TIME_DELAY;
\r
1961 appData.timeControl = TIME_CONTROL;
\r
1962 appData.timeIncrement = TIME_INCREMENT;
\r
1963 appData.icsActive = FALSE;
\r
1964 appData.icsHost = "";
\r
1965 appData.icsPort = ICS_PORT;
\r
1966 appData.icsCommPort = ICS_COMM_PORT;
\r
1967 appData.icsLogon = ICS_LOGON;
\r
1968 appData.icsHelper = "";
\r
1969 appData.useTelnet = FALSE;
\r
1970 appData.telnetProgram = TELNET_PROGRAM;
\r
1971 appData.gateway = "";
\r
1972 appData.loadGameFile = "";
\r
1973 appData.loadGameIndex = 0;
\r
1974 appData.saveGameFile = "";
\r
1975 appData.autoSaveGames = FALSE;
\r
1976 appData.loadPositionFile = "";
\r
1977 appData.loadPositionIndex = 1;
\r
1978 appData.savePositionFile = "";
\r
1979 appData.matchMode = FALSE;
\r
1980 appData.matchGames = 0;
\r
1981 appData.monoMode = FALSE;
\r
1982 appData.debugMode = FALSE;
\r
1983 appData.clockMode = TRUE;
\r
1984 boardSize = (BoardSize) -1; /* determine by screen size */
\r
1985 appData.Iconic = FALSE; /*unused*/
\r
1986 appData.searchTime = "";
\r
1987 appData.searchDepth = 0;
\r
1988 appData.showCoords = FALSE;
\r
1989 appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/
\r
1990 appData.autoCallFlag = FALSE;
\r
1991 appData.flipView = FALSE;
\r
1992 appData.autoFlipView = TRUE;
\r
1993 appData.cmailGameName = "";
\r
1994 appData.alwaysPromoteToQueen = FALSE;
\r
1995 appData.oldSaveStyle = FALSE;
\r
1996 appData.quietPlay = FALSE;
\r
1997 appData.showThinking = FALSE;
\r
1998 appData.ponderNextMove = TRUE;
\r
1999 appData.periodicUpdates = TRUE;
\r
2000 appData.popupExitMessage = TRUE;
\r
2001 appData.popupMoveErrors = FALSE;
\r
2002 appData.autoObserve = FALSE;
\r
2003 appData.autoComment = FALSE;
\r
2004 appData.animate = TRUE;
\r
2005 appData.animSpeed = 10;
\r
2006 appData.animateDragging = TRUE;
\r
2007 appData.highlightLastMove = TRUE;
\r
2008 appData.getMoveList = TRUE;
\r
2009 appData.testLegality = TRUE;
\r
2010 appData.premove = TRUE;
\r
2011 appData.premoveWhite = FALSE;
\r
2012 appData.premoveWhiteText = "";
\r
2013 appData.premoveBlack = FALSE;
\r
2014 appData.premoveBlackText = "";
\r
2015 appData.icsAlarm = TRUE;
\r
2016 appData.icsAlarmTime = 5000;
\r
2017 appData.autoRaiseBoard = TRUE;
\r
2018 appData.localLineEditing = TRUE;
\r
2019 appData.colorize = TRUE;
\r
2020 appData.reuseFirst = TRUE;
\r
2021 appData.reuseSecond = TRUE;
\r
2022 appData.blindfold = FALSE;
\r
2023 appData.icsEngineAnalyze = FALSE;
\r
2024 memset(&dcb, 0, sizeof(DCB)); // required by VS 2002 +
\r
2025 dcb.DCBlength = sizeof(DCB);
\r
2026 dcb.BaudRate = 9600;
\r
2027 dcb.fBinary = TRUE;
\r
2028 dcb.fParity = FALSE;
\r
2029 dcb.fOutxCtsFlow = FALSE;
\r
2030 dcb.fOutxDsrFlow = FALSE;
\r
2031 dcb.fDtrControl = DTR_CONTROL_ENABLE;
\r
2032 dcb.fDsrSensitivity = FALSE;
\r
2033 dcb.fTXContinueOnXoff = TRUE;
\r
2034 dcb.fOutX = FALSE;
\r
2036 dcb.fNull = FALSE;
\r
2037 dcb.fRtsControl = RTS_CONTROL_ENABLE;
\r
2038 dcb.fAbortOnError = FALSE;
\r
2040 dcb.Parity = SPACEPARITY;
\r
2041 dcb.StopBits = ONESTOPBIT;
\r
2042 settingsFileName = SETTINGS_FILE;
\r
2043 saveSettingsOnExit = TRUE;
\r
2044 boardX = CW_USEDEFAULT;
\r
2045 boardY = CW_USEDEFAULT;
\r
2046 analysisX = CW_USEDEFAULT;
\r
2047 analysisY = CW_USEDEFAULT;
\r
2048 analysisW = CW_USEDEFAULT;
\r
2049 analysisH = CW_USEDEFAULT;
\r
2050 commentX = CW_USEDEFAULT;
\r
2051 commentY = CW_USEDEFAULT;
\r
2052 commentW = CW_USEDEFAULT;
\r
2053 commentH = CW_USEDEFAULT;
\r
2054 editTagsX = CW_USEDEFAULT;
\r
2055 editTagsY = CW_USEDEFAULT;
\r
2056 editTagsW = CW_USEDEFAULT;
\r
2057 editTagsH = CW_USEDEFAULT;
\r
2058 icsTextMenuString = ICS_TEXT_MENU_DEFAULT;
\r
2059 icsNames = ICS_NAMES;
\r
2060 firstChessProgramNames = FCP_NAMES;
\r
2061 secondChessProgramNames = SCP_NAMES;
\r
2062 appData.initialMode = "";
\r
2063 appData.variant = "normal";
\r
2064 appData.firstProtocolVersion = PROTOVER;
\r
2065 appData.secondProtocolVersion = PROTOVER;
\r
2066 appData.showButtonBar = TRUE;
\r
2068 /* [AS] New properties (see comments in header file) */
\r
2069 appData.firstScoreIsAbsolute = FALSE;
\r
2070 appData.secondScoreIsAbsolute = FALSE;
\r
2071 appData.saveExtendedInfoInPGN = FALSE;
\r
2072 appData.hideThinkingFromHuman = FALSE;
\r
2073 appData.liteBackTextureFile = "";
\r
2074 appData.liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
2075 appData.darkBackTextureFile = "";
\r
2076 appData.darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
2077 appData.renderPiecesWithFont = "";
\r
2078 appData.fontToPieceTable = "";
\r
2079 appData.fontBackColorWhite = 0;
\r
2080 appData.fontForeColorWhite = 0;
\r
2081 appData.fontBackColorBlack = 0;
\r
2082 appData.fontForeColorBlack = 0;
\r
2083 appData.fontPieceSize = 80;
\r
2084 appData.overrideLineGap = 1;
\r
2085 appData.adjudicateLossThreshold = 0;
\r
2086 appData.delayBeforeQuit = 0;
\r
2087 appData.delayAfterQuit = 0;
\r
2088 appData.nameOfDebugFile = "winboard.debug";
\r
2089 appData.pgnEventHeader = "Computer Chess Game";
\r
2090 appData.defaultFrcPosition = -1;
\r
2091 appData.gameListTags = GLT_DEFAULT_TAGS;
\r
2092 appData.saveOutOfBookInfo = TRUE;
\r
2093 appData.showEvalInMoveHistory = TRUE;
\r
2094 appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );
\r
2095 appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );
\r
2096 appData.highlightMoveWithArrow = FALSE;
\r
2097 appData.highlightArrowColor = ParseColorName( "#FFFF80" );
\r
2098 appData.useStickyWindows = TRUE;
\r
2099 appData.adjudicateDrawMoves = 0;
\r
2100 appData.autoDisplayComment = TRUE;
\r
2101 appData.autoDisplayTags = TRUE;
\r
2102 appData.firstIsUCI = FALSE;
\r
2103 appData.secondIsUCI = FALSE;
\r
2104 appData.firstHasOwnBookUCI = TRUE;
\r
2105 appData.secondHasOwnBookUCI = TRUE;
\r
2106 appData.polyglotDir = "";
\r
2107 appData.usePolyglotBook = FALSE;
\r
2108 appData.polyglotBook = "";
\r
2109 appData.defaultHashSize = 64;
\r
2110 appData.defaultCacheSizeEGTB = 4;
\r
2111 appData.defaultPathEGTB = "c:\\egtb";
\r
2112 appData.firstOptions = "";
\r
2113 appData.secondOptions = "";
\r
2115 InitWindowPlacement( &wpGameList );
\r
2116 InitWindowPlacement( &wpMoveHistory );
\r
2117 InitWindowPlacement( &wpEvalGraph );
\r
2118 InitWindowPlacement( &wpEngineOutput );
\r
2119 InitWindowPlacement( &wpConsole );
\r
2121 /* [HGM] User-selectable board size, adjudication control, miscellaneous */
\r
2122 appData.NrFiles = -1;
\r
2123 appData.NrRanks = -1;
\r
2124 appData.holdingsSize = -1;
\r
2125 appData.testClaims = FALSE;
\r
2126 appData.checkMates = FALSE;
\r
2127 appData.materialDraws= FALSE;
\r
2128 appData.trivialDraws = FALSE;
\r
2129 appData.ruleMoves = 51;
\r
2130 appData.drawRepeats = 6;
\r
2131 appData.matchPause = 10000;
\r
2132 appData.alphaRank = FALSE;
\r
2133 appData.allWhite = FALSE;
\r
2134 appData.upsideDown = FALSE;
\r
2135 appData.serverPause = 15;
\r
2136 appData.serverMovesName = NULL;
\r
2137 appData.suppressLoadMoves = FALSE;
\r
2138 appData.firstTimeOdds = 1;
\r
2139 appData.secondTimeOdds = 1;
\r
2140 appData.firstAccumulateTC = 1; // combine previous and current sessions
\r
2141 appData.secondAccumulateTC = 1;
\r
2142 appData.firstNPS = -1; // [HGM] nps: use wall-clock time
\r
2143 appData.secondNPS = -1;
\r
2144 appData.engineComments = 1;
\r
2145 appData.smpCores = 1; // [HGM] SMP: max nr of cores
\r
2146 appData.egtFormats = "";
\r
2149 appData.zippyTalk = ZIPPY_TALK;
\r
2150 appData.zippyPlay = ZIPPY_PLAY;
\r
2151 appData.zippyLines = ZIPPY_LINES;
\r
2152 appData.zippyPinhead = ZIPPY_PINHEAD;
\r
2153 appData.zippyPassword = ZIPPY_PASSWORD;
\r
2154 appData.zippyPassword2 = ZIPPY_PASSWORD2;
\r
2155 appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;
\r
2156 appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;
\r
2157 appData.zippyUseI = ZIPPY_USE_I;
\r
2158 appData.zippyBughouse = ZIPPY_BUGHOUSE;
\r
2159 appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;
\r
2160 appData.zippyGameEnd = ZIPPY_GAME_END;
\r
2161 appData.zippyGameStart = ZIPPY_GAME_START;
\r
2162 appData.zippyAdjourn = ZIPPY_ADJOURN;
\r
2163 appData.zippyAbort = ZIPPY_ABORT;
\r
2164 appData.zippyVariants = ZIPPY_VARIANTS;
\r
2165 appData.zippyMaxGames = ZIPPY_MAX_GAMES;
\r
2166 appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;
\r
2169 /* Point font array elements to structures and
\r
2170 parse default font names */
\r
2171 for (i=0; i<NUM_FONTS; i++) {
\r
2172 for (j=0; j<NUM_SIZES; j++) {
\r
2173 font[j][i] = &fontRec[j][i];
\r
2174 ParseFontName(font[j][i]->def, &font[j][i]->mfp);
\r
2178 /* Parse default settings file if any */
\r
2179 if (ParseSettingsFile(settingsFileName, buf)) {
\r
2180 settingsFileName = strdup(buf);
\r
2183 /* Parse command line */
\r
2184 ParseArgs(StringGet, &lpCmdLine);
\r
2186 /* [HGM] make sure board size is acceptable */
\r
2187 if(appData.NrFiles > BOARD_SIZE ||
\r
2188 appData.NrRanks > BOARD_SIZE )
\r
2189 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
2191 /* [HGM] After parsing the options from the .ini file, and overruling them
\r
2192 * with options from the command line, we now make an even higher priority
\r
2193 * overrule by WB options attached to the engine command line. This so that
\r
2194 * tournament managers can use WB options (such as /timeOdds) that follow
\r
2197 if(appData.firstChessProgram != NULL) {
\r
2198 char *p = StrStr(appData.firstChessProgram, "WBopt");
\r
2199 static char *f = "first";
\r
2200 char buf[MSG_SIZ], *q = buf;
\r
2201 if(p != NULL) { // engine command line contains WinBoard options
\r
2202 sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"
\r
2203 ParseArgs(StringGet, &q);
\r
2204 p[-1] = 0; // cut them offengine command line
\r
2207 // now do same for second chess program
\r
2208 if(appData.secondChessProgram != NULL) {
\r
2209 char *p = StrStr(appData.secondChessProgram, "WBopt");
\r
2210 static char *s = "second";
\r
2211 char buf[MSG_SIZ], *q = buf;
\r
2212 if(p != NULL) { // engine command line contains WinBoard options
\r
2213 sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"
\r
2214 ParseArgs(StringGet, &q);
\r
2215 p[-1] = 0; // cut them offengine command line
\r
2220 /* Propagate options that affect others */
\r
2221 if (appData.matchMode || appData.matchGames) chessProgram = TRUE;
\r
2222 if (appData.icsActive || appData.noChessProgram) {
\r
2223 chessProgram = FALSE; /* not local chess program mode */
\r
2226 /* Open startup dialog if needed */
\r
2227 if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||
\r
2228 (appData.icsActive && *appData.icsHost == NULLCHAR) ||
\r
2229 (chessProgram && (*appData.firstChessProgram == NULLCHAR ||
\r
2230 *appData.secondChessProgram == NULLCHAR))) {
\r
2233 lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);
\r
2234 DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);
\r
2235 FreeProcInstance(lpProc);
\r
2238 /* Make sure save files land in the right (?) directory */
\r
2239 if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {
\r
2240 appData.saveGameFile = strdup(buf);
\r
2242 if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {
\r
2243 appData.savePositionFile = strdup(buf);
\r
2246 /* Finish initialization for fonts and sounds */
\r
2247 for (i=0; i<NUM_FONTS; i++) {
\r
2248 for (j=0; j<NUM_SIZES; j++) {
\r
2249 CreateFontInMF(font[j][i]);
\r
2252 /* xboard, and older WinBoards, controlled the move sound with the
\r
2253 appData.ringBellAfterMoves option. In the current WinBoard, we
\r
2254 always turn the option on (so that the backend will call us),
\r
2255 then let the user turn the sound off by setting it to silence if
\r
2256 desired. To accommodate old winboard.ini files saved by old
\r
2257 versions of WinBoard, we also turn off the sound if the option
\r
2258 was initially set to false. */
\r
2259 if (!appData.ringBellAfterMoves) {
\r
2260 sounds[(int)SoundMove].name = strdup("");
\r
2261 appData.ringBellAfterMoves = TRUE;
\r
2263 GetCurrentDirectory(MSG_SIZ, currDir);
\r
2264 SetCurrentDirectory(installDir);
\r
2266 SetCurrentDirectory(currDir);
\r
2268 p = icsTextMenuString;
\r
2269 if (p[0] == '@') {
\r
2270 FILE* f = fopen(p + 1, "r");
\r
2272 DisplayFatalError(p + 1, errno, 2);
\r
2275 i = fread(buf, 1, sizeof(buf)-1, f);
\r
2277 buf[i] = NULLCHAR;
\r
2280 ParseIcsTextMenu(strdup(p));
\r
2287 HMENU hmenu = GetMenu(hwndMain);
\r
2289 (void) EnableMenuItem(hmenu, IDM_CommPort,
\r
2290 MF_BYCOMMAND|((appData.icsActive &&
\r
2291 *appData.icsCommPort != NULLCHAR) ?
\r
2292 MF_ENABLED : MF_GRAYED));
\r
2293 (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,
\r
2294 MF_BYCOMMAND|(saveSettingsOnExit ?
\r
2295 MF_CHECKED : MF_UNCHECKED));
\r
2300 SaveSettings(char* name)
\r
2303 ArgDescriptor *ad;
\r
2304 WINDOWPLACEMENT wp;
\r
2305 char dir[MSG_SIZ];
\r
2307 if (!hwndMain) return;
\r
2309 GetCurrentDirectory(MSG_SIZ, dir);
\r
2310 SetCurrentDirectory(installDir);
\r
2311 f = fopen(name, "w");
\r
2312 SetCurrentDirectory(dir);
\r
2314 DisplayError(name, errno);
\r
2317 fprintf(f, ";\n");
\r
2318 fprintf(f, "; %s Save Settings file\n", PACKAGE_STRING);
\r
2319 fprintf(f, ";\n");
\r
2320 fprintf(f, "; You can edit the values of options that are already set in this file,\n");
\r
2321 fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");
\r
2322 fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");
\r
2323 fprintf(f, ";\n");
\r
2325 wp.length = sizeof(WINDOWPLACEMENT);
\r
2326 GetWindowPlacement(hwndMain, &wp);
\r
2327 boardX = wp.rcNormalPosition.left;
\r
2328 boardY = wp.rcNormalPosition.top;
\r
2330 if (hwndConsole) {
\r
2331 GetWindowPlacement(hwndConsole, &wp);
\r
2332 wpConsole.x = wp.rcNormalPosition.left;
\r
2333 wpConsole.y = wp.rcNormalPosition.top;
\r
2334 wpConsole.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2335 wpConsole.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2338 if (analysisDialog) {
\r
2339 GetWindowPlacement(analysisDialog, &wp);
\r
2340 analysisX = wp.rcNormalPosition.left;
\r
2341 analysisY = wp.rcNormalPosition.top;
\r
2342 analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2343 analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2346 if (commentDialog) {
\r
2347 GetWindowPlacement(commentDialog, &wp);
\r
2348 commentX = wp.rcNormalPosition.left;
\r
2349 commentY = wp.rcNormalPosition.top;
\r
2350 commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2351 commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2354 if (editTagsDialog) {
\r
2355 GetWindowPlacement(editTagsDialog, &wp);
\r
2356 editTagsX = wp.rcNormalPosition.left;
\r
2357 editTagsY = wp.rcNormalPosition.top;
\r
2358 editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2359 editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2362 if (gameListDialog) {
\r
2363 GetWindowPlacement(gameListDialog, &wp);
\r
2364 wpGameList.x = wp.rcNormalPosition.left;
\r
2365 wpGameList.y = wp.rcNormalPosition.top;
\r
2366 wpGameList.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2367 wpGameList.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2370 /* [AS] Move history */
\r
2371 wpMoveHistory.visible = MoveHistoryIsUp();
\r
2373 if( moveHistoryDialog ) {
\r
2374 GetWindowPlacement(moveHistoryDialog, &wp);
\r
2375 wpMoveHistory.x = wp.rcNormalPosition.left;
\r
2376 wpMoveHistory.y = wp.rcNormalPosition.top;
\r
2377 wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2378 wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2381 /* [AS] Eval graph */
\r
2382 wpEvalGraph.visible = EvalGraphIsUp();
\r
2384 if( evalGraphDialog ) {
\r
2385 GetWindowPlacement(evalGraphDialog, &wp);
\r
2386 wpEvalGraph.x = wp.rcNormalPosition.left;
\r
2387 wpEvalGraph.y = wp.rcNormalPosition.top;
\r
2388 wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2389 wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2392 /* [AS] Engine output */
\r
2393 wpEngineOutput.visible = EngineOutputIsUp();
\r
2395 if( engineOutputDialog ) {
\r
2396 GetWindowPlacement(engineOutputDialog, &wp);
\r
2397 wpEngineOutput.x = wp.rcNormalPosition.left;
\r
2398 wpEngineOutput.y = wp.rcNormalPosition.top;
\r
2399 wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2400 wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2403 for (ad = argDescriptors; ad->argName != NULL; ad++) {
\r
2404 if (!ad->save) continue;
\r
2405 switch (ad->argType) {
\r
2408 char *p = *(char **)ad->argLoc;
\r
2409 if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {
\r
2410 /* Quote multiline values or \-containing values
\r
2411 with { } if possible */
\r
2412 fprintf(f, "/%s={%s}\n", ad->argName, p);
\r
2414 /* Else quote with " " */
\r
2415 fprintf(f, "/%s=\"", ad->argName);
\r
2417 if (*p == '\n') fprintf(f, "\n");
\r
2418 else if (*p == '\r') fprintf(f, "\\r");
\r
2419 else if (*p == '\t') fprintf(f, "\\t");
\r
2420 else if (*p == '\b') fprintf(f, "\\b");
\r
2421 else if (*p == '\f') fprintf(f, "\\f");
\r
2422 else if (*p < ' ') fprintf(f, "\\%03o", *p);
\r
2423 else if (*p == '\"') fprintf(f, "\\\"");
\r
2424 else if (*p == '\\') fprintf(f, "\\\\");
\r
2428 fprintf(f, "\"\n");
\r
2434 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);
\r
2437 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardX); // [HGM] placement: stor relative value
\r
2440 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardY);
\r
2443 fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);
\r
2446 fprintf(f, "/%s=%s\n", ad->argName,
\r
2447 (*(Boolean *)ad->argLoc) ? "true" : "false");
\r
2450 if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2453 if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2457 COLORREF color = *(COLORREF *)ad->argLoc;
\r
2458 fprintf(f, "/%s=#%02lx%02lx%02lx\n", ad->argName,
\r
2459 color&0xff, (color>>8)&0xff, (color>>16)&0xff);
\r
2464 MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];
\r
2465 fprintf(f, "/%s=\"%s%s%s%s%s#%02lx%02lx%02lx\"\n", ad->argName,
\r
2466 (ta->effects & CFE_BOLD) ? "b" : "",
\r
2467 (ta->effects & CFE_ITALIC) ? "i" : "",
\r
2468 (ta->effects & CFE_UNDERLINE) ? "u" : "",
\r
2469 (ta->effects & CFE_STRIKEOUT) ? "s" : "",
\r
2470 (ta->effects) ? " " : "",
\r
2471 ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);
\r
2475 if (strchr(*(char **)ad->argLoc, '\"')) {
\r
2476 fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);
\r
2478 fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);
\r
2481 case ArgBoardSize:
\r
2482 fprintf(f, "/%s=%s\n", ad->argName,
\r
2483 sizeInfo[*(BoardSize *)ad->argLoc].name);
\r
2488 for (bs=0; bs<NUM_SIZES; bs++) {
\r
2489 MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;
\r
2490 fprintf(f, "/size=%s ", sizeInfo[bs].name);
\r
2491 fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n",
\r
2492 ad->argName, mfp->faceName, mfp->pointSize,
\r
2493 mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",
\r
2494 mfp->bold ? "b" : "",
\r
2495 mfp->italic ? "i" : "",
\r
2496 mfp->underline ? "u" : "",
\r
2497 mfp->strikeout ? "s" : "");
\r
2501 case ArgCommSettings:
\r
2502 PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);
\r
2504 case ArgSettingsFilename: ;
\r
2512 /*---------------------------------------------------------------------------*\
\r
2514 * GDI board drawing routines
\r
2516 \*---------------------------------------------------------------------------*/
\r
2518 /* [AS] Draw square using background texture */
\r
2519 static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )
\r
2524 return; /* Should never happen! */
\r
2527 SetGraphicsMode( dst, GM_ADVANCED );
\r
2534 /* X reflection */
\r
2539 x.eDx = (FLOAT) dw + dx - 1;
\r
2542 SetWorldTransform( dst, &x );
\r
2545 /* Y reflection */
\r
2551 x.eDy = (FLOAT) dh + dy - 1;
\r
2553 SetWorldTransform( dst, &x );
\r
2561 x.eDx = (FLOAT) dx;
\r
2562 x.eDy = (FLOAT) dy;
\r
2565 SetWorldTransform( dst, &x );
\r
2569 BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );
\r
2577 SetWorldTransform( dst, &x );
\r
2579 ModifyWorldTransform( dst, 0, MWT_IDENTITY );
\r
2582 /* [AS] [HGM] Make room for more piece types, so all pieces can be different */
\r
2584 PM_WP = (int) WhitePawn,
\r
2585 PM_WN = (int) WhiteKnight,
\r
2586 PM_WB = (int) WhiteBishop,
\r
2587 PM_WR = (int) WhiteRook,
\r
2588 PM_WQ = (int) WhiteQueen,
\r
2589 PM_WF = (int) WhiteFerz,
\r
2590 PM_WW = (int) WhiteWazir,
\r
2591 PM_WE = (int) WhiteAlfil,
\r
2592 PM_WM = (int) WhiteMan,
\r
2593 PM_WO = (int) WhiteCannon,
\r
2594 PM_WU = (int) WhiteUnicorn,
\r
2595 PM_WH = (int) WhiteNightrider,
\r
2596 PM_WA = (int) WhiteAngel,
\r
2597 PM_WC = (int) WhiteMarshall,
\r
2598 PM_WAB = (int) WhiteCardinal,
\r
2599 PM_WD = (int) WhiteDragon,
\r
2600 PM_WL = (int) WhiteLance,
\r
2601 PM_WS = (int) WhiteCobra,
\r
2602 PM_WV = (int) WhiteFalcon,
\r
2603 PM_WSG = (int) WhiteSilver,
\r
2604 PM_WG = (int) WhiteGrasshopper,
\r
2605 PM_WK = (int) WhiteKing,
\r
2606 PM_BP = (int) BlackPawn,
\r
2607 PM_BN = (int) BlackKnight,
\r
2608 PM_BB = (int) BlackBishop,
\r
2609 PM_BR = (int) BlackRook,
\r
2610 PM_BQ = (int) BlackQueen,
\r
2611 PM_BF = (int) BlackFerz,
\r
2612 PM_BW = (int) BlackWazir,
\r
2613 PM_BE = (int) BlackAlfil,
\r
2614 PM_BM = (int) BlackMan,
\r
2615 PM_BO = (int) BlackCannon,
\r
2616 PM_BU = (int) BlackUnicorn,
\r
2617 PM_BH = (int) BlackNightrider,
\r
2618 PM_BA = (int) BlackAngel,
\r
2619 PM_BC = (int) BlackMarshall,
\r
2620 PM_BG = (int) BlackGrasshopper,
\r
2621 PM_BAB = (int) BlackCardinal,
\r
2622 PM_BD = (int) BlackDragon,
\r
2623 PM_BL = (int) BlackLance,
\r
2624 PM_BS = (int) BlackCobra,
\r
2625 PM_BV = (int) BlackFalcon,
\r
2626 PM_BSG = (int) BlackSilver,
\r
2627 PM_BK = (int) BlackKing
\r
2630 static HFONT hPieceFont = NULL;
\r
2631 static HBITMAP hPieceMask[(int) EmptySquare];
\r
2632 static HBITMAP hPieceFace[(int) EmptySquare];
\r
2633 static int fontBitmapSquareSize = 0;
\r
2634 static char pieceToFontChar[(int) EmptySquare] =
\r
2635 { 'p', 'n', 'b', 'r', 'q',
\r
2636 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',
\r
2637 'k', 'o', 'm', 'v', 't', 'w',
\r
2638 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',
\r
2641 extern BOOL SetCharTable( char *table, const char * map );
\r
2642 /* [HGM] moved to backend.c */
\r
2644 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )
\r
2647 BYTE r1 = GetRValue( color );
\r
2648 BYTE g1 = GetGValue( color );
\r
2649 BYTE b1 = GetBValue( color );
\r
2655 /* Create a uniform background first */
\r
2656 hbrush = CreateSolidBrush( color );
\r
2657 SetRect( &rc, 0, 0, squareSize, squareSize );
\r
2658 FillRect( hdc, &rc, hbrush );
\r
2659 DeleteObject( hbrush );
\r
2662 /* Vertical gradient, good for pawn, knight and rook, less for queen and king */
\r
2663 int steps = squareSize / 2;
\r
2666 for( i=0; i<steps; i++ ) {
\r
2667 BYTE r = r1 - (r1-r2) * i / steps;
\r
2668 BYTE g = g1 - (g1-g2) * i / steps;
\r
2669 BYTE b = b1 - (b1-b2) * i / steps;
\r
2671 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2672 SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );
\r
2673 FillRect( hdc, &rc, hbrush );
\r
2674 DeleteObject(hbrush);
\r
2677 else if( mode == 2 ) {
\r
2678 /* Diagonal gradient, good more or less for every piece */
\r
2679 POINT triangle[3];
\r
2680 HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );
\r
2681 HBRUSH hbrush_old;
\r
2682 int steps = squareSize;
\r
2685 triangle[0].x = squareSize - steps;
\r
2686 triangle[0].y = squareSize;
\r
2687 triangle[1].x = squareSize;
\r
2688 triangle[1].y = squareSize;
\r
2689 triangle[2].x = squareSize;
\r
2690 triangle[2].y = squareSize - steps;
\r
2692 for( i=0; i<steps; i++ ) {
\r
2693 BYTE r = r1 - (r1-r2) * i / steps;
\r
2694 BYTE g = g1 - (g1-g2) * i / steps;
\r
2695 BYTE b = b1 - (b1-b2) * i / steps;
\r
2697 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2698 hbrush_old = SelectObject( hdc, hbrush );
\r
2699 Polygon( hdc, triangle, 3 );
\r
2700 SelectObject( hdc, hbrush_old );
\r
2701 DeleteObject(hbrush);
\r
2706 SelectObject( hdc, hpen );
\r
2711 [AS] The method I use to create the bitmaps it a bit tricky, but it
\r
2712 seems to work ok. The main problem here is to find the "inside" of a chess
\r
2713 piece: follow the steps as explained below.
\r
2715 static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
\r
2719 COLORREF chroma = RGB(0xFF,0x00,0xFF);
\r
2723 int backColor = whitePieceColor;
\r
2724 int foreColor = blackPieceColor;
\r
2726 if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {
\r
2727 backColor = appData.fontBackColorWhite;
\r
2728 foreColor = appData.fontForeColorWhite;
\r
2730 else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {
\r
2731 backColor = appData.fontBackColorBlack;
\r
2732 foreColor = appData.fontForeColorBlack;
\r
2736 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2738 hbm_old = SelectObject( hdc, hbm );
\r
2742 rc.right = squareSize;
\r
2743 rc.bottom = squareSize;
\r
2745 /* Step 1: background is now black */
\r
2746 FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );
\r
2748 GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );
\r
2750 pt.x = (squareSize - sz.cx) / 2;
\r
2751 pt.y = (squareSize - sz.cy) / 2;
\r
2753 SetBkMode( hdc, TRANSPARENT );
\r
2754 SetTextColor( hdc, chroma );
\r
2755 /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */
\r
2756 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2758 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
\r
2759 /* Step 3: the area outside the piece is filled with white */
\r
2760 // FloodFill( hdc, 0, 0, chroma );
\r
2761 ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );
\r
2762 ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big
\r
2763 ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );
\r
2764 ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );
\r
2765 SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
\r
2767 Step 4: this is the tricky part, the area inside the piece is filled with black,
\r
2768 but if the start point is not inside the piece we're lost!
\r
2769 There should be a better way to do this... if we could create a region or path
\r
2770 from the fill operation we would be fine for example.
\r
2772 // FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );
\r
2773 ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );
\r
2775 { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */
\r
2776 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2777 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2779 SelectObject( dc2, bm2 );
\r
2780 BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy
\r
2781 BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2782 BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2783 BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2784 BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2787 DeleteObject( bm2 );
\r
2790 SetTextColor( hdc, 0 );
\r
2792 Step 5: some fonts have "disconnected" areas that are skipped by the fill:
\r
2793 draw the piece again in black for safety.
\r
2795 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2797 SelectObject( hdc, hbm_old );
\r
2799 if( hPieceMask[index] != NULL ) {
\r
2800 DeleteObject( hPieceMask[index] );
\r
2803 hPieceMask[index] = hbm;
\r
2806 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2808 SelectObject( hdc, hbm );
\r
2811 HDC dc1 = CreateCompatibleDC( hdc_window );
\r
2812 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2813 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2815 SelectObject( dc1, hPieceMask[index] );
\r
2816 SelectObject( dc2, bm2 );
\r
2817 FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );
\r
2818 BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );
\r
2821 Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves
\r
2822 the piece background and deletes (makes transparent) the rest.
\r
2823 Thanks to that mask, we are free to paint the background with the greates
\r
2824 freedom, as we'll be able to mask off the unwanted parts when finished.
\r
2825 We use this, to make gradients and give the pieces a "roundish" look.
\r
2827 SetPieceBackground( hdc, backColor, 2 );
\r
2828 BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );
\r
2832 DeleteObject( bm2 );
\r
2835 SetTextColor( hdc, foreColor );
\r
2836 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2838 SelectObject( hdc, hbm_old );
\r
2840 if( hPieceFace[index] != NULL ) {
\r
2841 DeleteObject( hPieceFace[index] );
\r
2844 hPieceFace[index] = hbm;
\r
2847 static int TranslatePieceToFontPiece( int piece )
\r
2877 case BlackMarshall:
\r
2881 case BlackNightrider:
\r
2887 case BlackUnicorn:
\r
2891 case BlackGrasshopper:
\r
2903 case BlackCardinal:
\r
2910 case WhiteMarshall:
\r
2914 case WhiteNightrider:
\r
2920 case WhiteUnicorn:
\r
2924 case WhiteGrasshopper:
\r
2936 case WhiteCardinal:
\r
2945 void CreatePiecesFromFont()
\r
2948 HDC hdc_window = NULL;
\r
2954 if( fontBitmapSquareSize < 0 ) {
\r
2955 /* Something went seriously wrong in the past: do not try to recreate fonts! */
\r
2959 if( appData.renderPiecesWithFont == NULL || appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {
\r
2960 fontBitmapSquareSize = -1;
\r
2964 if( fontBitmapSquareSize != squareSize ) {
\r
2965 hdc_window = GetDC( hwndMain );
\r
2966 hdc = CreateCompatibleDC( hdc_window );
\r
2968 if( hPieceFont != NULL ) {
\r
2969 DeleteObject( hPieceFont );
\r
2972 for( i=0; i<=(int)BlackKing; i++ ) {
\r
2973 hPieceMask[i] = NULL;
\r
2974 hPieceFace[i] = NULL;
\r
2980 if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {
\r
2981 fontHeight = appData.fontPieceSize;
\r
2984 fontHeight = (fontHeight * squareSize) / 100;
\r
2986 lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
\r
2988 lf.lfEscapement = 0;
\r
2989 lf.lfOrientation = 0;
\r
2990 lf.lfWeight = FW_NORMAL;
\r
2992 lf.lfUnderline = 0;
\r
2993 lf.lfStrikeOut = 0;
\r
2994 lf.lfCharSet = DEFAULT_CHARSET;
\r
2995 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
2996 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
2997 lf.lfQuality = PROOF_QUALITY;
\r
2998 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
\r
2999 strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );
\r
3000 lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';
\r
3002 hPieceFont = CreateFontIndirect( &lf );
\r
3004 if( hPieceFont == NULL ) {
\r
3005 fontBitmapSquareSize = -2;
\r
3008 /* Setup font-to-piece character table */
\r
3009 if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {
\r
3010 /* No (or wrong) global settings, try to detect the font */
\r
3011 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {
\r
3013 SetCharTable(pieceToFontChar, "phbrqkojntwl");
\r
3015 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {
\r
3016 /* DiagramTT* family */
\r
3017 SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");
\r
3019 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {
\r
3020 /* Fairy symbols */
\r
3021 SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
\r
3023 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {
\r
3024 /* Good Companion (Some characters get warped as literal :-( */
\r
3025 char s[] = "1cmWG0ñueOS¯®oYI23wgQU";
\r
3026 s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;
\r
3027 SetCharTable(pieceToFontChar, s);
\r
3030 /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */
\r
3031 SetCharTable(pieceToFontChar, "pnbrqkomvtwl");
\r
3035 /* Create bitmaps */
\r
3036 hfont_old = SelectObject( hdc, hPieceFont );
\r
3038 CreatePieceMaskFromFont( hdc_window, hdc, PM_WP );
\r
3039 CreatePieceMaskFromFont( hdc_window, hdc, PM_WN );
\r
3040 CreatePieceMaskFromFont( hdc_window, hdc, PM_WB );
\r
3041 CreatePieceMaskFromFont( hdc_window, hdc, PM_WR );
\r
3042 CreatePieceMaskFromFont( hdc_window, hdc, PM_WQ );
\r
3043 CreatePieceMaskFromFont( hdc_window, hdc, PM_WK );
\r
3044 CreatePieceMaskFromFont( hdc_window, hdc, PM_BP );
\r
3045 CreatePieceMaskFromFont( hdc_window, hdc, PM_BN );
\r
3046 CreatePieceMaskFromFont( hdc_window, hdc, PM_BB );
\r
3047 CreatePieceMaskFromFont( hdc_window, hdc, PM_BR );
\r
3048 CreatePieceMaskFromFont( hdc_window, hdc, PM_BQ );
\r
3049 CreatePieceMaskFromFont( hdc_window, hdc, PM_BK );
\r
3051 CreatePieceMaskFromFont( hdc_window, hdc, PM_WA );
\r
3052 CreatePieceMaskFromFont( hdc_window, hdc, PM_WC );
\r
3053 CreatePieceMaskFromFont( hdc_window, hdc, PM_WF );
\r
3054 CreatePieceMaskFromFont( hdc_window, hdc, PM_WH );
\r
3055 CreatePieceMaskFromFont( hdc_window, hdc, PM_WE );
\r
3056 CreatePieceMaskFromFont( hdc_window, hdc, PM_WW );
\r
3057 CreatePieceMaskFromFont( hdc_window, hdc, PM_WU );
\r
3058 CreatePieceMaskFromFont( hdc_window, hdc, PM_WO );
\r
3059 CreatePieceMaskFromFont( hdc_window, hdc, PM_WG );
\r
3060 CreatePieceMaskFromFont( hdc_window, hdc, PM_WM );
\r
3061 CreatePieceMaskFromFont( hdc_window, hdc, PM_WSG );
\r
3062 CreatePieceMaskFromFont( hdc_window, hdc, PM_WV );
\r
3063 CreatePieceMaskFromFont( hdc_window, hdc, PM_WAB );
\r
3064 CreatePieceMaskFromFont( hdc_window, hdc, PM_WD );
\r
3065 CreatePieceMaskFromFont( hdc_window, hdc, PM_WL );
\r
3066 CreatePieceMaskFromFont( hdc_window, hdc, PM_WS );
\r
3067 CreatePieceMaskFromFont( hdc_window, hdc, PM_BA );
\r
3068 CreatePieceMaskFromFont( hdc_window, hdc, PM_BC );
\r
3069 CreatePieceMaskFromFont( hdc_window, hdc, PM_BF );
\r
3070 CreatePieceMaskFromFont( hdc_window, hdc, PM_BH );
\r
3071 CreatePieceMaskFromFont( hdc_window, hdc, PM_BE );
\r
3072 CreatePieceMaskFromFont( hdc_window, hdc, PM_BW );
\r
3073 CreatePieceMaskFromFont( hdc_window, hdc, PM_BU );
\r
3074 CreatePieceMaskFromFont( hdc_window, hdc, PM_BO );
\r
3075 CreatePieceMaskFromFont( hdc_window, hdc, PM_BG );
\r
3076 CreatePieceMaskFromFont( hdc_window, hdc, PM_BM );
\r
3077 CreatePieceMaskFromFont( hdc_window, hdc, PM_BSG );
\r
3078 CreatePieceMaskFromFont( hdc_window, hdc, PM_BV );
\r
3079 CreatePieceMaskFromFont( hdc_window, hdc, PM_BAB );
\r
3080 CreatePieceMaskFromFont( hdc_window, hdc, PM_BD );
\r
3081 CreatePieceMaskFromFont( hdc_window, hdc, PM_BL );
\r
3082 CreatePieceMaskFromFont( hdc_window, hdc, PM_BS );
\r
3084 for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */
\r
3085 if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */
\r
3086 CreatePieceMaskFromFont( hdc_window, hdc, i );
\r
3088 SelectObject( hdc, hfont_old );
\r
3090 fontBitmapSquareSize = squareSize;
\r
3094 if( hdc != NULL ) {
\r
3098 if( hdc_window != NULL ) {
\r
3099 ReleaseDC( hwndMain, hdc_window );
\r
3104 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)
\r
3108 sprintf(name, "%s%d%s", piece, squareSize, suffix);
\r
3109 if (gameInfo.event &&
\r
3110 strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&
\r
3111 strcmp(name, "k80s") == 0) {
\r
3112 strcpy(name, "tim");
\r
3114 return LoadBitmap(hinst, name);
\r
3118 /* Insert a color into the program's logical palette
\r
3119 structure. This code assumes the given color is
\r
3120 the result of the RGB or PALETTERGB macro, and it
\r
3121 knows how those macros work (which is documented).
\r
3124 InsertInPalette(COLORREF color)
\r
3126 LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);
\r
3128 if (pLogPal->palNumEntries++ >= PALETTESIZE) {
\r
3129 DisplayFatalError("Too many colors", 0, 1);
\r
3130 pLogPal->palNumEntries--;
\r
3134 pe->peFlags = (char) 0;
\r
3135 pe->peRed = (char) (0xFF & color);
\r
3136 pe->peGreen = (char) (0xFF & (color >> 8));
\r
3137 pe->peBlue = (char) (0xFF & (color >> 16));
\r
3143 InitDrawingColors()
\r
3145 if (pLogPal == NULL) {
\r
3146 /* Allocate enough memory for a logical palette with
\r
3147 * PALETTESIZE entries and set the size and version fields
\r
3148 * of the logical palette structure.
\r
3150 pLogPal = (NPLOGPALETTE)
\r
3151 LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +
\r
3152 (sizeof(PALETTEENTRY) * (PALETTESIZE))));
\r
3153 pLogPal->palVersion = 0x300;
\r
3155 pLogPal->palNumEntries = 0;
\r
3157 InsertInPalette(lightSquareColor);
\r
3158 InsertInPalette(darkSquareColor);
\r
3159 InsertInPalette(whitePieceColor);
\r
3160 InsertInPalette(blackPieceColor);
\r
3161 InsertInPalette(highlightSquareColor);
\r
3162 InsertInPalette(premoveHighlightColor);
\r
3164 /* create a logical color palette according the information
\r
3165 * in the LOGPALETTE structure.
\r
3167 hPal = CreatePalette((LPLOGPALETTE) pLogPal);
\r
3169 lightSquareBrush = CreateSolidBrush(lightSquareColor);
\r
3170 blackSquareBrush = CreateSolidBrush(blackPieceColor);
\r
3171 darkSquareBrush = CreateSolidBrush(darkSquareColor);
\r
3172 whitePieceBrush = CreateSolidBrush(whitePieceColor);
\r
3173 blackPieceBrush = CreateSolidBrush(blackPieceColor);
\r
3174 iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
\r
3175 explodeBrush = CreateSolidBrush(highlightSquareColor); // [HGM] atomic
\r
3176 /* [AS] Force rendering of the font-based pieces */
\r
3177 if( fontBitmapSquareSize > 0 ) {
\r
3178 fontBitmapSquareSize = 0;
\r
3184 BoardWidth(int boardSize, int n)
\r