2 * WinBoard.c -- Windows NT front end to XBoard
\r
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
\r
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
\r
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
\r
10 * Enhancements Copyright 2005 Alessandro Scotti
\r
12 * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,
\r
13 * which was written and is copyrighted by Wayne Christopher.
\r
15 * The following terms apply to Digital Equipment Corporation's copyright
\r
16 * interest in XBoard:
\r
17 * ------------------------------------------------------------------------
\r
18 * All Rights Reserved
\r
20 * Permission to use, copy, modify, and distribute this software and its
\r
21 * documentation for any purpose and without fee is hereby granted,
\r
22 * provided that the above copyright notice appear in all copies and that
\r
23 * both that copyright notice and this permission notice appear in
\r
24 * supporting documentation, and that the name of Digital not be
\r
25 * used in advertising or publicity pertaining to distribution of the
\r
26 * software without specific, written prior permission.
\r
28 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
\r
29 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
\r
30 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
\r
31 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
\r
32 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
\r
33 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
\r
35 * ------------------------------------------------------------------------
\r
37 * The following terms apply to the enhanced version of XBoard
\r
38 * distributed by the Free Software Foundation:
\r
39 * ------------------------------------------------------------------------
\r
41 * GNU XBoard is free software: you can redistribute it and/or modify
\r
42 * it under the terms of the GNU General Public License as published by
\r
43 * the Free Software Foundation, either version 3 of the License, or (at
\r
44 * your option) any later version.
\r
46 * GNU XBoard is distributed in the hope that it will be useful, but
\r
47 * WITHOUT ANY WARRANTY; without even the implied warranty of
\r
48 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
49 * General Public License for more details.
\r
51 * You should have received a copy of the GNU General Public License
\r
52 * along with this program. If not, see http://www.gnu.org/licenses/. *
\r
54 *------------------------------------------------------------------------
\r
55 ** See the file ChangeLog for a revision history. */
\r
59 #include <windows.h>
\r
60 #include <winuser.h>
\r
61 #include <winsock.h>
\r
62 #include <commctrl.h>
\r
68 #include <sys/stat.h>
\r
71 #include <commdlg.h>
\r
73 #include <richedit.h>
\r
74 #include <mmsystem.h>
\r
83 #include "winboard.h"
\r
84 #include "frontend.h"
\r
85 #include "backend.h"
\r
87 #include "wclipbrd.h"
\r
88 #include "wgamelist.h"
\r
89 #include "wedittags.h"
\r
90 #include "woptions.h"
\r
91 #include "wsockerr.h"
\r
92 #include "defaults.h"
\r
96 //void InitEngineUCI( const char * iniDir, ChessProgramState * cps );
\r
99 void mysrandom(unsigned int seed);
\r
101 extern int whiteFlag, blackFlag;
\r
102 Boolean flipClock = FALSE;
\r
103 extern HANDLE chatHandle[];
\r
104 extern int ics_type;
\r
106 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);
\r
107 VOID NewVariantPopup(HWND hwnd);
\r
108 int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,
\r
109 /*char*/int promoChar));
\r
110 void AnimateAtomicCapture(int fromX, int fromY, int toX, int toY, int nFrames);
\r
111 void DisplayMove P((int moveNumber));
\r
112 Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen));
\r
113 void ChatPopUp P(());
\r
115 ChessSquare piece;
\r
116 POINT pos; /* window coordinates of current pos */
\r
117 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
118 POINT from; /* board coordinates of the piece's orig pos */
\r
119 POINT to; /* board coordinates of the piece's new pos */
\r
122 static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };
\r
125 POINT start; /* window coordinates of start pos */
\r
126 POINT pos; /* window coordinates of current pos */
\r
127 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
128 POINT from; /* board coordinates of the piece's orig pos */
\r
131 static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} };
\r
134 POINT sq[2]; /* board coordinates of from, to squares */
\r
137 static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} };
\r
138 static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };
\r
140 typedef struct { // [HGM] atomic
\r
141 int fromX, fromY, toX, toY, radius;
\r
144 static ExplodeInfo explodeInfo;
\r
146 /* Window class names */
\r
147 char szAppName[] = "WinBoard";
\r
148 char szConsoleName[] = "WBConsole";
\r
150 /* Title bar text */
\r
151 char szTitle[] = "WinBoard";
\r
152 char szConsoleTitle[] = "I C S Interaction";
\r
155 char *settingsFileName;
\r
156 BOOLEAN saveSettingsOnExit;
\r
157 char installDir[MSG_SIZ];
\r
159 BoardSize boardSize;
\r
160 BOOLEAN chessProgram;
\r
161 static int boardX, boardY;
\r
162 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
\r
163 static int squareSize, lineGap, minorSize;
\r
164 static int winWidth, winHeight, winW, winH;
\r
165 static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo
\r
166 static int logoHeight = 0;
\r
167 static char messageText[MESSAGE_TEXT_MAX];
\r
168 static int clockTimerEvent = 0;
\r
169 static int loadGameTimerEvent = 0;
\r
170 static int analysisTimerEvent = 0;
\r
171 static DelayedEventCallback delayedTimerCallback;
\r
172 static int delayedTimerEvent = 0;
\r
173 static int buttonCount = 2;
\r
174 char *icsTextMenuString;
\r
176 char *firstChessProgramNames;
\r
177 char *secondChessProgramNames;
\r
179 #define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */
\r
181 #define PALETTESIZE 256
\r
183 HINSTANCE hInst; /* current instance */
\r
184 HWND hwndMain = NULL; /* root window*/
\r
185 HWND hwndConsole = NULL;
\r
186 BOOLEAN alwaysOnTop = FALSE;
\r
188 COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
\r
189 blackPieceColor, highlightSquareColor, premoveHighlightColor;
\r
191 ColorClass currentColorClass;
\r
193 HWND hCommPort = NULL; /* currently open comm port */
\r
194 static HWND hwndPause; /* pause button */
\r
195 static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */
\r
196 static HBRUSH lightSquareBrush, darkSquareBrush,
\r
197 blackSquareBrush, /* [HGM] for band between board and holdings */
\r
198 explodeBrush, /* [HGM] atomic */
\r
199 whitePieceBrush, blackPieceBrush, iconBkgndBrush /*, outlineBrush*/;
\r
200 static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];
\r
201 static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];
\r
202 static HPEN gridPen = NULL;
\r
203 static HPEN highlightPen = NULL;
\r
204 static HPEN premovePen = NULL;
\r
205 static NPLOGPALETTE pLogPal;
\r
206 static BOOL paletteChanged = FALSE;
\r
207 static HICON iconWhite, iconBlack, iconCurrent;
\r
208 static int doingSizing = FALSE;
\r
209 static int lastSizing = 0;
\r
210 static int prevStderrPort;
\r
211 static HBITMAP userLogo;
\r
213 /* [AS] Support for background textures */
\r
214 #define BACK_TEXTURE_MODE_DISABLED 0
\r
215 #define BACK_TEXTURE_MODE_PLAIN 1
\r
216 #define BACK_TEXTURE_MODE_FULL_RANDOM 2
\r
218 static HBITMAP liteBackTexture = NULL;
\r
219 static HBITMAP darkBackTexture = NULL;
\r
220 static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
221 static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
222 static int backTextureSquareSize = 0;
\r
223 static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_SIZE][BOARD_SIZE];
\r
225 #if __GNUC__ && !defined(_winmajor)
\r
226 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */
\r
228 #if defined(_winmajor)
\r
229 #define oldDialog (_winmajor < 4)
\r
231 #define oldDialog 0
\r
235 char *defaultTextAttribs[] =
\r
237 COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,
\r
238 COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,
\r
248 int cliWidth, cliHeight;
\r
251 SizeInfo sizeInfo[] =
\r
253 { "tiny", 21, 0, 1, 1, 0, 0 },
\r
254 { "teeny", 25, 1, 1, 1, 0, 0 },
\r
255 { "dinky", 29, 1, 1, 1, 0, 0 },
\r
256 { "petite", 33, 1, 1, 1, 0, 0 },
\r
257 { "slim", 37, 2, 1, 0, 0, 0 },
\r
258 { "small", 40, 2, 1, 0, 0, 0 },
\r
259 { "mediocre", 45, 2, 1, 0, 0, 0 },
\r
260 { "middling", 49, 2, 0, 0, 0, 0 },
\r
261 { "average", 54, 2, 0, 0, 0, 0 },
\r
262 { "moderate", 58, 3, 0, 0, 0, 0 },
\r
263 { "medium", 64, 3, 0, 0, 0, 0 },
\r
264 { "bulky", 72, 3, 0, 0, 0, 0 },
\r
265 { "large", 80, 3, 0, 0, 0, 0 },
\r
266 { "big", 87, 3, 0, 0, 0, 0 },
\r
267 { "huge", 95, 3, 0, 0, 0, 0 },
\r
268 { "giant", 108, 3, 0, 0, 0, 0 },
\r
269 { "colossal", 116, 4, 0, 0, 0, 0 },
\r
270 { "titanic", 129, 4, 0, 0, 0, 0 },
\r
271 { NULL, 0, 0, 0, 0, 0, 0 }
\r
274 #define MF(x) {x, {{0,}, 0. }, {0, }, 0}
\r
275 MyFont fontRec[NUM_SIZES][NUM_FONTS] =
\r
277 { MF(CLOCK_FONT_TINY), MF(MESSAGE_FONT_TINY), MF(COORD_FONT_TINY), MF(CONSOLE_FONT_TINY), MF(COMMENT_FONT_TINY), MF(EDITTAGS_FONT_TINY), MF(MOVEHISTORY_FONT_ALL) },
\r
278 { MF(CLOCK_FONT_TEENY), MF(MESSAGE_FONT_TEENY), MF(COORD_FONT_TEENY), MF(CONSOLE_FONT_TEENY), MF(COMMENT_FONT_TEENY), MF(EDITTAGS_FONT_TEENY), MF(MOVEHISTORY_FONT_ALL) },
\r
279 { MF(CLOCK_FONT_DINKY), MF(MESSAGE_FONT_DINKY), MF(COORD_FONT_DINKY), MF(CONSOLE_FONT_DINKY), MF(COMMENT_FONT_DINKY), MF(EDITTAGS_FONT_DINKY), MF(MOVEHISTORY_FONT_ALL) },
\r
280 { MF(CLOCK_FONT_PETITE), MF(MESSAGE_FONT_PETITE), MF(COORD_FONT_PETITE), MF(CONSOLE_FONT_PETITE), MF(COMMENT_FONT_PETITE), MF(EDITTAGS_FONT_PETITE), MF(MOVEHISTORY_FONT_ALL) },
\r
281 { MF(CLOCK_FONT_SLIM), MF(MESSAGE_FONT_SLIM), MF(COORD_FONT_SLIM), MF(CONSOLE_FONT_SLIM), MF(COMMENT_FONT_SLIM), MF(EDITTAGS_FONT_SLIM), MF(MOVEHISTORY_FONT_ALL) },
\r
282 { MF(CLOCK_FONT_SMALL), MF(MESSAGE_FONT_SMALL), MF(COORD_FONT_SMALL), MF(CONSOLE_FONT_SMALL), MF(COMMENT_FONT_SMALL), MF(EDITTAGS_FONT_SMALL), MF(MOVEHISTORY_FONT_ALL) },
\r
283 { MF(CLOCK_FONT_MEDIOCRE), MF(MESSAGE_FONT_MEDIOCRE), MF(COORD_FONT_MEDIOCRE), MF(CONSOLE_FONT_MEDIOCRE), MF(COMMENT_FONT_MEDIOCRE), MF(EDITTAGS_FONT_MEDIOCRE), MF(MOVEHISTORY_FONT_ALL) },
\r
284 { MF(CLOCK_FONT_MIDDLING), MF(MESSAGE_FONT_MIDDLING), MF(COORD_FONT_MIDDLING), MF(CONSOLE_FONT_MIDDLING), MF(COMMENT_FONT_MIDDLING), MF(EDITTAGS_FONT_MIDDLING), MF(MOVEHISTORY_FONT_ALL) },
\r
285 { MF(CLOCK_FONT_AVERAGE), MF(MESSAGE_FONT_AVERAGE), MF(COORD_FONT_AVERAGE), MF(CONSOLE_FONT_AVERAGE), MF(COMMENT_FONT_AVERAGE), MF(EDITTAGS_FONT_AVERAGE), MF(MOVEHISTORY_FONT_ALL) },
\r
286 { MF(CLOCK_FONT_MODERATE), MF(MESSAGE_FONT_MODERATE), MF(COORD_FONT_MODERATE), MF(CONSOLE_FONT_MODERATE), MF(COMMENT_FONT_MODERATE), MF(EDITTAGS_FONT_MODERATE), MF(MOVEHISTORY_FONT_ALL) },
\r
287 { MF(CLOCK_FONT_MEDIUM), MF(MESSAGE_FONT_MEDIUM), MF(COORD_FONT_MEDIUM), MF(CONSOLE_FONT_MEDIUM), MF(COMMENT_FONT_MEDIUM), MF(EDITTAGS_FONT_MEDIUM), MF(MOVEHISTORY_FONT_ALL) },
\r
288 { MF(CLOCK_FONT_BULKY), MF(MESSAGE_FONT_BULKY), MF(COORD_FONT_BULKY), MF(CONSOLE_FONT_BULKY), MF(COMMENT_FONT_BULKY), MF(EDITTAGS_FONT_BULKY), MF(MOVEHISTORY_FONT_ALL) },
\r
289 { MF(CLOCK_FONT_LARGE), MF(MESSAGE_FONT_LARGE), MF(COORD_FONT_LARGE), MF(CONSOLE_FONT_LARGE), MF(COMMENT_FONT_LARGE), MF(EDITTAGS_FONT_LARGE), MF(MOVEHISTORY_FONT_ALL) },
\r
290 { MF(CLOCK_FONT_BIG), MF(MESSAGE_FONT_BIG), MF(COORD_FONT_BIG), MF(CONSOLE_FONT_BIG), MF(COMMENT_FONT_BIG), MF(EDITTAGS_FONT_BIG), MF(MOVEHISTORY_FONT_ALL) },
\r
291 { MF(CLOCK_FONT_HUGE), MF(MESSAGE_FONT_HUGE), MF(COORD_FONT_HUGE), MF(CONSOLE_FONT_HUGE), MF(COMMENT_FONT_HUGE), MF(EDITTAGS_FONT_HUGE), MF(MOVEHISTORY_FONT_ALL) },
\r
292 { MF(CLOCK_FONT_GIANT), MF(MESSAGE_FONT_GIANT), MF(COORD_FONT_GIANT), MF(CONSOLE_FONT_GIANT), MF(COMMENT_FONT_GIANT), MF(EDITTAGS_FONT_GIANT), MF(MOVEHISTORY_FONT_ALL) },
\r
293 { MF(CLOCK_FONT_COLOSSAL), MF(MESSAGE_FONT_COLOSSAL), MF(COORD_FONT_COLOSSAL), MF(CONSOLE_FONT_COLOSSAL), MF(COMMENT_FONT_COLOSSAL), MF(EDITTAGS_FONT_COLOSSAL), MF(MOVEHISTORY_FONT_ALL) },
\r
294 { MF(CLOCK_FONT_TITANIC), MF(MESSAGE_FONT_TITANIC), MF(COORD_FONT_TITANIC), MF(CONSOLE_FONT_TITANIC), MF(COMMENT_FONT_TITANIC), MF(EDITTAGS_FONT_TITANIC), MF(MOVEHISTORY_FONT_ALL) },
\r
297 MyFont *font[NUM_SIZES][NUM_FONTS];
\r
306 #define BUTTON_WIDTH (tinyLayout ? 16 : 32)
\r
307 #define N_BUTTONS 5
\r
309 MyButtonDesc buttonDesc[N_BUTTONS] =
\r
311 {"<<", IDM_ToStart, NULL, NULL},
\r
312 {"<", IDM_Backward, NULL, NULL},
\r
313 {"P", IDM_Pause, NULL, NULL},
\r
314 {">", IDM_Forward, NULL, NULL},
\r
315 {">>", IDM_ToEnd, NULL, NULL},
\r
318 int tinyLayout = 0, smallLayout = 0;
\r
319 #define MENU_BAR_ITEMS 7
\r
320 char *menuBarText[2][MENU_BAR_ITEMS+1] = {
\r
321 { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },
\r
322 { "&F", "&M", "&A", "&S", "&O", "&H", NULL },
\r
326 MySound sounds[(int)NSoundClasses];
\r
327 MyTextAttribs textAttribs[(int)NColorClasses];
\r
329 MyColorizeAttribs colorizeAttribs[] = {
\r
330 { (COLORREF)0, 0, "Shout Text" },
\r
331 { (COLORREF)0, 0, "SShout/CShout" },
\r
332 { (COLORREF)0, 0, "Channel 1 Text" },
\r
333 { (COLORREF)0, 0, "Channel Text" },
\r
334 { (COLORREF)0, 0, "Kibitz Text" },
\r
335 { (COLORREF)0, 0, "Tell Text" },
\r
336 { (COLORREF)0, 0, "Challenge Text" },
\r
337 { (COLORREF)0, 0, "Request Text" },
\r
338 { (COLORREF)0, 0, "Seek Text" },
\r
339 { (COLORREF)0, 0, "Normal Text" },
\r
340 { (COLORREF)0, 0, "None" }
\r
345 static char *commentTitle;
\r
346 static char *commentText;
\r
347 static int commentIndex;
\r
348 static Boolean editComment = FALSE;
\r
349 HWND commentDialog = NULL;
\r
350 int commentUp = FALSE;
\r
351 static int commentX, commentY, commentH, commentW;
\r
353 static char *analysisTitle;
\r
354 static char *analysisText;
\r
355 HWND analysisDialog = NULL;
\r
356 BOOLEAN analysisDialogUp = FALSE;
\r
357 static int analysisX, analysisY, analysisH, analysisW;
\r
359 char errorTitle[MSG_SIZ];
\r
360 char errorMessage[2*MSG_SIZ];
\r
361 HWND errorDialog = NULL;
\r
362 BOOLEAN moveErrorMessageUp = FALSE;
\r
363 BOOLEAN consoleEcho = TRUE;
\r
364 CHARFORMAT consoleCF;
\r
365 COLORREF consoleBackgroundColor;
\r
367 char *programVersion;
\r
373 typedef int CPKind;
\r
382 SOCKET sock2; /* stderr socket for OpenRcmd */
\r
385 #define INPUT_SOURCE_BUF_SIZE 4096
\r
387 typedef struct _InputSource {
\r
394 char buf[INPUT_SOURCE_BUF_SIZE];
\r
398 InputCallback func;
\r
399 struct _InputSource *second; /* for stderr thread on CPRcmd */
\r
403 InputSource *consoleInputSource;
\r
408 VOID ConsoleOutput(char* data, int length, int forceVisible);
\r
409 VOID ConsoleCreate();
\r
411 ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
412 VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
\r
413 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
\r
414 VOID ParseCommSettings(char *arg, DCB *dcb);
\r
416 StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
417 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
\r
418 void ParseIcsTextMenu(char *icsTextMenuString);
\r
419 VOID PopUpMoveDialog(char firstchar);
\r
420 VOID PopUpNameDialog(char firstchar);
\r
421 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
\r
425 int GameListOptions();
\r
427 HWND moveHistoryDialog = NULL;
\r
428 BOOLEAN moveHistoryDialogUp = FALSE;
\r
430 WindowPlacement wpMoveHistory;
\r
432 HWND evalGraphDialog = NULL;
\r
433 BOOLEAN evalGraphDialogUp = FALSE;
\r
435 WindowPlacement wpEvalGraph;
\r
437 HWND engineOutputDialog = NULL;
\r
438 BOOLEAN engineOutputDialogUp = FALSE;
\r
440 WindowPlacement wpEngineOutput;
\r
441 WindowPlacement wpGameList;
\r
442 WindowPlacement wpConsole;
\r
444 VOID MoveHistoryPopUp();
\r
445 VOID MoveHistoryPopDown();
\r
446 VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
447 BOOL MoveHistoryIsUp();
\r
449 VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
450 VOID EvalGraphPopUp();
\r
451 VOID EvalGraphPopDown();
\r
452 BOOL EvalGraphIsUp();
\r
454 VOID EngineOutputPopUp();
\r
455 VOID EngineOutputPopDown();
\r
456 BOOL EngineOutputIsUp();
\r
457 VOID EngineOutputUpdate( FrontEndProgramStats * stats );
\r
459 VOID EngineOptionsPopup(); // [HGM] settings
\r
461 VOID GothicPopUp(char *title, VariantClass variant);
\r
463 * Setting "frozen" should disable all user input other than deleting
\r
464 * the window. We do this while engines are initializing themselves.
\r
466 static int frozen = 0;
\r
467 static int oldMenuItemState[MENU_BAR_ITEMS];
\r
473 if (frozen) return;
\r
475 hmenu = GetMenu(hwndMain);
\r
476 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
477 oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
\r
479 DrawMenuBar(hwndMain);
\r
482 /* Undo a FreezeUI */
\r
488 if (!frozen) return;
\r
490 hmenu = GetMenu(hwndMain);
\r
491 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
492 EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
\r
494 DrawMenuBar(hwndMain);
\r
497 /*static*/ int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them
\r
499 /* JAWS preparation patch (WinBoard for the sight impaired). Define required insertions as empty */
\r
505 #define JAWS_ALT_INTERCEPT
\r
506 #define JAWS_KB_NAVIGATION
\r
507 #define JAWS_MENU_ITEMS
\r
508 #define JAWS_SILENCE
\r
509 #define JAWS_REPLAY
\r
511 #define JAWS_COPYRIGHT
\r
512 #define JAWS_DELETE(X) X
\r
513 #define SAYMACHINEMOVE()
\r
517 /*---------------------------------------------------------------------------*\
\r
521 \*---------------------------------------------------------------------------*/
\r
524 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
\r
525 LPSTR lpCmdLine, int nCmdShow)
\r
528 HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
\r
529 // INITCOMMONCONTROLSEX ex;
\r
533 LoadLibrary("RICHED32.DLL");
\r
534 consoleCF.cbSize = sizeof(CHARFORMAT);
\r
536 if (!InitApplication(hInstance)) {
\r
539 if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
\r
545 // InitCommonControlsEx(&ex);
\r
546 InitCommonControls();
\r
548 hAccelMain = LoadAccelerators (hInstance, szAppName);
\r
549 hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
\r
550 hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
\r
552 /* Acquire and dispatch messages until a WM_QUIT message is received. */
\r
554 while (GetMessage(&msg, /* message structure */
\r
555 NULL, /* handle of window receiving the message */
\r
556 0, /* lowest message to examine */
\r
557 0)) /* highest message to examine */
\r
560 if(msg.message == WM_CHAR && msg.wParam == '\t') {
\r
561 // [HGM] navigate: switch between all windows with tab
\r
562 HWND e1 = NULL, e2 = NULL, mh = NULL, hInput = NULL, hText = NULL;
\r
563 int i, currentElement = 0;
\r
565 // first determine what element of the chain we come from (if any)
\r
566 if(appData.icsActive) {
\r
567 hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);
\r
568 hText = GetDlgItem(hwndConsole, OPT_ConsoleText);
\r
570 if(engineOutputDialog && EngineOutputIsUp()) {
\r
571 e1 = GetDlgItem(engineOutputDialog, IDC_EngineMemo1);
\r
572 e2 = GetDlgItem(engineOutputDialog, IDC_EngineMemo2);
\r
574 if(moveHistoryDialog && MoveHistoryIsUp()) {
\r
575 mh = GetDlgItem(moveHistoryDialog, IDC_MoveHistory);
\r
577 if(msg.hwnd == hwndMain) currentElement = 7 ; else
\r
578 if(msg.hwnd == engineOutputDialog) currentElement = 2; else
\r
579 if(msg.hwnd == e1) currentElement = 2; else
\r
580 if(msg.hwnd == e2) currentElement = 3; else
\r
581 if(msg.hwnd == moveHistoryDialog) currentElement = 4; else
\r
582 if(msg.hwnd == mh) currentElement = 4; else
\r
583 if(msg.hwnd == evalGraphDialog) currentElement = 6; else
\r
584 if(msg.hwnd == hText) currentElement = 5; else
\r
585 if(msg.hwnd == hInput) currentElement = 6; else
\r
586 for (i = 0; i < N_BUTTONS; i++) {
\r
587 if (buttonDesc[i].hwnd == msg.hwnd) { currentElement = 1; break; }
\r
590 // determine where to go to
\r
591 if(currentElement) { HWND h = NULL; int direction = GetKeyState(VK_SHIFT) < 0 ? -1 : 1;
\r
593 currentElement = (currentElement + direction) % 7;
\r
594 switch(currentElement) {
\r
596 h = hwndMain; break; // passing this case always makes the loop exit
\r
598 h = buttonDesc[0].hwnd; break; // could be NULL
\r
600 if(!EngineOutputIsUp()) continue; // skip closed auxiliary windows
\r
603 if(!EngineOutputIsUp()) continue;
\r
606 if(!MoveHistoryIsUp()) continue;
\r
608 // case 6: // input to eval graph does not seem to get here!
\r
609 // if(!EvalGraphIsUp()) continue;
\r
610 // h = evalGraphDialog; break;
\r
612 if(!appData.icsActive) continue;
\r
616 if(!appData.icsActive) continue;
\r
622 if(currentElement > 4 && IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);
\r
623 if(currentElement < 5 && IsIconic(hwndMain)) ShowWindow(hwndMain, SW_RESTORE); // all open together
\r
626 continue; // this message now has been processed
\r
630 if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
\r
631 !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
\r
632 !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
\r
633 !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
\r
634 !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
\r
635 !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
\r
636 !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
\r
637 !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) && JAWS_ACCEL
\r
638 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
\r
639 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
\r
640 int done = 0, i; // [HGM] chat: dispatch cat-box messages
\r
641 for(i=0; i<MAX_CHAT; i++)
\r
642 if(chatHandle[i] && IsDialogMessage(chatHandle[i], &msg)) {
\r
645 if(done) continue; // [HGM] chat: end patch
\r
646 TranslateMessage(&msg); /* Translates virtual key codes */
\r
647 DispatchMessage(&msg); /* Dispatches message to window */
\r
652 return (msg.wParam); /* Returns the value from PostQuitMessage */
\r
655 /*---------------------------------------------------------------------------*\
\r
657 * Initialization functions
\r
659 \*---------------------------------------------------------------------------*/
\r
663 { // update user logo if necessary
\r
664 static char oldUserName[MSG_SIZ], *curName;
\r
666 if(appData.autoLogo) {
\r
667 curName = UserName();
\r
668 if(strcmp(curName, oldUserName)) {
\r
669 sprintf(oldUserName, "logos\\%s.bmp", curName);
\r
670 userLogo = LoadImage( 0, oldUserName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
671 strcpy(oldUserName, curName);
\r
677 InitApplication(HINSTANCE hInstance)
\r
681 /* Fill in window class structure with parameters that describe the */
\r
684 wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
\r
685 wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
\r
686 wc.cbClsExtra = 0; /* No per-class extra data. */
\r
687 wc.cbWndExtra = 0; /* No per-window extra data. */
\r
688 wc.hInstance = hInstance; /* Owner of this class */
\r
689 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
690 wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
\r
691 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
\r
692 wc.lpszMenuName = szAppName; /* Menu name from .RC */
\r
693 wc.lpszClassName = szAppName; /* Name to register as */
\r
695 /* Register the window class and return success/failure code. */
\r
696 if (!RegisterClass(&wc)) return FALSE;
\r
698 wc.style = CS_HREDRAW | CS_VREDRAW;
\r
699 wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
\r
701 wc.cbWndExtra = DLGWINDOWEXTRA;
\r
702 wc.hInstance = hInstance;
\r
703 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
704 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
\r
705 wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
\r
706 wc.lpszMenuName = NULL;
\r
707 wc.lpszClassName = szConsoleName;
\r
709 if (!RegisterClass(&wc)) return FALSE;
\r
714 /* Set by InitInstance, used by EnsureOnScreen */
\r
715 int screenHeight, screenWidth;
\r
718 EnsureOnScreen(int *x, int *y, int minX, int minY)
\r
720 // int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
\r
721 /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
\r
722 if (*x > screenWidth - 32) *x = 0;
\r
723 if (*y > screenHeight - 32) *y = 0;
\r
724 if (*x < minX) *x = minX;
\r
725 if (*y < minY) *y = minY;
\r
729 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
\r
731 HWND hwnd; /* Main window handle. */
\r
733 WINDOWPLACEMENT wp;
\r
736 hInst = hInstance; /* Store instance handle in our global variable */
\r
738 if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
\r
739 *filepart = NULLCHAR;
\r
741 GetCurrentDirectory(MSG_SIZ, installDir);
\r
743 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise
\r
744 screenWidth = screenHeight = 1000; // [HGM] placement: kludge to allow calling EnsureOnScreen from InitAppData
\r
745 InitAppData(lpCmdLine); /* Get run-time parameters */
\r
746 if (appData.debugMode) {
\r
747 debugFP = fopen(appData.nameOfDebugFile, "w");
\r
748 setbuf(debugFP, NULL);
\r
753 // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()
\r
754 // InitEngineUCI( installDir, &second );
\r
756 /* Create a main window for this application instance. */
\r
757 hwnd = CreateWindow(szAppName, szTitle,
\r
758 (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
\r
759 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
\r
760 NULL, NULL, hInstance, NULL);
\r
763 /* If window could not be created, return "failure" */
\r
768 /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */
\r
769 if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {
\r
770 first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
772 if (first.programLogo == NULL && appData.debugMode) {
\r
773 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );
\r
775 } else if(appData.autoLogo) {
\r
776 if(appData.firstDirectory && appData.firstDirectory[0]) {
\r
778 sprintf(buf, "%s/logo.bmp", appData.firstDirectory);
\r
779 first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
783 if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {
\r
784 second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
786 if (second.programLogo == NULL && appData.debugMode) {
\r
787 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );
\r
789 } else if(appData.autoLogo) {
\r
791 if(appData.icsActive) { // [HGM] logo: in ICS mode second can be used for ICS
\r
792 sprintf(buf, "logos\\%s.bmp", appData.icsHost);
\r
793 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
795 if(appData.secondDirectory && appData.secondDirectory[0]) {
\r
796 sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);
\r
797 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
803 iconWhite = LoadIcon(hInstance, "icon_white");
\r
804 iconBlack = LoadIcon(hInstance, "icon_black");
\r
805 iconCurrent = iconWhite;
\r
806 InitDrawingColors();
\r
807 screenHeight = GetSystemMetrics(SM_CYSCREEN);
\r
808 screenWidth = GetSystemMetrics(SM_CXSCREEN);
\r
809 for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
\r
810 /* Compute window size for each board size, and use the largest
\r
811 size that fits on this screen as the default. */
\r
812 InitDrawingSizes((BoardSize)(ibs+1000), 0);
\r
813 if (boardSize == (BoardSize)-1 &&
\r
814 winH <= screenHeight
\r
815 - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10
\r
816 && winW <= screenWidth) {
\r
817 boardSize = (BoardSize)ibs;
\r
821 InitDrawingSizes(boardSize, 0);
\r
823 buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
\r
825 /* [AS] Load textures if specified */
\r
826 ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );
\r
828 if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {
\r
829 liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
830 liteBackTextureMode = appData.liteBackTextureMode;
\r
832 if (liteBackTexture == NULL && appData.debugMode) {
\r
833 fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );
\r
837 if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {
\r
838 darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
839 darkBackTextureMode = appData.darkBackTextureMode;
\r
841 if (darkBackTexture == NULL && appData.debugMode) {
\r
842 fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );
\r
846 mysrandom( (unsigned) time(NULL) );
\r
848 /* [AS] Restore layout */
\r
849 if( wpMoveHistory.visible ) {
\r
850 MoveHistoryPopUp();
\r
853 if( wpEvalGraph.visible ) {
\r
857 if( wpEngineOutput.visible ) {
\r
858 EngineOutputPopUp();
\r
863 /* Make the window visible; update its client area; and return "success" */
\r
864 EnsureOnScreen(&boardX, &boardY, minX, minY);
\r
865 wp.length = sizeof(WINDOWPLACEMENT);
\r
867 wp.showCmd = nCmdShow;
\r
868 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
\r
869 wp.rcNormalPosition.left = boardX;
\r
870 wp.rcNormalPosition.right = boardX + winWidth;
\r
871 wp.rcNormalPosition.top = boardY;
\r
872 wp.rcNormalPosition.bottom = boardY + winHeight;
\r
873 SetWindowPlacement(hwndMain, &wp);
\r
875 if(!appData.noGUI) SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
876 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
880 SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
881 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
883 ShowWindow(hwndConsole, nCmdShow);
\r
885 if(!appData.noGUI) UpdateWindow(hwnd); else ShowWindow(hwnd, SW_MINIMIZE);
\r
886 if(gameListDialog) SetFocus(gameListDialog); // [HGM] jaws: for if we clicked multi-game game file
\r
894 ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
\r
895 ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
\r
896 ArgSettingsFilename,
\r
897 ArgX, ArgY, ArgZ // [HGM] placement: for window-placement options stored relative to main window
\r
905 String *pString; // ArgString
\r
906 int *pInt; // ArgInt
\r
907 float *pFloat; // ArgFloat
\r
908 Boolean *pBoolean; // ArgBoolean
\r
909 COLORREF *pColor; // ArgColor
\r
910 ColorClass cc; // ArgAttribs
\r
911 String *pFilename; // ArgFilename
\r
912 BoardSize *pBoardSize; // ArgBoardSize
\r
913 int whichFont; // ArgFont
\r
914 DCB *pDCB; // ArgCommSettings
\r
915 String *pFilename; // ArgSettingsFilename
\r
923 ArgDescriptor argDescriptors[] = {
\r
924 /* positional arguments */
\r
925 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
926 { "", ArgNone, NULL },
\r
927 /* keyword arguments */
\r
929 { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },
\r
930 { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },
\r
931 { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },
\r
932 { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },
\r
933 { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },
\r
934 { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },
\r
935 { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },
\r
936 { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },
\r
937 { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },
\r
938 { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },
\r
939 { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },
\r
940 { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },
\r
941 { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },
\r
942 { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },
\r
943 { "initString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
944 { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
945 { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },
\r
946 { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,
\r
948 { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,
\r
950 { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,
\r
952 { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },
\r
953 { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,
\r
955 { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },
\r
956 { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
957 { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
958 { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
959 { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
960 { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },
\r
961 { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },
\r
962 { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
963 { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
964 { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
965 { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
966 { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
967 { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
968 { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
969 { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
970 { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
971 { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
972 /*!!bitmapDirectory?*/
\r
973 { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
974 { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
975 { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
976 { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
977 { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },
\r
978 { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },
\r
979 { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },
\r
980 { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },
\r
981 { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },
\r
982 { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },
\r
983 { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },
\r
984 { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },
\r
985 { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
986 { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
987 { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
988 { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
989 { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
990 { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
991 { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
992 { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
993 { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
994 { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
995 { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
996 { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
997 { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },
\r
998 { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },
\r
999 { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
1000 { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
1001 { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },
\r
1002 { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },
\r
1003 { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },
\r
1004 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
1005 { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
1006 { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
1007 { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
1008 { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },
\r
1009 { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },
\r
1010 { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },
\r
1011 { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },
\r
1012 { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
1013 { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
1014 { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
1015 { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
1016 { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
1017 { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
1018 { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
1019 { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
1020 { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },
\r
1021 { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },
\r
1022 { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
1023 { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
1024 { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
1025 { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
1026 { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },
\r
1027 { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },
\r
1028 { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
1029 { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
1030 { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },
\r
1031 { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },
\r
1032 { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
1033 { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
1034 { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },
\r
1035 { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },
\r
1036 { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
1037 { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
1038 { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
1039 { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
1040 { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
1041 { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
1042 { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },
\r
1043 { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },
\r
1044 { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
1045 { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
1046 { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },
\r
1047 { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },
\r
1048 { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
1049 { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
1050 { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },
\r
1051 { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1052 { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1053 { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1054 { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },
\r
1055 { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1056 { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1057 { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1058 { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },
\r
1059 { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1060 { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1061 { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1062 { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },
\r
1063 { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1064 { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1065 { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1066 { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors,
\r
1067 FALSE }, /* only so that old WinBoard.ini files from betas can be read */
\r
1068 { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },
\r
1069 { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },
\r
1070 { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },
\r
1071 { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },
\r
1072 { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },
\r
1073 { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },
\r
1074 { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE }, /* [AS] */
\r
1075 { "boardSize", ArgBoardSize, (LPVOID) &boardSize,
\r
1076 TRUE }, /* must come after all fonts */
\r
1077 { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },
\r
1078 { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,
\r
1079 FALSE }, /* historical; kept only so old winboard.ini files will parse */
\r
1080 { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },
\r
1081 { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },
\r
1082 { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
1083 { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
1084 { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },
\r
1085 { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1086 { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1087 { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1088 { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },
\r
1089 { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },
\r
1090 { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
1091 { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
1092 { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },
\r
1093 { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },
\r
1094 { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
1095 { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
1096 { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },
\r
1097 { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },
\r
1098 { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
1099 { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
1100 { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },
\r
1101 { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },
\r
1102 { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
1103 { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
1104 { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },
\r
1105 { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1106 { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1107 { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1108 { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },
\r
1109 { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1110 { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1111 { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1112 { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },
\r
1113 { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1114 { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1115 { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1116 { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },
\r
1117 { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },
\r
1118 { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
1119 { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
1120 { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },
\r
1121 { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },
\r
1122 { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
1123 { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
1124 { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },
\r
1125 { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },
\r
1126 { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
1127 { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
1128 { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },
\r
1129 { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },
\r
1130 { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
1131 { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
1132 { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },
\r
1133 { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },
\r
1134 { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
1135 { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
1136 { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },
\r
1137 { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },
\r
1138 { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },
\r
1139 { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1140 { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1141 { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },
\r
1142 { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},
\r
1143 { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},
\r
1144 { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1145 { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1146 { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},
\r
1147 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1148 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1149 { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },
\r
1150 { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1151 { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1152 { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },
\r
1153 { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },
\r
1154 { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1155 { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1156 { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },
\r
1157 { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },
\r
1158 { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },
\r
1159 { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1160 { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1161 { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },
\r
1162 { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },
\r
1163 { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1164 { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1165 { "highlightLastMove", ArgBoolean,
\r
1166 (LPVOID) &appData.highlightLastMove, TRUE },
\r
1167 { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1168 { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1169 { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1170 { "highlightDragging", ArgBoolean,
\r
1171 (LPVOID) &appData.highlightDragging, TRUE },
\r
1172 { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },
\r
1173 { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1174 { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1175 { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },
\r
1176 { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },
\r
1177 { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1178 { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1179 { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },
\r
1180 { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },
\r
1181 { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },
\r
1182 { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },
\r
1183 { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },
\r
1184 { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },
\r
1185 { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },
\r
1186 { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },
\r
1187 { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },
\r
1188 { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },
\r
1189 { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },
\r
1190 { "soundShout", ArgFilename,
\r
1191 (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },
\r
1192 { "soundSShout", ArgFilename,
\r
1193 (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },
\r
1194 { "soundChannel1", ArgFilename,
\r
1195 (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },
\r
1196 { "soundChannel", ArgFilename,
\r
1197 (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },
\r
1198 { "soundKibitz", ArgFilename,
\r
1199 (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },
\r
1200 { "soundTell", ArgFilename,
\r
1201 (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },
\r
1202 { "soundChallenge", ArgFilename,
\r
1203 (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },
\r
1204 { "soundRequest", ArgFilename,
\r
1205 (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },
\r
1206 { "soundSeek", ArgFilename,
\r
1207 (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },
\r
1208 { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },
\r
1209 { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },
\r
1210 { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },
\r
1211 { "soundIcsLoss", ArgFilename,
\r
1212 (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },
\r
1213 { "soundIcsDraw", ArgFilename,
\r
1214 (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },
\r
1215 { "soundIcsUnfinished", ArgFilename,
\r
1216 (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},
\r
1217 { "soundIcsAlarm", ArgFilename,
\r
1218 (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },
\r
1219 { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },
\r
1220 { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },
\r
1221 { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1222 { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1223 { "reuseChessPrograms", ArgBoolean,
\r
1224 (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */
\r
1225 { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },
\r
1226 { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },
\r
1227 { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1228 { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1229 { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },
\r
1230 { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1231 { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1232 { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },
\r
1233 { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },
\r
1234 { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },
\r
1235 { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1236 { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1237 { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },
\r
1238 { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },
\r
1239 { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,
\r
1241 { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,
\r
1243 { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1244 { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1245 { "variant", ArgString, (LPVOID) &appData.variant, FALSE },
\r
1246 { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion, FALSE },
\r
1247 { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,FALSE },
\r
1248 { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },
\r
1249 { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },
\r
1250 { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1251 { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1252 /* [AS] New features */
\r
1253 { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE },
\r
1254 { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE },
\r
1255 { "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE },
\r
1256 { "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE },
\r
1257 { "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE },
\r
1258 { "darkBackTextureFile", ArgString, (LPVOID) &appData.darkBackTextureFile, TRUE },
\r
1259 { "liteBackTextureMode", ArgInt, (LPVOID) &appData.liteBackTextureMode, TRUE },
\r
1260 { "darkBackTextureMode", ArgInt, (LPVOID) &appData.darkBackTextureMode, TRUE },
\r
1261 { "renderPiecesWithFont", ArgString, (LPVOID) &appData.renderPiecesWithFont, TRUE },
\r
1262 { "fontPieceToCharTable", ArgString, (LPVOID) &appData.fontToPieceTable, TRUE },
\r
1263 { "fontPieceBackColorWhite", ArgColor, (LPVOID) &appData.fontBackColorWhite, TRUE },
\r
1264 { "fontPieceForeColorWhite", ArgColor, (LPVOID) &appData.fontForeColorWhite, TRUE },
\r
1265 { "fontPieceBackColorBlack", ArgColor, (LPVOID) &appData.fontBackColorBlack, TRUE },
\r
1266 { "fontPieceForeColorBlack", ArgColor, (LPVOID) &appData.fontForeColorBlack, TRUE },
\r
1267 { "fontPieceSize", ArgInt, (LPVOID) &appData.fontPieceSize, TRUE },
\r
1268 { "overrideLineGap", ArgInt, (LPVOID) &appData.overrideLineGap, TRUE },
\r
1269 { "adjudicateLossThreshold", ArgInt, (LPVOID) &appData.adjudicateLossThreshold, TRUE },
\r
1270 { "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE },
\r
1271 { "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE },
\r
1272 { "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1273 { "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1274 { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },
\r
1275 { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE },
\r
1276 { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE },
\r
1277 { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE },
\r
1278 { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE },
\r
1279 { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE },
\r
1280 { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE },
\r
1281 { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE },
\r
1282 { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE },
\r
1283 { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE },
\r
1284 { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE },
\r
1285 { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE },
\r
1286 { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE },
\r
1287 { "firstIsUCI", ArgBoolean, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1288 { "fUCI", ArgTrue, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1289 { "secondIsUCI", ArgBoolean, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1290 { "sUCI", ArgTrue, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1291 { "firstHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1292 { "fNoOwnBookUCI", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1293 { "firstXBook", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1294 { "secondHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1295 { "sNoOwnBookUCI", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1296 { "secondXBook", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1297 { "polyglotDir", ArgFilename, (LPVOID) &appData.polyglotDir, TRUE },
\r
1298 { "usePolyglotBook", ArgBoolean, (LPVOID) &appData.usePolyglotBook, TRUE },
\r
1299 { "polyglotBook", ArgFilename, (LPVOID) &appData.polyglotBook, TRUE },
\r
1300 { "defaultHashSize", ArgInt, (LPVOID) &appData.defaultHashSize, TRUE },
\r
1301 { "defaultCacheSizeEGTB", ArgInt, (LPVOID) &appData.defaultCacheSizeEGTB, TRUE },
\r
1302 { "defaultPathEGTB", ArgFilename, (LPVOID) &appData.defaultPathEGTB, TRUE },
\r
1304 /* [HGM] board-size, adjudication and misc. options */
\r
1305 { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE },
\r
1306 { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE },
\r
1307 { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE },
\r
1308 { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE },
\r
1309 { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE },
\r
1310 { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE },
\r
1311 { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE },
\r
1312 { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE },
\r
1313 { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE },
\r
1314 { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE },
\r
1315 { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE },
\r
1316 { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE },
\r
1317 { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE },
\r
1318 { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE },
\r
1319 { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE },
\r
1320 { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE },
\r
1321 { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE },
\r
1322 { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE },
\r
1323 { "userName", ArgString, (LPVOID) &appData.userName, FALSE },
\r
1324 { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE },
\r
1325 { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE },
\r
1326 { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE },
\r
1327 { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE },
\r
1328 { "niceEngines", ArgInt, (LPVOID) &appData.niceEngines, TRUE },
\r
1329 { "firstLogo", ArgFilename, (LPVOID) &appData.firstLogo, FALSE },
\r
1330 { "secondLogo", ArgFilename, (LPVOID) &appData.secondLogo, FALSE },
\r
1331 { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE },
\r
1332 { "firstOptions", ArgString, (LPVOID) &appData.firstOptions, FALSE },
\r
1333 { "secondOptions", ArgString, (LPVOID) &appData.secondOptions, FALSE },
\r
1334 { "firstNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride1, FALSE },
\r
1335 { "secondNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride2, FALSE },
\r
1336 { "keepAlive", ArgInt, (LPVOID) &appData.keepAlive, FALSE },
\r
1337 { "icstype", ArgInt, (LPVOID) &ics_type, FALSE },
\r
1338 { "forceIllegalMoves", ArgTrue, (LPVOID) &appData.forceIllegal, FALSE },
\r
1341 { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },
\r
1342 { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },
\r
1343 { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1344 { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1345 { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },
\r
1346 { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },
\r
1347 { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1348 { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1349 { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },
\r
1350 { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },
\r
1351 { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },
\r
1352 { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE },
\r
1353 { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,
\r
1355 { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE },
\r
1356 { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE },
\r
1357 { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE },
\r
1358 { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1359 { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1360 { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE },
\r
1361 { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,
\r
1363 { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1364 { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1365 { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1366 { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE },
\r
1367 { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE },
\r
1368 { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1369 { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1370 { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1371 { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1372 { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE },
\r
1373 { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE },
\r
1374 { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1375 { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1376 { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },
\r
1377 { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },
\r
1378 { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },
\r
1379 { "zippyShortGame", ArgInt, (LPVOID)&appData.zippyShortGame, FALSE },
\r
1380 /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */
\r
1381 { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },
\r
1383 /* [HGM] options for broadcasting and time odds */
\r
1384 { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },
\r
1385 { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },
\r
1386 { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },
\r
1387 { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },
\r
1388 { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },
\r
1389 { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },
\r
1390 { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },
\r
1391 { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },
\r
1392 { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },
\r
1393 { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },
\r
1394 { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE },
\r
1395 { "keepLineBreaksICS", ArgBoolean, (LPVOID) &appData.noJoin, TRUE },
\r
1396 { "wrapContinuationSequence", ArgString, (LPVOID) &appData.wrapContSeq, FALSE },
\r
1397 { "useInternalWrap", ArgTrue, (LPVOID) &appData.useInternalWrap, FALSE }, /* noJoin usurps this if set */
\r
1399 // [HGM] placement: put all window layouts last in ini file, but man X,Y before all others
\r
1400 { "minX", ArgZ, (LPVOID) &minX, FALSE }, // [HGM] placement: to make suer auxialary windows can be placed
\r
1401 { "minY", ArgZ, (LPVOID) &minY, FALSE },
\r
1402 { "winWidth", ArgInt, (LPVOID) &winWidth, TRUE }, // [HGM] placement: dummies to remember right & bottom
\r
1403 { "winHeight", ArgInt, (LPVOID) &winHeight, TRUE }, // for attaching auxiliary windows to them
\r
1404 { "x", ArgInt, (LPVOID) &boardX, TRUE },
\r
1405 { "y", ArgInt, (LPVOID) &boardY, TRUE },
\r
1406 { "icsX", ArgX, (LPVOID) &wpConsole.x, TRUE },
\r
1407 { "icsY", ArgY, (LPVOID) &wpConsole.y, TRUE },
\r
1408 { "icsW", ArgInt, (LPVOID) &wpConsole.width, TRUE },
\r
1409 { "icsH", ArgInt, (LPVOID) &wpConsole.height, TRUE },
\r
1410 { "analysisX", ArgX, (LPVOID) &analysisX, FALSE }, // [HGM] placement: analysis window no longer exists
\r
1411 { "analysisY", ArgY, (LPVOID) &analysisY, FALSE }, // provided for compatibility with old ini files
\r
1412 { "analysisW", ArgInt, (LPVOID) &analysisW, FALSE },
\r
1413 { "analysisH", ArgInt, (LPVOID) &analysisH, FALSE },
\r
1414 { "commentX", ArgX, (LPVOID) &commentX, TRUE },
\r
1415 { "commentY", ArgY, (LPVOID) &commentY, TRUE },
\r
1416 { "commentW", ArgInt, (LPVOID) &commentW, TRUE },
\r
1417 { "commentH", ArgInt, (LPVOID) &commentH, TRUE },
\r
1418 { "tagsX", ArgX, (LPVOID) &editTagsX, TRUE },
\r
1419 { "tagsY", ArgY, (LPVOID) &editTagsY, TRUE },
\r
1420 { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },
\r
1421 { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },
\r
1422 { "gameListX", ArgX, (LPVOID) &wpGameList.x, TRUE },
\r
1423 { "gameListY", ArgY, (LPVOID) &wpGameList.y, TRUE },
\r
1424 { "gameListW", ArgInt, (LPVOID) &wpGameList.width, TRUE },
\r
1425 { "gameListH", ArgInt, (LPVOID) &wpGameList.height, TRUE },
\r
1426 /* [AS] Layout stuff */
\r
1427 { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },
\r
1428 { "moveHistoryX", ArgX, (LPVOID) &wpMoveHistory.x, TRUE },
\r
1429 { "moveHistoryY", ArgY, (LPVOID) &wpMoveHistory.y, TRUE },
\r
1430 { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },
\r
1431 { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },
\r
1433 { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },
\r
1434 { "evalGraphX", ArgX, (LPVOID) &wpEvalGraph.x, TRUE },
\r
1435 { "evalGraphY", ArgY, (LPVOID) &wpEvalGraph.y, TRUE },
\r
1436 { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },
\r
1437 { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },
\r
1439 { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },
\r
1440 { "engineOutputX", ArgX, (LPVOID) &wpEngineOutput.x, TRUE },
\r
1441 { "engineOutputY", ArgY, (LPVOID) &wpEngineOutput.y, TRUE },
\r
1442 { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },
\r
1443 { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },
\r
1445 { NULL, ArgNone, NULL, FALSE }
\r
1449 /* Kludge for indirection files on command line */
\r
1450 char* lastIndirectionFilename;
\r
1451 ArgDescriptor argDescriptorIndirection =
\r
1452 { "", ArgSettingsFilename, (LPVOID) NULL, FALSE };
\r
1456 ExitArgError(char *msg, char *badArg)
\r
1458 char buf[MSG_SIZ];
\r
1460 sprintf(buf, "%s %s", msg, badArg);
\r
1461 DisplayFatalError(buf, 0, 2);
\r
1465 /* Command line font name parser. NULL name means do nothing.
\r
1466 Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"
\r
1467 For backward compatibility, syntax without the colon is also
\r
1468 accepted, but font names with digits in them won't work in that case.
\r
1471 ParseFontName(char *name, MyFontParams *mfp)
\r
1474 if (name == NULL) return;
\r
1476 q = strchr(p, ':');
\r
1478 if (q - p >= sizeof(mfp->faceName))
\r
1479 ExitArgError("Font name too long:", name);
\r
1480 memcpy(mfp->faceName, p, q - p);
\r
1481 mfp->faceName[q - p] = NULLCHAR;
\r
1484 q = mfp->faceName;
\r
1485 while (*p && !isdigit(*p)) {
\r
1487 if (q - mfp->faceName >= sizeof(mfp->faceName))
\r
1488 ExitArgError("Font name too long:", name);
\r
1490 while (q > mfp->faceName && q[-1] == ' ') q--;
\r
1493 if (!*p) ExitArgError("Font point size missing:", name);
\r
1494 mfp->pointSize = (float) atof(p);
\r
1495 mfp->bold = (strchr(p, 'b') != NULL);
\r
1496 mfp->italic = (strchr(p, 'i') != NULL);
\r
1497 mfp->underline = (strchr(p, 'u') != NULL);
\r
1498 mfp->strikeout = (strchr(p, 's') != NULL);
\r
1499 mfp->charset = DEFAULT_CHARSET;
\r
1500 q = strchr(p, 'c');
\r
1502 mfp->charset = (BYTE) atoi(q+1);
\r
1505 /* Color name parser.
\r
1506 X version accepts X color names, but this one
\r
1507 handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */
\r
1509 ParseColorName(char *name)
\r
1511 int red, green, blue, count;
\r
1512 char buf[MSG_SIZ];
\r
1514 count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);
\r
1516 count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d",
\r
1517 &red, &green, &blue);
\r
1520 sprintf(buf, "Can't parse color name %s", name);
\r
1521 DisplayError(buf, 0);
\r
1522 return RGB(0, 0, 0);
\r
1524 return PALETTERGB(red, green, blue);
\r
1528 void ParseAttribs(COLORREF *color, int *effects, char* argValue)
\r
1530 char *e = argValue;
\r
1534 if (*e == 'b') eff |= CFE_BOLD;
\r
1535 else if (*e == 'i') eff |= CFE_ITALIC;
\r
1536 else if (*e == 'u') eff |= CFE_UNDERLINE;
\r
1537 else if (*e == 's') eff |= CFE_STRIKEOUT;
\r
1538 else if (*e == '#' || isdigit(*e)) break;
\r
1542 *color = ParseColorName(e);
\r
1547 ParseBoardSize(char *name)
\r
1549 BoardSize bs = SizeTiny;
\r
1550 while (sizeInfo[bs].name != NULL) {
\r
1551 if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;
\r
1554 ExitArgError("Unrecognized board size value", name);
\r
1555 return bs; /* not reached */
\r
1560 StringGet(void *getClosure)
\r
1562 char **p = (char **) getClosure;
\r
1567 FileGet(void *getClosure)
\r
1570 FILE* f = (FILE*) getClosure;
\r
1573 if (c == '\r') c = getc(f); // work around DOS format files by bypassing the '\r' completely
\r
1580 /* Parse settings file named "name". If file found, return the
\r
1581 full name in fullname and return TRUE; else return FALSE */
\r
1583 ParseSettingsFile(char *name, char fullname[MSG_SIZ])
\r
1587 int ok; char buf[MSG_SIZ];
\r
1589 ok = SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy);
\r
1590 if(!ok && strchr(name, '.') == NULL) { // [HGM] append default file-name extension '.ini' when needed
\r
1591 sprintf(buf, "%s.ini", name);
\r
1592 ok = SearchPath(installDir, buf, NULL, MSG_SIZ, fullname, &dummy);
\r
1595 f = fopen(fullname, "r");
\r
1597 ParseArgs(FileGet, f);
\r
1606 ParseArgs(GetFunc get, void *cl)
\r
1608 char argName[ARG_MAX];
\r
1609 char argValue[ARG_MAX];
\r
1610 ArgDescriptor *ad;
\r
1619 while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);
\r
1620 if (ch == NULLCHAR) break;
\r
1622 /* Comment to end of line */
\r
1624 while (ch != '\n' && ch != NULLCHAR) ch = get(cl);
\r
1626 } else if (ch == '/' || ch == '-') {
\r
1629 while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&
\r
1630 ch != '\n' && ch != '\t') {
\r
1636 for (ad = argDescriptors; ad->argName != NULL; ad++)
\r
1637 if (strcmp(ad->argName, argName + 1) == 0) break;
\r
1639 if (ad->argName == NULL)
\r
1640 ExitArgError("Unrecognized argument", argName);
\r
1642 } else if (ch == '@') {
\r
1643 /* Indirection file */
\r
1644 ad = &argDescriptorIndirection;
\r
1647 /* Positional argument */
\r
1648 ad = &argDescriptors[posarg++];
\r
1649 strcpy(argName, ad->argName);
\r
1652 if (ad->argType == ArgTrue) {
\r
1653 *(Boolean *) ad->argLoc = TRUE;
\r
1656 if (ad->argType == ArgFalse) {
\r
1657 *(Boolean *) ad->argLoc = FALSE;
\r
1661 while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
\r
1662 if (ch == NULLCHAR || ch == '\n') {
\r
1663 ExitArgError("No value provided for argument", argName);
\r
1667 // Quoting with { }. No characters have to (or can) be escaped.
\r
1668 // Thus the string cannot contain a '}' character.
\r
1688 } else if (ch == '\'' || ch == '"') {
\r
1689 // Quoting with ' ' or " ", with \ as escape character.
\r
1690 // Inconvenient for long strings that may contain Windows filenames.
\r
1707 if (ch == start) {
\r
1716 if (ad->argType == ArgFilename
\r
1717 || ad->argType == ArgSettingsFilename) {
\r
1723 ExitArgError("Incomplete \\ escape in value for", argName);
\r
1747 for (i = 0; i < 3; i++) {
\r
1748 if (ch >= '0' && ch <= '7') {
\r
1749 octval = octval*8 + (ch - '0');
\r
1756 *q++ = (char) octval;
\r
1767 while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {
\r
1774 switch (ad->argType) {
\r
1776 *(int *) ad->argLoc = atoi(argValue);
\r
1780 *(int *) ad->argLoc = atoi(argValue) + boardX; // [HGM] placement: translate stored relative to absolute
\r
1784 *(int *) ad->argLoc = atoi(argValue) + boardY; // (this is really kludgey, it should be done where used...)
\r
1788 *(int *) ad->argLoc = atoi(argValue);
\r
1789 EnsureOnScreen(&boardX, &boardY, minX, minY);
\r
1793 *(float *) ad->argLoc = (float) atof(argValue);
\r
1798 *(char **) ad->argLoc = strdup(argValue);
\r
1801 case ArgSettingsFilename:
\r
1803 char fullname[MSG_SIZ];
\r
1804 if (ParseSettingsFile(argValue, fullname)) {
\r
1805 if (ad->argLoc != NULL) {
\r
1806 *(char **) ad->argLoc = strdup(fullname);
\r
1809 if (ad->argLoc != NULL) {
\r
1811 ExitArgError("Failed to open indirection file", argValue);
\r
1818 switch (argValue[0]) {
\r
1821 *(Boolean *) ad->argLoc = TRUE;
\r
1825 *(Boolean *) ad->argLoc = FALSE;
\r
1828 ExitArgError("Unrecognized boolean argument value", argValue);
\r
1834 *(COLORREF *)ad->argLoc = ParseColorName(argValue);
\r
1837 case ArgAttribs: {
\r
1838 ColorClass cc = (ColorClass)ad->argLoc;
\r
1839 ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);
\r
1843 case ArgBoardSize:
\r
1844 *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);
\r
1848 ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);
\r
1851 case ArgCommSettings:
\r
1852 ParseCommSettings(argValue, &dcb);
\r
1856 ExitArgError("Unrecognized argument", argValue);
\r
1865 LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
\r
1867 HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
\r
1868 lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);
\r
1871 lf->lfEscapement = 0;
\r
1872 lf->lfOrientation = 0;
\r
1873 lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;
\r
1874 lf->lfItalic = mfp->italic;
\r
1875 lf->lfUnderline = mfp->underline;
\r
1876 lf->lfStrikeOut = mfp->strikeout;
\r
1877 lf->lfCharSet = mfp->charset;
\r
1878 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
1879 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
1880 lf->lfQuality = DEFAULT_QUALITY;
\r
1881 lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
\r
1882 strcpy(lf->lfFaceName, mfp->faceName);
\r
1886 CreateFontInMF(MyFont *mf)
\r
1888 LFfromMFP(&mf->lf, &mf->mfp);
\r
1889 if (mf->hf) DeleteObject(mf->hf);
\r
1890 mf->hf = CreateFontIndirect(&mf->lf);
\r
1894 SetDefaultTextAttribs()
\r
1897 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1898 ParseAttribs(&textAttribs[cc].color,
\r
1899 &textAttribs[cc].effects,
\r
1900 defaultTextAttribs[cc]);
\r
1905 SetDefaultSounds()
\r
1909 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1910 textAttribs[cc].sound.name = strdup("");
\r
1911 textAttribs[cc].sound.data = NULL;
\r
1913 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1914 sounds[sc].name = strdup("");
\r
1915 sounds[sc].data = NULL;
\r
1917 sounds[(int)SoundBell].name = strdup(SOUND_BELL);
\r
1925 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1926 MyLoadSound(&textAttribs[cc].sound);
\r
1928 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1929 MyLoadSound(&sounds[sc]);
\r
1934 InitAppData(LPSTR lpCmdLine)
\r
1937 char buf[ARG_MAX], currDir[MSG_SIZ];
\r
1940 programName = szAppName;
\r
1942 /* Initialize to defaults */
\r
1943 lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);
\r
1944 darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);
\r
1945 whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);
\r
1946 blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);
\r
1947 highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);
\r
1948 premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);
\r
1949 consoleBackgroundColor = ParseColorName(COLOR_BKGD);
\r
1950 SetDefaultTextAttribs();
\r
1951 SetDefaultSounds();
\r
1952 appData.movesPerSession = MOVES_PER_SESSION;
\r
1953 appData.initString = INIT_STRING;
\r
1954 appData.secondInitString = INIT_STRING;
\r
1955 appData.firstComputerString = COMPUTER_STRING;
\r
1956 appData.secondComputerString = COMPUTER_STRING;
\r
1957 appData.firstChessProgram = FIRST_CHESS_PROGRAM;
\r
1958 appData.secondChessProgram = SECOND_CHESS_PROGRAM;
\r
1959 appData.firstPlaysBlack = FALSE;
\r
1960 appData.noChessProgram = FALSE;
\r
1961 chessProgram = FALSE;
\r
1962 appData.firstHost = FIRST_HOST;
\r
1963 appData.secondHost = SECOND_HOST;
\r
1964 appData.firstDirectory = FIRST_DIRECTORY;
\r
1965 appData.secondDirectory = SECOND_DIRECTORY;
\r
1966 appData.bitmapDirectory = "";
\r
1967 appData.remoteShell = REMOTE_SHELL;
\r
1968 appData.remoteUser = "";
\r
1969 appData.timeDelay = TIME_DELAY;
\r
1970 appData.timeControl = TIME_CONTROL;
\r
1971 appData.timeIncrement = TIME_INCREMENT;
\r
1972 appData.icsActive = FALSE;
\r
1973 appData.icsHost = "";
\r
1974 appData.icsPort = ICS_PORT;
\r
1975 appData.icsCommPort = ICS_COMM_PORT;
\r
1976 appData.icsLogon = ICS_LOGON;
\r
1977 appData.icsHelper = "";
\r
1978 appData.useTelnet = FALSE;
\r
1979 appData.telnetProgram = TELNET_PROGRAM;
\r
1980 appData.gateway = "";
\r
1981 appData.loadGameFile = "";
\r
1982 appData.loadGameIndex = 0;
\r
1983 appData.saveGameFile = "";
\r
1984 appData.autoSaveGames = FALSE;
\r
1985 appData.loadPositionFile = "";
\r
1986 appData.loadPositionIndex = 1;
\r
1987 appData.savePositionFile = "";
\r
1988 appData.matchMode = FALSE;
\r
1989 appData.matchGames = 0;
\r
1990 appData.monoMode = FALSE;
\r
1991 appData.debugMode = FALSE;
\r
1992 appData.clockMode = TRUE;
\r
1993 boardSize = (BoardSize) -1; /* determine by screen size */
\r
1994 appData.Iconic = FALSE; /*unused*/
\r
1995 appData.searchTime = "";
\r
1996 appData.searchDepth = 0;
\r
1997 appData.showCoords = FALSE;
\r
1998 appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/
\r
1999 appData.autoCallFlag = FALSE;
\r
2000 appData.flipView = FALSE;
\r
2001 appData.autoFlipView = TRUE;
\r
2002 appData.cmailGameName = "";
\r
2003 appData.alwaysPromoteToQueen = FALSE;
\r
2004 appData.oldSaveStyle = FALSE;
\r
2005 appData.quietPlay = FALSE;
\r
2006 appData.showThinking = FALSE;
\r
2007 appData.ponderNextMove = TRUE;
\r
2008 appData.periodicUpdates = TRUE;
\r
2009 appData.popupExitMessage = TRUE;
\r
2010 appData.popupMoveErrors = FALSE;
\r
2011 appData.autoObserve = FALSE;
\r
2012 appData.autoComment = FALSE;
\r
2013 appData.animate = TRUE;
\r
2014 appData.animSpeed = 10;
\r
2015 appData.animateDragging = TRUE;
\r
2016 appData.highlightLastMove = TRUE;
\r
2017 appData.getMoveList = TRUE;
\r
2018 appData.testLegality = TRUE;
\r
2019 appData.premove = TRUE;
\r
2020 appData.premoveWhite = FALSE;
\r
2021 appData.premoveWhiteText = "";
\r
2022 appData.premoveBlack = FALSE;
\r
2023 appData.premoveBlackText = "";
\r
2024 appData.icsAlarm = TRUE;
\r
2025 appData.icsAlarmTime = 5000;
\r
2026 appData.autoRaiseBoard = TRUE;
\r
2027 appData.localLineEditing = TRUE;
\r
2028 appData.colorize = TRUE;
\r
2029 appData.reuseFirst = TRUE;
\r
2030 appData.reuseSecond = TRUE;
\r
2031 appData.blindfold = FALSE;
\r
2032 appData.icsEngineAnalyze = FALSE;
\r
2033 memset(&dcb, 0, sizeof(DCB)); // required by VS 2002 +
\r
2034 dcb.DCBlength = sizeof(DCB);
\r
2035 dcb.BaudRate = 9600;
\r
2036 dcb.fBinary = TRUE;
\r
2037 dcb.fParity = FALSE;
\r
2038 dcb.fOutxCtsFlow = FALSE;
\r
2039 dcb.fOutxDsrFlow = FALSE;
\r
2040 dcb.fDtrControl = DTR_CONTROL_ENABLE;
\r
2041 dcb.fDsrSensitivity = FALSE;
\r
2042 dcb.fTXContinueOnXoff = TRUE;
\r
2043 dcb.fOutX = FALSE;
\r
2045 dcb.fNull = FALSE;
\r
2046 dcb.fRtsControl = RTS_CONTROL_ENABLE;
\r
2047 dcb.fAbortOnError = FALSE;
\r
2049 dcb.Parity = SPACEPARITY;
\r
2050 dcb.StopBits = ONESTOPBIT;
\r
2051 settingsFileName = SETTINGS_FILE;
\r
2052 saveSettingsOnExit = TRUE;
\r
2053 boardX = CW_USEDEFAULT;
\r
2054 boardY = CW_USEDEFAULT;
\r
2055 analysisX = CW_USEDEFAULT;
\r
2056 analysisY = CW_USEDEFAULT;
\r
2057 analysisW = CW_USEDEFAULT;
\r
2058 analysisH = CW_USEDEFAULT;
\r
2059 commentX = CW_USEDEFAULT;
\r
2060 commentY = CW_USEDEFAULT;
\r
2061 commentW = CW_USEDEFAULT;
\r
2062 commentH = CW_USEDEFAULT;
\r
2063 editTagsX = CW_USEDEFAULT;
\r
2064 editTagsY = CW_USEDEFAULT;
\r
2065 editTagsW = CW_USEDEFAULT;
\r
2066 editTagsH = CW_USEDEFAULT;
\r
2067 icsTextMenuString = ICS_TEXT_MENU_DEFAULT;
\r
2068 icsNames = ICS_NAMES;
\r
2069 firstChessProgramNames = FCP_NAMES;
\r
2070 secondChessProgramNames = SCP_NAMES;
\r
2071 appData.initialMode = "";
\r
2072 appData.variant = "normal";
\r
2073 appData.firstProtocolVersion = PROTOVER;
\r
2074 appData.secondProtocolVersion = PROTOVER;
\r
2075 appData.showButtonBar = TRUE;
\r
2077 /* [AS] New properties (see comments in header file) */
\r
2078 appData.firstScoreIsAbsolute = FALSE;
\r
2079 appData.secondScoreIsAbsolute = FALSE;
\r
2080 appData.saveExtendedInfoInPGN = FALSE;
\r
2081 appData.hideThinkingFromHuman = FALSE;
\r
2082 appData.liteBackTextureFile = "";
\r
2083 appData.liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
2084 appData.darkBackTextureFile = "";
\r
2085 appData.darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
2086 appData.renderPiecesWithFont = "";
\r
2087 appData.fontToPieceTable = "";
\r
2088 appData.fontBackColorWhite = 0;
\r
2089 appData.fontForeColorWhite = 0;
\r
2090 appData.fontBackColorBlack = 0;
\r
2091 appData.fontForeColorBlack = 0;
\r
2092 appData.fontPieceSize = 80;
\r
2093 appData.overrideLineGap = 1;
\r
2094 appData.adjudicateLossThreshold = 0;
\r
2095 appData.delayBeforeQuit = 0;
\r
2096 appData.delayAfterQuit = 0;
\r
2097 appData.nameOfDebugFile = "winboard.debug";
\r
2098 appData.pgnEventHeader = "Computer Chess Game";
\r
2099 appData.defaultFrcPosition = -1;
\r
2100 appData.gameListTags = GLT_DEFAULT_TAGS;
\r
2101 appData.saveOutOfBookInfo = TRUE;
\r
2102 appData.showEvalInMoveHistory = TRUE;
\r
2103 appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );
\r
2104 appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );
\r
2105 appData.highlightMoveWithArrow = FALSE;
\r
2106 appData.highlightArrowColor = ParseColorName( "#FFFF80" );
\r
2107 appData.useStickyWindows = TRUE;
\r
2108 appData.adjudicateDrawMoves = 0;
\r
2109 appData.autoDisplayComment = TRUE;
\r
2110 appData.autoDisplayTags = TRUE;
\r
2111 appData.firstIsUCI = FALSE;
\r
2112 appData.secondIsUCI = FALSE;
\r
2113 appData.firstHasOwnBookUCI = TRUE;
\r
2114 appData.secondHasOwnBookUCI = TRUE;
\r
2115 appData.polyglotDir = "";
\r
2116 appData.usePolyglotBook = FALSE;
\r
2117 appData.polyglotBook = "";
\r
2118 appData.defaultHashSize = 64;
\r
2119 appData.defaultCacheSizeEGTB = 4;
\r
2120 appData.defaultPathEGTB = "c:\\egtb";
\r
2121 appData.firstOptions = "";
\r
2122 appData.secondOptions = "";
\r
2124 InitWindowPlacement( &wpGameList );
\r
2125 InitWindowPlacement( &wpMoveHistory );
\r
2126 InitWindowPlacement( &wpEvalGraph );
\r
2127 InitWindowPlacement( &wpEngineOutput );
\r
2128 InitWindowPlacement( &wpConsole );
\r
2130 /* [HGM] User-selectable board size, adjudication control, miscellaneous */
\r
2131 appData.NrFiles = -1;
\r
2132 appData.NrRanks = -1;
\r
2133 appData.holdingsSize = -1;
\r
2134 appData.testClaims = FALSE;
\r
2135 appData.checkMates = FALSE;
\r
2136 appData.materialDraws= FALSE;
\r
2137 appData.trivialDraws = FALSE;
\r
2138 appData.ruleMoves = 51;
\r
2139 appData.drawRepeats = 6;
\r
2140 appData.matchPause = 10000;
\r
2141 appData.alphaRank = FALSE;
\r
2142 appData.allWhite = FALSE;
\r
2143 appData.upsideDown = FALSE;
\r
2144 appData.serverPause = 15;
\r
2145 appData.serverMovesName = NULL;
\r
2146 appData.suppressLoadMoves = FALSE;
\r
2147 appData.firstTimeOdds = 1;
\r
2148 appData.secondTimeOdds = 1;
\r
2149 appData.firstAccumulateTC = 1; // combine previous and current sessions
\r
2150 appData.secondAccumulateTC = 1;
\r
2151 appData.firstNPS = -1; // [HGM] nps: use wall-clock time
\r
2152 appData.secondNPS = -1;
\r
2153 appData.engineComments = 1;
\r
2154 appData.smpCores = 1; // [HGM] SMP: max nr of cores
\r
2155 appData.egtFormats = "";
\r
2158 appData.zippyTalk = ZIPPY_TALK;
\r
2159 appData.zippyPlay = ZIPPY_PLAY;
\r
2160 appData.zippyLines = ZIPPY_LINES;
\r
2161 appData.zippyPinhead = ZIPPY_PINHEAD;
\r
2162 appData.zippyPassword = ZIPPY_PASSWORD;
\r
2163 appData.zippyPassword2 = ZIPPY_PASSWORD2;
\r
2164 appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;
\r
2165 appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;
\r
2166 appData.zippyUseI = ZIPPY_USE_I;
\r
2167 appData.zippyBughouse = ZIPPY_BUGHOUSE;
\r
2168 appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;
\r
2169 appData.zippyGameEnd = ZIPPY_GAME_END;
\r
2170 appData.zippyGameStart = ZIPPY_GAME_START;
\r
2171 appData.zippyAdjourn = ZIPPY_ADJOURN;
\r
2172 appData.zippyAbort = ZIPPY_ABORT;
\r
2173 appData.zippyVariants = ZIPPY_VARIANTS;
\r
2174 appData.zippyMaxGames = ZIPPY_MAX_GAMES;
\r
2175 appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;
\r
2178 /* Point font array elements to structures and
\r
2179 parse default font names */
\r
2180 for (i=0; i<NUM_FONTS; i++) {
\r
2181 for (j=0; j<NUM_SIZES; j++) {
\r
2182 font[j][i] = &fontRec[j][i];
\r
2183 ParseFontName(font[j][i]->def, &font[j][i]->mfp);
\r
2187 /* Parse default settings file if any */
\r
2188 if (ParseSettingsFile(settingsFileName, buf)) {
\r
2189 settingsFileName = strdup(buf);
\r
2192 /* Parse command line */
\r
2193 ParseArgs(StringGet, &lpCmdLine);
\r
2195 /* [HGM] make sure board size is acceptable */
\r
2196 if(appData.NrFiles > BOARD_SIZE ||
\r
2197 appData.NrRanks > BOARD_SIZE )
\r
2198 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
2200 /* [HGM] After parsing the options from the .ini file, and overruling them
\r
2201 * with options from the command line, we now make an even higher priority
\r
2202 * overrule by WB options attached to the engine command line. This so that
\r
2203 * tournament managers can use WB options (such as /timeOdds) that follow
\r
2206 if(appData.firstChessProgram != NULL) {
\r
2207 char *p = StrStr(appData.firstChessProgram, "WBopt");
\r
2208 static char *f = "first";
\r
2209 char buf[MSG_SIZ], *q = buf;
\r
2210 if(p != NULL) { // engine command line contains WinBoard options
\r
2211 sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"
\r
2212 ParseArgs(StringGet, &q);
\r
2213 p[-1] = 0; // cut them offengine command line
\r
2216 // now do same for second chess program
\r
2217 if(appData.secondChessProgram != NULL) {
\r
2218 char *p = StrStr(appData.secondChessProgram, "WBopt");
\r
2219 static char *s = "second";
\r
2220 char buf[MSG_SIZ], *q = buf;
\r
2221 if(p != NULL) { // engine command line contains WinBoard options
\r
2222 sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"
\r
2223 ParseArgs(StringGet, &q);
\r
2224 p[-1] = 0; // cut them offengine command line
\r
2229 /* Propagate options that affect others */
\r
2230 if (appData.matchMode || appData.matchGames) chessProgram = TRUE;
\r
2231 if (appData.icsActive || appData.noChessProgram) {
\r
2232 chessProgram = FALSE; /* not local chess program mode */
\r
2235 /* Open startup dialog if needed */
\r
2236 if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||
\r
2237 (appData.icsActive && *appData.icsHost == NULLCHAR) ||
\r
2238 (chessProgram && (*appData.firstChessProgram == NULLCHAR ||
\r
2239 *appData.secondChessProgram == NULLCHAR))) {
\r
2242 lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);
\r
2243 DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);
\r
2244 FreeProcInstance(lpProc);
\r
2247 /* Make sure save files land in the right (?) directory */
\r
2248 if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {
\r
2249 appData.saveGameFile = strdup(buf);
\r
2251 if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {
\r
2252 appData.savePositionFile = strdup(buf);
\r
2255 /* Finish initialization for fonts and sounds */
\r
2256 for (i=0; i<NUM_FONTS; i++) {
\r
2257 for (j=0; j<NUM_SIZES; j++) {
\r
2258 CreateFontInMF(font[j][i]);
\r
2261 /* xboard, and older WinBoards, controlled the move sound with the
\r
2262 appData.ringBellAfterMoves option. In the current WinBoard, we
\r
2263 always turn the option on (so that the backend will call us),
\r
2264 then let the user turn the sound off by setting it to silence if
\r
2265 desired. To accommodate old winboard.ini files saved by old
\r
2266 versions of WinBoard, we also turn off the sound if the option
\r
2267 was initially set to false. */
\r
2268 if (!appData.ringBellAfterMoves) {
\r
2269 sounds[(int)SoundMove].name = strdup("");
\r
2270 appData.ringBellAfterMoves = TRUE;
\r
2272 GetCurrentDirectory(MSG_SIZ, currDir);
\r
2273 SetCurrentDirectory(installDir);
\r
2275 SetCurrentDirectory(currDir);
\r
2277 p = icsTextMenuString;
\r
2278 if (p[0] == '@') {
\r
2279 FILE* f = fopen(p + 1, "r");
\r
2281 DisplayFatalError(p + 1, errno, 2);
\r
2284 i = fread(buf, 1, sizeof(buf)-1, f);
\r
2286 buf[i] = NULLCHAR;
\r
2289 ParseIcsTextMenu(strdup(p));
\r
2296 HMENU hmenu = GetMenu(hwndMain);
\r
2298 (void) EnableMenuItem(hmenu, IDM_CommPort,
\r
2299 MF_BYCOMMAND|((appData.icsActive &&
\r
2300 *appData.icsCommPort != NULLCHAR) ?
\r
2301 MF_ENABLED : MF_GRAYED));
\r
2302 (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,
\r
2303 MF_BYCOMMAND|(saveSettingsOnExit ?
\r
2304 MF_CHECKED : MF_UNCHECKED));
\r
2309 SaveSettings(char* name)
\r
2312 ArgDescriptor *ad;
\r
2313 WINDOWPLACEMENT wp;
\r
2314 char dir[MSG_SIZ];
\r
2316 if (!hwndMain) return;
\r
2318 GetCurrentDirectory(MSG_SIZ, dir);
\r
2319 SetCurrentDirectory(installDir);
\r
2320 f = fopen(name, "w");
\r
2321 SetCurrentDirectory(dir);
\r
2323 DisplayError(name, errno);
\r
2326 fprintf(f, ";\n");
\r
2327 fprintf(f, "; %s Save Settings file\n", PACKAGE_STRING);
\r
2328 fprintf(f, ";\n");
\r
2329 fprintf(f, "; You can edit the values of options that are already set in this file,\n");
\r
2330 fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");
\r
2331 fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");
\r
2332 fprintf(f, ";\n");
\r
2334 wp.length = sizeof(WINDOWPLACEMENT);
\r
2335 GetWindowPlacement(hwndMain, &wp);
\r
2336 boardX = wp.rcNormalPosition.left;
\r
2337 boardY = wp.rcNormalPosition.top;
\r
2339 if (hwndConsole) {
\r
2340 GetWindowPlacement(hwndConsole, &wp);
\r
2341 wpConsole.x = wp.rcNormalPosition.left;
\r
2342 wpConsole.y = wp.rcNormalPosition.top;
\r
2343 wpConsole.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2344 wpConsole.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2347 if (analysisDialog) {
\r
2348 GetWindowPlacement(analysisDialog, &wp);
\r
2349 analysisX = wp.rcNormalPosition.left;
\r
2350 analysisY = wp.rcNormalPosition.top;
\r
2351 analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2352 analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2355 if (commentDialog) {
\r
2356 GetWindowPlacement(commentDialog, &wp);
\r
2357 commentX = wp.rcNormalPosition.left;
\r
2358 commentY = wp.rcNormalPosition.top;
\r
2359 commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2360 commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2363 if (editTagsDialog) {
\r
2364 GetWindowPlacement(editTagsDialog, &wp);
\r
2365 editTagsX = wp.rcNormalPosition.left;
\r
2366 editTagsY = wp.rcNormalPosition.top;
\r
2367 editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2368 editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2371 if (gameListDialog) {
\r
2372 GetWindowPlacement(gameListDialog, &wp);
\r
2373 wpGameList.x = wp.rcNormalPosition.left;
\r
2374 wpGameList.y = wp.rcNormalPosition.top;
\r
2375 wpGameList.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2376 wpGameList.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2379 /* [AS] Move history */
\r
2380 wpMoveHistory.visible = MoveHistoryIsUp();
\r
2382 if( moveHistoryDialog ) {
\r
2383 GetWindowPlacement(moveHistoryDialog, &wp);
\r
2384 wpMoveHistory.x = wp.rcNormalPosition.left;
\r
2385 wpMoveHistory.y = wp.rcNormalPosition.top;
\r
2386 wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2387 wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2390 /* [AS] Eval graph */
\r
2391 wpEvalGraph.visible = EvalGraphIsUp();
\r
2393 if( evalGraphDialog ) {
\r
2394 GetWindowPlacement(evalGraphDialog, &wp);
\r
2395 wpEvalGraph.x = wp.rcNormalPosition.left;
\r
2396 wpEvalGraph.y = wp.rcNormalPosition.top;
\r
2397 wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2398 wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2401 /* [AS] Engine output */
\r
2402 wpEngineOutput.visible = EngineOutputIsUp();
\r
2404 if( engineOutputDialog ) {
\r
2405 GetWindowPlacement(engineOutputDialog, &wp);
\r
2406 wpEngineOutput.x = wp.rcNormalPosition.left;
\r
2407 wpEngineOutput.y = wp.rcNormalPosition.top;
\r
2408 wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2409 wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2412 for (ad = argDescriptors; ad->argName != NULL; ad++) {
\r
2413 if (!ad->save) continue;
\r
2414 switch (ad->argType) {
\r
2417 char *p = *(char **)ad->argLoc;
\r
2418 if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {
\r
2419 /* Quote multiline values or \-containing values
\r
2420 with { } if possible */
\r
2421 fprintf(f, "/%s={%s}\n", ad->argName, p);
\r
2423 /* Else quote with " " */
\r
2424 fprintf(f, "/%s=\"", ad->argName);
\r
2426 if (*p == '\n') fprintf(f, "\n");
\r
2427 else if (*p == '\r') fprintf(f, "\\r");
\r
2428 else if (*p == '\t') fprintf(f, "\\t");
\r
2429 else if (*p == '\b') fprintf(f, "\\b");
\r
2430 else if (*p == '\f') fprintf(f, "\\f");
\r
2431 else if (*p < ' ') fprintf(f, "\\%03o", *p);
\r
2432 else if (*p == '\"') fprintf(f, "\\\"");
\r
2433 else if (*p == '\\') fprintf(f, "\\\\");
\r
2437 fprintf(f, "\"\n");
\r
2443 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);
\r
2446 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardX); // [HGM] placement: stor relative value
\r
2449 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardY);
\r
2452 fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);
\r
2455 fprintf(f, "/%s=%s\n", ad->argName,
\r
2456 (*(Boolean *)ad->argLoc) ? "true" : "false");
\r
2459 if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2462 if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2466 COLORREF color = *(COLORREF *)ad->argLoc;
\r
2467 fprintf(f, "/%s=#%02lx%02lx%02lx\n", ad->argName,
\r
2468 color&0xff, (color>>8)&0xff, (color>>16)&0xff);
\r
2473 MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];
\r
2474 fprintf(f, "/%s=\"%s%s%s%s%s#%02lx%02lx%02lx\"\n", ad->argName,
\r
2475 (ta->effects & CFE_BOLD) ? "b" : "",
\r
2476 (ta->effects & CFE_ITALIC) ? "i" : "",
\r
2477 (ta->effects & CFE_UNDERLINE) ? "u" : "",
\r
2478 (ta->effects & CFE_STRIKEOUT) ? "s" : "",
\r
2479 (ta->effects) ? " " : "",
\r
2480 ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);
\r
2484 if (strchr(*(char **)ad->argLoc, '\"')) {
\r
2485 fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);
\r
2487 fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);
\r
2490 case ArgBoardSize:
\r
2491 fprintf(f, "/%s=%s\n", ad->argName,
\r
2492 sizeInfo[*(BoardSize *)ad->argLoc].name);
\r
2497 for (bs=0; bs<NUM_SIZES; bs++) {
\r
2498 MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;
\r
2499 fprintf(f, "/size=%s ", sizeInfo[bs].name);
\r
2500 fprintf(f, "/%s=\"%s:%g%s%s%s%s%sc%d\"\n",
\r
2501 ad->argName, mfp->faceName, mfp->pointSize,
\r
2502 mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",
\r
2503 mfp->bold ? "b" : "",
\r
2504 mfp->italic ? "i" : "",
\r
2505 mfp->underline ? "u" : "",
\r
2506 mfp->strikeout ? "s" : "",
\r
2507 (int)mfp->charset);
\r
2511 case ArgCommSettings:
\r
2512 PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);
\r
2514 case ArgSettingsFilename: ;
\r
2522 /*---------------------------------------------------------------------------*\
\r
2524 * GDI board drawing routines
\r
2526 \*---------------------------------------------------------------------------*/
\r
2528 /* [AS] Draw square using background texture */
\r
2529 static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )
\r
2534 return; /* Should never happen! */
\r
2537 SetGraphicsMode( dst, GM_ADVANCED );
\r
2544 /* X reflection */
\r
2549 x.eDx = (FLOAT) dw + dx - 1;
\r
2552 SetWorldTransform( dst, &x );
\r
2555 /* Y reflection */
\r
2561 x.eDy = (FLOAT) dh + dy - 1;
\r
2563 SetWorldTransform( dst, &x );
\r
2571 x.eDx = (FLOAT) dx;
\r
2572 x.eDy = (FLOAT) dy;
\r
2575 SetWorldTransform( dst, &x );
\r
2579 BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );
\r
2587 SetWorldTransform( dst, &x );
\r
2589 ModifyWorldTransform( dst, 0, MWT_IDENTITY );
\r
2592 /* [AS] [HGM] Make room for more piece types, so all pieces can be different */
\r
2594 PM_WP = (int) WhitePawn,
\r
2595 PM_WN = (int) WhiteKnight,
\r
2596 PM_WB = (int) WhiteBishop,
\r
2597 PM_WR = (int) WhiteRook,
\r
2598 PM_WQ = (int) WhiteQueen,
\r
2599 PM_WF = (int) WhiteFerz,
\r
2600 PM_WW = (int) WhiteWazir,
\r
2601 PM_WE = (int) WhiteAlfil,
\r
2602 PM_WM = (int) WhiteMan,
\r
2603 PM_WO = (int) WhiteCannon,
\r
2604 PM_WU = (int) WhiteUnicorn,
\r
2605 PM_WH = (int) WhiteNightrider,
\r
2606 PM_WA = (int) WhiteAngel,
\r
2607 PM_WC = (int) WhiteMarshall,
\r
2608 PM_WAB = (int) WhiteCardinal,
\r
2609 PM_WD = (int) WhiteDragon,
\r
2610 PM_WL = (int) WhiteLance,
\r
2611 PM_WS = (int) WhiteCobra,
\r
2612 PM_WV = (int) WhiteFalcon,
\r
2613 PM_WSG = (int) WhiteSilver,
\r
2614 PM_WG = (int) WhiteGrasshopper,
\r
2615 PM_WK = (int) WhiteKing,
\r
2616 PM_BP = (int) BlackPawn,
\r
2617 PM_BN = (int) BlackKnight,
\r
2618 PM_BB = (int) BlackBishop,
\r
2619 PM_BR = (int) BlackRook,
\r
2620 PM_BQ = (int) BlackQueen,
\r
2621 PM_BF = (int) BlackFerz,
\r
2622 PM_BW = (int) BlackWazir,
\r
2623 PM_BE = (int) BlackAlfil,
\r
2624 PM_BM = (int) BlackMan,
\r
2625 PM_BO = (int) BlackCannon,
\r
2626 PM_BU = (int) BlackUnicorn,
\r
2627 PM_BH = (int) BlackNightrider,
\r
2628 PM_BA = (int) BlackAngel,
\r
2629 PM_BC = (int) BlackMarshall,
\r
2630 PM_BG = (int) BlackGrasshopper,
\r
2631 PM_BAB = (int) BlackCardinal,
\r
2632 PM_BD = (int) BlackDragon,
\r
2633 PM_BL = (int) BlackLance,
\r
2634 PM_BS = (int) BlackCobra,
\r
2635 PM_BV = (int) BlackFalcon,
\r
2636 PM_BSG = (int) BlackSilver,
\r
2637 PM_BK = (int) BlackKing
\r
2640 static HFONT hPieceFont = NULL;
\r
2641 static HBITMAP hPieceMask[(int) EmptySquare];
\r
2642 static HBITMAP hPieceFace[(int) EmptySquare];
\r
2643 static int fontBitmapSquareSize = 0;
\r
2644 static char pieceToFontChar[(int) EmptySquare] =
\r
2645 { 'p', 'n', 'b', 'r', 'q',
\r
2646 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',
\r
2647 'k', 'o', 'm', 'v', 't', 'w',
\r
2648 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',
\r
2651 extern BOOL SetCharTable( char *table, const char * map );
\r
2652 /* [HGM] moved to backend.c */
\r
2654 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )
\r
2657 BYTE r1 = GetRValue( color );
\r
2658 BYTE g1 = GetGValue( color );
\r
2659 BYTE b1 = GetBValue( color );
\r
2665 /* Create a uniform background first */
\r
2666 hbrush = CreateSolidBrush( color );
\r
2667 SetRect( &rc, 0, 0, squareSize, squareSize );
\r
2668 FillRect( hdc, &rc, hbrush );
\r
2669 DeleteObject( hbrush );
\r
2672 /* Vertical gradient, good for pawn, knight and rook, less for queen and king */
\r
2673 int steps = squareSize / 2;
\r
2676 for( i=0; i<steps; i++ ) {
\r
2677 BYTE r = r1 - (r1-r2) * i / steps;
\r
2678 BYTE g = g1 - (g1-g2) * i / steps;
\r
2679 BYTE b = b1 - (b1-b2) * i / steps;
\r
2681 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2682 SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );
\r
2683 FillRect( hdc, &rc, hbrush );
\r
2684 DeleteObject(hbrush);
\r
2687 else if( mode == 2 ) {
\r
2688 /* Diagonal gradient, good more or less for every piece */
\r
2689 POINT triangle[3];
\r
2690 HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );
\r
2691 HBRUSH hbrush_old;
\r
2692 int steps = squareSize;
\r
2695 triangle[0].x = squareSize - steps;
\r
2696 triangle[0].y = squareSize;
\r
2697 triangle[1].x = squareSize;
\r
2698 triangle[1].y = squareSize;
\r
2699 triangle[2].x = squareSize;
\r
2700 triangle[2].y = squareSize - steps;
\r
2702 for( i=0; i<steps; i++ ) {
\r
2703 BYTE r = r1 - (r1-r2) * i / steps;
\r
2704 BYTE g = g1 - (g1-g2) * i / steps;
\r
2705 BYTE b = b1 - (b1-b2) * i / steps;
\r
2707 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2708 hbrush_old = SelectObject( hdc, hbrush );
\r
2709 Polygon( hdc, triangle, 3 );
\r
2710 SelectObject( hdc, hbrush_old );
\r
2711 DeleteObject(hbrush);
\r
2716 SelectObject( hdc, hpen );
\r
2721 [AS] The method I use to create the bitmaps it a bit tricky, but it
\r
2722 seems to work ok. The main problem here is to find the "inside" of a chess
\r
2723 piece: follow the steps as explained below.
\r
2725 static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
\r
2729 COLORREF chroma = RGB(0xFF,0x00,0xFF);
\r
2733 int backColor = whitePieceColor;
\r
2734 int foreColor = blackPieceColor;
\r
2736 if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {
\r
2737 backColor = appData.fontBackColorWhite;
\r
2738 foreColor = appData.fontForeColorWhite;
\r
2740 else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {
\r
2741 backColor = appData.fontBackColorBlack;
\r
2742 foreColor = appData.fontForeColorBlack;
\r
2746 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2748 hbm_old = SelectObject( hdc, hbm );
\r
2752 rc.right = squareSize;
\r
2753 rc.bottom = squareSize;
\r
2755 /* Step 1: background is now black */
\r
2756 FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );
\r
2758 GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );
\r
2760 pt.x = (squareSize - sz.cx) / 2;
\r
2761 pt.y = (squareSize - sz.cy) / 2;
\r
2763 SetBkMode( hdc, TRANSPARENT );
\r
2764 SetTextColor( hdc, chroma );
\r
2765 /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */
\r
2766 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2768 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
\r
2769 /* Step 3: the area outside the piece is filled with white */
\r
2770 // FloodFill( hdc, 0, 0, chroma );
\r
2771 ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );
\r
2772 ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big
\r
2773 ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );
\r
2774 ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );
\r
2775 SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
\r
2777 Step 4: this is the tricky part, the area inside the piece is filled with black,
\r
2778 but if the start point is not inside the piece we're lost!
\r
2779 There should be a better way to do this... if we could create a region or path
\r
2780 from the fill operation we would be fine for example.
\r
2782 // FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );
\r
2783 ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );
\r
2785 { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */
\r
2786 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2787 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2789 SelectObject( dc2, bm2 );
\r
2790 BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy
\r
2791 BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2792 BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2793 BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2794 BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2797 DeleteObject( bm2 );
\r
2800 SetTextColor( hdc, 0 );
\r
2802 Step 5: some fonts have "disconnected" areas that are skipped by the fill:
\r
2803 draw the piece again in black for safety.
\r
2805 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2807 SelectObject( hdc, hbm_old );
\r
2809 if( hPieceMask[index] != NULL ) {
\r
2810 DeleteObject( hPieceMask[index] );
\r
2813 hPieceMask[index] = hbm;
\r
2816 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2818 SelectObject( hdc, hbm );
\r
2821 HDC dc1 = CreateCompatibleDC( hdc_window );
\r
2822 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2823 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2825 SelectObject( dc1, hPieceMask[index] );
\r
2826 SelectObject( dc2, bm2 );
\r
2827 FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );
\r
2828 BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );
\r
2831 Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves
\r
2832 the piece background and deletes (makes transparent) the rest.
\r
2833 Thanks to that mask, we are free to paint the background with the greates
\r
2834 freedom, as we'll be able to mask off the unwanted parts when finished.
\r
2835 We use this, to make gradients and give the pieces a "roundish" look.
\r
2837 SetPieceBackground( hdc, backColor, 2 );
\r
2838 BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );
\r
2842 DeleteObject( bm2 );
\r
2845 SetTextColor( hdc, foreColor );
\r
2846 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2848 SelectObject( hdc, hbm_old );
\r
2850 if( hPieceFace[index] != NULL ) {
\r
2851 DeleteObject( hPieceFace[index] );
\r
2854 hPieceFace[index] = hbm;
\r
2857 static int TranslatePieceToFontPiece( int piece )
\r
2887 case BlackMarshall:
\r
2891 case BlackNightrider:
\r
2897 case BlackUnicorn:
\r
2901 case BlackGrasshopper:
\r
2913 case BlackCardinal:
\r
2920 case WhiteMarshall:
\r
2924 case WhiteNightrider:
\r
2930 case WhiteUnicorn:
\r
2934 case WhiteGrasshopper:
\r
2946 case WhiteCardinal:
\r
2955 void CreatePiecesFromFont()
\r
2958 HDC hdc_window = NULL;
\r
2964 if( fontBitmapSquareSize < 0 ) {
\r
2965 /* Something went seriously wrong in the past: do not try to recreate fonts! */
\r
2969 if( appData.renderPiecesWithFont == NULL || appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {
\r
2970 fontBitmapSquareSize = -1;
\r
2974 if( fontBitmapSquareSize != squareSize ) {
\r
2975 hdc_window = GetDC( hwndMain );
\r
2976 hdc = CreateCompatibleDC( hdc_window );
\r
2978 if( hPieceFont != NULL ) {
\r
2979 DeleteObject( hPieceFont );
\r
2982 for( i=0; i<=(int)BlackKing; i++ ) {
\r
2983 hPieceMask[i] = NULL;
\r
2984 hPieceFace[i] = NULL;
\r
2990 if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {
\r
2991 fontHeight = appData.fontPieceSize;
\r
2994 fontHeight = (fontHeight * squareSize) / 100;
\r
2996 lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
\r
2998 lf.lfEscapement = 0;
\r
2999 lf.lfOrientation = 0;
\r
3000 lf.lfWeight = FW_NORMAL;
\r
3002 lf.lfUnderline = 0;
\r
3003 lf.lfStrikeOut = 0;
\r
3004 lf.lfCharSet = DEFAULT_CHARSET;
\r
3005 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
3006 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
3007 lf.lfQuality = PROOF_QUALITY;
\r
3008 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
\r
3009 strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );
\r
3010 lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';
\r
3012 hPieceFont = CreateFontIndirect( &lf );
\r
3014 if( hPieceFont == NULL ) {
\r
3015 fontBitmapSquareSize = -2;
\r
3018 /* Setup font-to-piece character table */
\r
3019 if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {
\r
3020 /* No (or wrong) global settings, try to detect the font */
\r
3021 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {
\r
3023 SetCharTable(pieceToFontChar, "phbrqkojntwl");
\r
3025 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {
\r
3026 /* DiagramTT* family */
\r
3027 SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");
\r
3029 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {
\r
3030 /* Fairy symbols */
\r
3031 SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
\r
3033 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {
\r
3034 /* Good Companion (Some characters get warped as literal :-( */
\r
3035 char s[] = "1cmWG0ñueOS¯®oYI23wgQU";
\r
3036 s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;
\r
3037 SetCharTable(pieceToFontChar, s);
\r
3040 /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */
\r
3041 SetCharTable(pieceToFontChar, "pnbrqkomvtwl");
\r
3045 /* Create bitmaps */
\r
3046 hfont_old = SelectObject( hdc, hPieceFont );
\r
3047 for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */
\r
3048 if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */
\r
3049 CreatePieceMaskFromFont( hdc_window, hdc, i );
\r
3051 SelectObject( hdc, hfont_old );
\r
3053 fontBitmapSquareSize = squareSize;
\r
3057 if( hdc != NULL ) {
\r
3061 if( hdc_window != NULL ) {
\r
3062 ReleaseDC( hwndMain, hdc_window );
\r
3067 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)
\r
3071 sprintf(name, "%s%d%s", piece, squareSize, suffix);
\r
3072 if (gameInfo.event &&
\r
3073 strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&
\r
3074 strcmp(name, "k80s") == 0) {
\r
3075 strcpy(name, "tim");
\r
3077 return LoadBitmap(hinst, name);
\r
3081 /* Insert a color into the program's logical palette
\r
3082 structure. This code assumes the given color is
\r
3083 the result of the RGB or PALETTERGB macro, and it
\r
3084 knows how those macros work (which is documented).
\r
3087 InsertInPalette(COLORREF color)
\r
3089 LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);
\r
3091 if (pLogPal->palNumEntries++ >= PALETTESIZE) {
\r
3092 DisplayFatalError("Too many colors", 0, 1);
\r
3093 pLogPal->palNumEntries--;
\r
3097 pe->peFlags = (char) 0;
\r
3098 pe->peRed = (char) (0xFF & color);
\r
3099 pe->peGreen = (char) (0xFF & (color >> 8));
\r
3100 pe->peBlue = (char) (0xFF & (color >> 16));
\r
3106 InitDrawingColors()
\r
3108 if (pLogPal == NULL) {
\r
3109 /* Allocate enough memory for a logical palette with
\r
3110 * PALETTESIZE entries and set the size and version fields
\r
3111 * of the logical palette structure.
\r
3113 pLogPal = (NPLOGPALETTE)
\r
3114 LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +
\r
3115 (sizeof(PALETTEENTRY) * (PALETTESIZE))));
\r
3116 pLogPal->palVersion = 0x300;
\r
3118 pLogPal->palNumEntries = 0;
\r
3120 InsertInPalette(lightSquareColor);
\r
3121 InsertInPalette(darkSquareColor);
\r
3122 InsertInPalette(whitePieceColor);
\r
3123 InsertInPalette(blackPieceColor);
\r
3124 InsertInPalette(highlightSquareColor);
\r
3125 InsertInPalette(premoveHighlightColor);
\r
3127 /* create a logical color palette according the information
\r
3128 * in the LOGPALETTE structure.
\r
3130 hPal = CreatePalette((LPLOGPALETTE) pLogPal);
\r
3132 lightSquareBrush = CreateSolidBrush(lightSquareColor);
\r
3133 blackSquareBrush = CreateSolidBrush(blackPieceColor);
\r
3134 darkSquareBrush = CreateSolidBrush(darkSquareColor);
\r
3135 whitePieceBrush = CreateSolidBrush(whitePieceColor);
\r
3136 blackPieceBrush = CreateSolidBrush(blackPieceColor);
\r
3137 iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
\r
3138 explodeBrush = CreateSolidBrush(highlightSquareColor); // [HGM] atomic
\r
3139 /* [AS] Force rendering of the font-based pieces */
\r
3140 if( fontBitmapSquareSize > 0 ) {
\r
3141 fontBitmapSquareSize = 0;
\r
3147 BoardWidth(int boardSize, int n)
\r
3148 { /* [HGM] argument n added to allow different width and height */
\r
3149 int lineGap = sizeInfo[boardSize].lineGap;
\r
3151 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3152 lineGap = appData.overrideLineGap;
\r
3155 return (n + 1) * lineGap +
\r
3156 n * sizeInfo[boardSize].squareSize;
\r
3159 /* Respond to board resize by dragging edge */
\r
3161 ResizeBoard(int newSizeX, int newSizeY, int flags)
\r
3163 BoardSize newSize = NUM_SIZES - 1;
\r
3164 static int recurse = 0;
\r
3165 if (IsIconic(hwndMain)) return;
\r
3166 if (recurse > 0) return;
\r
3168 while (newSize > 0) {
\r
3169 InitDrawingSizes(newSize+1000, 0); // [HGM] kludge to update sizeInfo without visible effects
\r
3170 if(newSizeX >= sizeInfo[newSize].cliWidth &&
\r
3171 newSizeY >= sizeInfo[newSize].cliHeight) break;
\r
3174 boardSize = newSize;
\r
3175 InitDrawingSizes(boardSize, flags);
\r
3182 InitDrawingSizes(BoardSize boardSize, int flags)
\r
3184 int i, boardWidth, boardHeight; /* [HGM] height treated separately */
\r
3185 ChessSquare piece;
\r
3186 static int oldBoardSize = -1, oldTinyLayout = 0;
\r
3188 SIZE clockSize, messageSize;
\r
3190 char buf[MSG_SIZ];
\r
3192 HMENU hmenu = GetMenu(hwndMain);
\r
3193 RECT crect, wrect, oldRect;
\r
3195 LOGBRUSH logbrush;
\r
3197 int suppressVisibleEffects = 0; // [HGM] kludge to request updating sizeInfo only
\r
3198 if((int)boardSize >= 1000 ) { boardSize -= 1000; suppressVisibleEffects = 1; }
\r
3200 /* [HGM] call with -2 uses old size (for if nr of files, ranks changes) */
\r
3201 if(boardSize == (BoardSize)(-2) ) boardSize = oldBoardSize;
\r
3203 oldRect.left = boardX; //[HGM] placement: remember previous window params
\r
3204 oldRect.top = boardY;
\r
3205 oldRect.right = boardX + winWidth;
\r
3206 oldRect.bottom = boardY + winHeight;
\r
3208 tinyLayout = sizeInfo[boardSize].tinyLayout;
\r
3209 smallLayout = sizeInfo[boardSize].smallLayout;
\r
3210 squareSize = sizeInfo[boardSize].squareSize;
\r
3211 lineGap = sizeInfo[boardSize].lineGap;
\r
3212 minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted */
\r
3214 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3215 lineGap = appData.overrideLineGap;
\r
3218 if (tinyLayout != oldTinyLayout) {
\r
3219 long style = GetWindowLong(hwndMain, GWL_STYLE);
\r
3221 style &= ~WS_SYSMENU;
\r
3222 InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize,
\r
3223 "&Minimize\tCtrl+F4");
\r
3225 style |= WS_SYSMENU;
\r
3226 RemoveMenu(hmenu, IDM_Minimize, MF_BYCOMMAND);
\r
3228 SetWindowLong(hwndMain, GWL_STYLE, style);
\r
3230 for (i=0; menuBarText[tinyLayout][i]; i++) {
\r
3231 ModifyMenu(hmenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP,
\r
3232 (UINT)GetSubMenu(hmenu, i), menuBarText[tinyLayout][i]);
\r
3234 DrawMenuBar(hwndMain);
\r
3237 boardWidth = BoardWidth(boardSize, BOARD_WIDTH);
\r
3238 boardHeight = BoardWidth(boardSize, BOARD_HEIGHT);
\r
3240 /* Get text area sizes */
\r
3241 hdc = GetDC(hwndMain);
\r
3242 if (appData.clockMode) {
\r
3243 sprintf(buf, "White: %s", TimeString(23*60*60*1000L));
\r
3245 sprintf(buf, "White");
\r
3247 oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);
\r
3248 GetTextExtentPoint(hdc, buf, strlen(buf), &clockSize);
\r
3249 SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);
\r
3250 str = "We only care about the height here";
\r
3251 GetTextExtentPoint(hdc, str, strlen(str), &messageSize);
\r
3252 SelectObject(hdc, oldFont);
\r
3253 ReleaseDC(hwndMain, hdc);
\r
3255 /* Compute where everything goes */
\r
3256 if((first.programLogo || second.programLogo) && !tinyLayout) {
\r
3257 /* [HGM] logo: if either logo is on, reserve space for it */
\r
3258 logoHeight = 2*clockSize.cy;
\r
3259 leftLogoRect.left = OUTER_MARGIN;
\r
3260 leftLogoRect.right = leftLogoRect.left + 4*clockSize.cy;
\r
3261 leftLogoRect.top = OUTER_MARGIN;
\r
3262 leftLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3264 rightLogoRect.right = OUTER_MARGIN + boardWidth;
\r
3265 rightLogoRect.left = rightLogoRect.right - 4*clockSize.cy;
\r
3266 rightLogoRect.top = OUTER_MARGIN;
\r
3267 rightLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3270 whiteRect.left = leftLogoRect.right;
\r
3271 whiteRect.right = OUTER_MARGIN + boardWidth/2 - INNER_MARGIN/2;
\r
3272 whiteRect.top = OUTER_MARGIN;
\r
3273 whiteRect.bottom = whiteRect.top + logoHeight;
\r
3275 blackRect.right = rightLogoRect.left;
\r
3276 blackRect.left = whiteRect.right + INNER_MARGIN;
\r
3277 blackRect.top = whiteRect.top;
\r
3278 blackRect.bottom = whiteRect.bottom;
\r
3280 whiteRect.left = OUTER_MARGIN;
\r
3281 whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2;
\r
3282 whiteRect.top = OUTER_MARGIN;
\r
3283 whiteRect.bottom = whiteRect.top + clockSize.cy;
\r
3285 blackRect.left = whiteRect.right + INNER_MARGIN;
\r
3286 blackRect.right = blackRect.left + boardWidth/2 - 1;
\r
3287 blackRect.top = whiteRect.top;
\r
3288 blackRect.bottom = whiteRect.bottom;
\r
3291 messageRect.left = OUTER_MARGIN + MESSAGE_LINE_LEFTMARGIN;
\r
3292 if (appData.showButtonBar) {
\r
3293 messageRect.right = OUTER_MARGIN + boardWidth // [HGM] logo: expressed independent of clock placement
\r
3294 - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN;
\r
3296 messageRect.right = OUTER_MARGIN + boardWidth;
\r
3298 messageRect.top = whiteRect.bottom + INNER_MARGIN;
\r
3299 messageRect.bottom = messageRect.top + messageSize.cy;
\r
3301 boardRect.left = OUTER_MARGIN;
\r
3302 boardRect.right = boardRect.left + boardWidth;
\r
3303 boardRect.top = messageRect.bottom + INNER_MARGIN;
\r
3304 boardRect.bottom = boardRect.top + boardHeight;
\r
3306 sizeInfo[boardSize].cliWidth = boardRect.right + OUTER_MARGIN;
\r
3307 sizeInfo[boardSize].cliHeight = boardRect.bottom + OUTER_MARGIN;
\r
3308 oldBoardSize = boardSize;
\r
3309 oldTinyLayout = tinyLayout;
\r
3310 winW = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN;
\r
3311 winH = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) +
\r
3312 GetSystemMetrics(SM_CYCAPTION) + boardRect.bottom + OUTER_MARGIN;
\r
3313 if(suppressVisibleEffects) return; // [HGM] when called for filling sizeInfo only
\r
3314 winWidth = winW; // [HGM] placement: set through temporary which can used by initial sizing choice
\r
3315 winHeight = winH; // without disturbing window attachments
\r
3316 GetWindowRect(hwndMain, &wrect);
\r
3317 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3318 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3320 // [HGM] placement: let attached windows follow size change.
\r
3321 ReattachAfterSize( &oldRect, winWidth, winHeight, moveHistoryDialog, &wpMoveHistory );
\r
3322 ReattachAfterSize( &oldRect, winWidth, winHeight, evalGraphDialog, &wpEvalGraph );
\r
3323 ReattachAfterSize( &oldRect, winWidth, winHeight, engineOutputDialog, &wpEngineOutput );
\r
3324 ReattachAfterSize( &oldRect, winWidth, winHeight, gameListDialog, &wpGameList );
\r
3325 ReattachAfterSize( &oldRect, winWidth, winHeight, hwndConsole, &wpConsole );
\r
3327 /* compensate if menu bar wrapped */
\r
3328 GetClientRect(hwndMain, &crect);
\r
3329 offby = boardRect.bottom + OUTER_MARGIN - crect.bottom;
\r
3330 winHeight += offby;
\r
3332 case WMSZ_TOPLEFT:
\r
3333 SetWindowPos(hwndMain, NULL,
\r
3334 wrect.right - winWidth, wrect.bottom - winHeight,
\r
3335 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3338 case WMSZ_TOPRIGHT:
\r
3340 SetWindowPos(hwndMain, NULL,
\r
3341 wrect.left, wrect.bottom - winHeight,
\r
3342 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3345 case WMSZ_BOTTOMLEFT:
\r
3347 SetWindowPos(hwndMain, NULL,
\r
3348 wrect.right - winWidth, wrect.top,
\r
3349 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3352 case WMSZ_BOTTOMRIGHT:
\r
3356 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3357 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3362 for (i = 0; i < N_BUTTONS; i++) {
\r
3363 if (buttonDesc[i].hwnd != NULL) {
\r
3364 DestroyWindow(buttonDesc[i].hwnd);
\r
3365 buttonDesc[i].hwnd = NULL;
\r
3367 if (appData.showButtonBar) {
\r
3368 buttonDesc[i].hwnd =
\r
3369 CreateWindow("BUTTON", buttonDesc[i].label,
\r
3370 WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
\r
3371 boardRect.right - BUTTON_WIDTH*(N_BUTTONS-i),
\r
3372 messageRect.top, BUTTON_WIDTH, messageSize.cy, hwndMain,
\r
3373 (HMENU) buttonDesc[i].id,
\r
3374 (HINSTANCE) GetWindowLong(hwndMain, GWL_HINSTANCE), NULL);
\r
3376 SendMessage(buttonDesc[i].hwnd, WM_SETFONT,
\r
3377 (WPARAM)font[boardSize][MESSAGE_FONT]->hf,
\r
3378 MAKELPARAM(FALSE, 0));
\r
3380 if (buttonDesc[i].id == IDM_Pause)
\r
3381 hwndPause = buttonDesc[i].hwnd;
\r
3382 buttonDesc[i].wndproc = (WNDPROC)
\r
3383 SetWindowLong(buttonDesc[i].hwnd, GWL_WNDPROC, (LONG) ButtonProc);
\r
3386 if (gridPen != NULL) DeleteObject(gridPen);
\r
3387 if (highlightPen != NULL) DeleteObject(highlightPen);
\r
3388 if (premovePen != NULL) DeleteObject(premovePen);
\r
3389 if (lineGap != 0) {
\r
3390 logbrush.lbStyle = BS_SOLID;
\r
3391 logbrush.lbColor = RGB(0, 0, 0); /* grid pen color = black */
\r
3393 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3394 lineGap, &logbrush, 0, NULL);
\r
3395 logbrush.lbColor = highlightSquareColor;
\r
3397 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3398 lineGap, &logbrush, 0, NULL);
\r
3400 logbrush.lbColor = premoveHighlightColor;
\r
3402 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3403 lineGap, &logbrush, 0, NULL);
\r
3405 /* [HGM] Loop had to be split in part for vert. and hor. lines */
\r
3406 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
\r
3407 gridEndpoints[i*2].x = boardRect.left + lineGap / 2;
\r
3408 gridEndpoints[i*2].y = gridEndpoints[i*2 + 1].y =
\r
3409 boardRect.top + lineGap / 2 + (i * (squareSize + lineGap));
\r
3410 gridEndpoints[i*2 + 1].x = boardRect.left + lineGap / 2 +
\r
3411 BOARD_WIDTH * (squareSize + lineGap);
\r
3412 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3414 for (i = 0; i < BOARD_WIDTH + 1; i++) {
\r
3415 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].y = boardRect.top + lineGap / 2;
\r
3416 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].x =
\r
3417 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].x = boardRect.left +
\r
3418 lineGap / 2 + (i * (squareSize + lineGap));
\r
3419 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].y =
\r
3420 boardRect.top + BOARD_HEIGHT * (squareSize + lineGap);
\r
3421 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3425 /* [HGM] Licensing requirement */
\r
3427 if(gameInfo.variant == VariantGothic) GothicPopUp( GOTHIC, VariantGothic); else
\r
3430 if(gameInfo.variant == VariantFalcon) GothicPopUp( FALCON, VariantFalcon); else
\r
3432 GothicPopUp( "", VariantNormal);
\r
3435 /* if (boardSize == oldBoardSize) return; [HGM] variant might have changed */
\r
3437 /* Load piece bitmaps for this board size */
\r
3438 for (i=0; i<=2; i++) {
\r
3439 for (piece = WhitePawn;
\r
3440 (int) piece < (int) BlackPawn;
\r
3441 piece = (ChessSquare) ((int) piece + 1)) {
\r
3442 if (pieceBitmap[i][piece] != NULL)
\r
3443 DeleteObject(pieceBitmap[i][piece]);
\r
3447 fontBitmapSquareSize = 0; /* [HGM] render: make sure pieces will be recreated, as we might need others now */
\r
3448 // Orthodox Chess pieces
\r
3449 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s");
\r
3450 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s");
\r
3451 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "s");
\r
3452 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "s");
\r
3453 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "s");
\r
3454 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "o");
\r
3455 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "o");
\r
3456 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "o");
\r
3457 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "o");
\r
3458 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "o");
\r
3459 pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "w");
\r
3460 pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "w");
\r
3461 pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "w");
\r
3462 pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w");
\r
3463 pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w");
\r
3464 if( !strcmp(appData.variant, "shogi") && (squareSize==72 || squareSize==49)) {
\r
3465 // in Shogi, Hijack the unused Queen for Lance
\r
3466 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3467 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3468 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3470 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s");
\r
3471 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o");
\r
3472 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w");
\r
3475 if(squareSize <= 72 && squareSize >= 33) {
\r
3476 /* A & C are available in most sizes now */
\r
3477 if(squareSize != 49 && squareSize != 72 && squareSize != 33) { // Vortex-like
\r
3478 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3479 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3480 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3481 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3482 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3483 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3484 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3485 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3486 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3487 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3488 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3489 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3490 } else { // Smirf-like
\r
3491 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "s");
\r
3492 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "o");
\r
3493 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "w");
\r
3495 if(gameInfo.variant == VariantGothic) { // Vortex-like
\r
3496 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3497 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3498 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3499 } else { // WinBoard standard
\r
3500 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s");
\r
3501 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o");
\r
3502 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "w");
\r
3507 if(squareSize==72 || squareSize==49 || squareSize==33) { /* experiment with some home-made bitmaps */
\r
3508 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "s");
\r
3509 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "o");
\r
3510 pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "w");
\r
3511 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "s");
\r
3512 pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "o");
\r
3513 pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3514 pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "s");
\r
3515 pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "o");
\r
3516 pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "w");
\r
3517 pieceBitmap[0][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "s");
\r
3518 pieceBitmap[1][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "o");
\r
3519 pieceBitmap[2][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "w");
\r
3520 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3521 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3522 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3523 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "s");
\r
3524 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "o");
\r
3525 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "w");
\r
3526 pieceBitmap[0][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "s");
\r
3527 pieceBitmap[1][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "o");
\r
3528 pieceBitmap[2][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "w");
\r
3529 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "s");
\r
3530 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "o");
\r
3531 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "w");
\r
3532 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3533 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3534 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3535 pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s");
\r
3536 pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o");
\r
3537 pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w");
\r
3539 if(gameInfo.variant == VariantShogi) { /* promoted Gold represemtations */
\r
3540 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s");
\r
3541 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "o");
\r
3542 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3543 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "s");
\r
3544 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "o");
\r
3545 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3546 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "s");
\r
3547 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "o");
\r
3548 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3549 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "s");
\r
3550 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "o");
\r
3551 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3553 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "s");
\r
3554 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "o");
\r
3555 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "w");
\r
3556 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "s");
\r
3557 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "o");
\r
3558 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "w");
\r
3559 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3560 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3561 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3562 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "s");
\r
3563 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "o");
\r
3564 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "w");
\r
3567 } else { /* other size, no special bitmaps available. Use smaller symbols */
\r
3568 if((int)boardSize < 2) minorSize = sizeInfo[0].squareSize;
\r
3569 else minorSize = sizeInfo[(int)boardSize - 2].squareSize;
\r
3570 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "s");
\r
3571 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "o");
\r
3572 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "w");
\r
3573 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "s");
\r
3574 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "o");
\r
3575 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "w");
\r
3576 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "s");
\r
3577 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "o");
\r
3578 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "w");
\r
3579 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "s");
\r
3580 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "o");
\r
3581 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "w");
\r
3585 if(gameInfo.variant == VariantShogi && squareSize == 58)
\r
3586 /* special Shogi support in this size */
\r
3587 { for (i=0; i<=2; i++) { /* replace all bitmaps */
\r
3588 for (piece = WhitePawn;
\r
3589 (int) piece < (int) BlackPawn;
\r
3590 piece = (ChessSquare) ((int) piece + 1)) {
\r
3591 if (pieceBitmap[i][piece] != NULL)
\r
3592 DeleteObject(pieceBitmap[i][piece]);
\r
3595 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3596 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3597 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3598 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3599 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3600 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3601 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r
3602 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");
\r
3603 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");
\r
3604 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");
\r
3605 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");
\r
3606 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");
\r
3607 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");
\r
3608 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");
\r
3609 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3610 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3611 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3612 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3613 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3614 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3615 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r
3616 pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");
\r
3617 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");
\r
3618 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");
\r
3619 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");
\r
3620 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");
\r
3621 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");
\r
3622 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");
\r
3623 pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "w");
\r
3624 pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "w");
\r
3625 pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3626 pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3627 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "w");
\r
3628 pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "w");
\r
3629 pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3630 pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3631 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "sp", squareSize, "w");
\r
3632 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "sn", squareSize, "w");
\r
3633 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3634 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3635 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "sl", squareSize, "w");
\r
3636 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3642 PieceBitmap(ChessSquare p, int kind)
\r
3644 if ((int) p >= (int) BlackPawn)
\r