2 * WinBoard.c -- Windows NT front end to XBoard
\r
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
\r
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
\r
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
\r
10 * Enhancements Copyright 2005 Alessandro Scotti
\r
12 * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,
\r
13 * which was written and is copyrighted by Wayne Christopher.
\r
15 * The following terms apply to Digital Equipment Corporation's copyright
\r
16 * interest in XBoard:
\r
17 * ------------------------------------------------------------------------
\r
18 * All Rights Reserved
\r
20 * Permission to use, copy, modify, and distribute this software and its
\r
21 * documentation for any purpose and without fee is hereby granted,
\r
22 * provided that the above copyright notice appear in all copies and that
\r
23 * both that copyright notice and this permission notice appear in
\r
24 * supporting documentation, and that the name of Digital not be
\r
25 * used in advertising or publicity pertaining to distribution of the
\r
26 * software without specific, written prior permission.
\r
28 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
\r
29 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
\r
30 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
\r
31 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
\r
32 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
\r
33 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
\r
35 * ------------------------------------------------------------------------
\r
37 * The following terms apply to the enhanced version of XBoard
\r
38 * distributed by the Free Software Foundation:
\r
39 * ------------------------------------------------------------------------
\r
41 * GNU XBoard is free software: you can redistribute it and/or modify
\r
42 * it under the terms of the GNU General Public License as published by
\r
43 * the Free Software Foundation, either version 3 of the License, or (at
\r
44 * your option) any later version.
\r
46 * GNU XBoard is distributed in the hope that it will be useful, but
\r
47 * WITHOUT ANY WARRANTY; without even the implied warranty of
\r
48 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
49 * General Public License for more details.
\r
51 * You should have received a copy of the GNU General Public License
\r
52 * along with this program. If not, see http://www.gnu.org/licenses/. *
\r
54 *------------------------------------------------------------------------
\r
55 ** See the file ChangeLog for a revision history. */
\r
59 #include <windows.h>
\r
60 #include <winuser.h>
\r
61 #include <winsock.h>
\r
62 #include <commctrl.h>
\r
68 #include <sys/stat.h>
\r
71 #include <commdlg.h>
\r
73 #include <richedit.h>
\r
74 #include <mmsystem.h>
\r
83 #include "winboard.h"
\r
84 #include "frontend.h"
\r
85 #include "backend.h"
\r
87 #include "wclipbrd.h"
\r
88 #include "wgamelist.h"
\r
89 #include "wedittags.h"
\r
90 #include "woptions.h"
\r
91 #include "wsockerr.h"
\r
92 #include "defaults.h"
\r
96 //void InitEngineUCI( const char * iniDir, ChessProgramState * cps );
\r
99 void mysrandom(unsigned int seed);
\r
101 extern int whiteFlag, blackFlag;
\r
102 Boolean flipClock = FALSE;
\r
103 extern HANDLE chatHandle[];
\r
104 extern int ics_type;
\r
106 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);
\r
107 VOID NewVariantPopup(HWND hwnd);
\r
108 int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,
\r
109 /*char*/int promoChar));
\r
110 void AnimateAtomicCapture(int fromX, int fromY, int toX, int toY, int nFrames);
\r
111 void DisplayMove P((int moveNumber));
\r
112 Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen));
\r
113 void ChatPopUp P(());
\r
115 ChessSquare piece;
\r
116 POINT pos; /* window coordinates of current pos */
\r
117 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
118 POINT from; /* board coordinates of the piece's orig pos */
\r
119 POINT to; /* board coordinates of the piece's new pos */
\r
122 static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };
\r
125 POINT start; /* window coordinates of start pos */
\r
126 POINT pos; /* window coordinates of current pos */
\r
127 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
128 POINT from; /* board coordinates of the piece's orig pos */
\r
131 static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} };
\r
134 POINT sq[2]; /* board coordinates of from, to squares */
\r
137 static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} };
\r
138 static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };
\r
140 typedef struct { // [HGM] atomic
\r
141 int fromX, fromY, toX, toY, radius;
\r
144 static ExplodeInfo explodeInfo;
\r
146 /* Window class names */
\r
147 char szAppName[] = "WinBoard";
\r
148 char szConsoleName[] = "WBConsole";
\r
150 /* Title bar text */
\r
151 char szTitle[] = "WinBoard";
\r
152 char szConsoleTitle[] = "I C S Interaction";
\r
155 char *settingsFileName;
\r
156 BOOLEAN saveSettingsOnExit;
\r
157 char installDir[MSG_SIZ];
\r
159 BoardSize boardSize;
\r
160 BOOLEAN chessProgram;
\r
161 static int boardX, boardY;
\r
162 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
\r
163 static int squareSize, lineGap, minorSize;
\r
164 static int winWidth, winHeight, winW, winH;
\r
165 static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo
\r
166 static int logoHeight = 0;
\r
167 static char messageText[MESSAGE_TEXT_MAX];
\r
168 static int clockTimerEvent = 0;
\r
169 static int loadGameTimerEvent = 0;
\r
170 static int analysisTimerEvent = 0;
\r
171 static DelayedEventCallback delayedTimerCallback;
\r
172 static int delayedTimerEvent = 0;
\r
173 static int buttonCount = 2;
\r
174 char *icsTextMenuString;
\r
176 char *firstChessProgramNames;
\r
177 char *secondChessProgramNames;
\r
179 #define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */
\r
181 #define PALETTESIZE 256
\r
183 HINSTANCE hInst; /* current instance */
\r
184 HWND hwndMain = NULL; /* root window*/
\r
185 HWND hwndConsole = NULL;
\r
186 BOOLEAN alwaysOnTop = FALSE;
\r
188 COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
\r
189 blackPieceColor, highlightSquareColor, premoveHighlightColor;
\r
191 ColorClass currentColorClass;
\r
193 HWND hCommPort = NULL; /* currently open comm port */
\r
194 static HWND hwndPause; /* pause button */
\r
195 static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */
\r
196 static HBRUSH lightSquareBrush, darkSquareBrush,
\r
197 blackSquareBrush, /* [HGM] for band between board and holdings */
\r
198 explodeBrush, /* [HGM] atomic */
\r
199 whitePieceBrush, blackPieceBrush, iconBkgndBrush /*, outlineBrush*/;
\r
200 static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];
\r
201 static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];
\r
202 static HPEN gridPen = NULL;
\r
203 static HPEN highlightPen = NULL;
\r
204 static HPEN premovePen = NULL;
\r
205 static NPLOGPALETTE pLogPal;
\r
206 static BOOL paletteChanged = FALSE;
\r
207 static HICON iconWhite, iconBlack, iconCurrent;
\r
208 static int doingSizing = FALSE;
\r
209 static int lastSizing = 0;
\r
210 static int prevStderrPort;
\r
211 static HBITMAP userLogo;
\r
213 /* [AS] Support for background textures */
\r
214 #define BACK_TEXTURE_MODE_DISABLED 0
\r
215 #define BACK_TEXTURE_MODE_PLAIN 1
\r
216 #define BACK_TEXTURE_MODE_FULL_RANDOM 2
\r
218 static HBITMAP liteBackTexture = NULL;
\r
219 static HBITMAP darkBackTexture = NULL;
\r
220 static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
221 static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
222 static int backTextureSquareSize = 0;
\r
223 static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_SIZE][BOARD_SIZE];
\r
225 #if __GNUC__ && !defined(_winmajor)
\r
226 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */
\r
228 #if defined(_winmajor)
\r
229 #define oldDialog (_winmajor < 4)
\r
231 #define oldDialog 0
\r
235 char *defaultTextAttribs[] =
\r
237 COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,
\r
238 COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,
\r
248 int cliWidth, cliHeight;
\r
251 SizeInfo sizeInfo[] =
\r
253 { "tiny", 21, 0, 1, 1, 0, 0 },
\r
254 { "teeny", 25, 1, 1, 1, 0, 0 },
\r
255 { "dinky", 29, 1, 1, 1, 0, 0 },
\r
256 { "petite", 33, 1, 1, 1, 0, 0 },
\r
257 { "slim", 37, 2, 1, 0, 0, 0 },
\r
258 { "small", 40, 2, 1, 0, 0, 0 },
\r
259 { "mediocre", 45, 2, 1, 0, 0, 0 },
\r
260 { "middling", 49, 2, 0, 0, 0, 0 },
\r
261 { "average", 54, 2, 0, 0, 0, 0 },
\r
262 { "moderate", 58, 3, 0, 0, 0, 0 },
\r
263 { "medium", 64, 3, 0, 0, 0, 0 },
\r
264 { "bulky", 72, 3, 0, 0, 0, 0 },
\r
265 { "large", 80, 3, 0, 0, 0, 0 },
\r
266 { "big", 87, 3, 0, 0, 0, 0 },
\r
267 { "huge", 95, 3, 0, 0, 0, 0 },
\r
268 { "giant", 108, 3, 0, 0, 0, 0 },
\r
269 { "colossal", 116, 4, 0, 0, 0, 0 },
\r
270 { "titanic", 129, 4, 0, 0, 0, 0 },
\r
271 { NULL, 0, 0, 0, 0, 0, 0 }
\r
274 #define MF(x) {x, {{0,}, 0. }, {0, }, 0}
\r
275 MyFont fontRec[NUM_SIZES][NUM_FONTS] =
\r
277 { MF(CLOCK_FONT_TINY), MF(MESSAGE_FONT_TINY), MF(COORD_FONT_TINY), MF(CONSOLE_FONT_TINY), MF(COMMENT_FONT_TINY), MF(EDITTAGS_FONT_TINY), MF(MOVEHISTORY_FONT_ALL) },
\r
278 { MF(CLOCK_FONT_TEENY), MF(MESSAGE_FONT_TEENY), MF(COORD_FONT_TEENY), MF(CONSOLE_FONT_TEENY), MF(COMMENT_FONT_TEENY), MF(EDITTAGS_FONT_TEENY), MF(MOVEHISTORY_FONT_ALL) },
\r
279 { MF(CLOCK_FONT_DINKY), MF(MESSAGE_FONT_DINKY), MF(COORD_FONT_DINKY), MF(CONSOLE_FONT_DINKY), MF(COMMENT_FONT_DINKY), MF(EDITTAGS_FONT_DINKY), MF(MOVEHISTORY_FONT_ALL) },
\r
280 { MF(CLOCK_FONT_PETITE), MF(MESSAGE_FONT_PETITE), MF(COORD_FONT_PETITE), MF(CONSOLE_FONT_PETITE), MF(COMMENT_FONT_PETITE), MF(EDITTAGS_FONT_PETITE), MF(MOVEHISTORY_FONT_ALL) },
\r
281 { MF(CLOCK_FONT_SLIM), MF(MESSAGE_FONT_SLIM), MF(COORD_FONT_SLIM), MF(CONSOLE_FONT_SLIM), MF(COMMENT_FONT_SLIM), MF(EDITTAGS_FONT_SLIM), MF(MOVEHISTORY_FONT_ALL) },
\r
282 { MF(CLOCK_FONT_SMALL), MF(MESSAGE_FONT_SMALL), MF(COORD_FONT_SMALL), MF(CONSOLE_FONT_SMALL), MF(COMMENT_FONT_SMALL), MF(EDITTAGS_FONT_SMALL), MF(MOVEHISTORY_FONT_ALL) },
\r
283 { MF(CLOCK_FONT_MEDIOCRE), MF(MESSAGE_FONT_MEDIOCRE), MF(COORD_FONT_MEDIOCRE), MF(CONSOLE_FONT_MEDIOCRE), MF(COMMENT_FONT_MEDIOCRE), MF(EDITTAGS_FONT_MEDIOCRE), MF(MOVEHISTORY_FONT_ALL) },
\r
284 { MF(CLOCK_FONT_MIDDLING), MF(MESSAGE_FONT_MIDDLING), MF(COORD_FONT_MIDDLING), MF(CONSOLE_FONT_MIDDLING), MF(COMMENT_FONT_MIDDLING), MF(EDITTAGS_FONT_MIDDLING), MF(MOVEHISTORY_FONT_ALL) },
\r
285 { MF(CLOCK_FONT_AVERAGE), MF(MESSAGE_FONT_AVERAGE), MF(COORD_FONT_AVERAGE), MF(CONSOLE_FONT_AVERAGE), MF(COMMENT_FONT_AVERAGE), MF(EDITTAGS_FONT_AVERAGE), MF(MOVEHISTORY_FONT_ALL) },
\r
286 { MF(CLOCK_FONT_MODERATE), MF(MESSAGE_FONT_MODERATE), MF(COORD_FONT_MODERATE), MF(CONSOLE_FONT_MODERATE), MF(COMMENT_FONT_MODERATE), MF(EDITTAGS_FONT_MODERATE), MF(MOVEHISTORY_FONT_ALL) },
\r
287 { MF(CLOCK_FONT_MEDIUM), MF(MESSAGE_FONT_MEDIUM), MF(COORD_FONT_MEDIUM), MF(CONSOLE_FONT_MEDIUM), MF(COMMENT_FONT_MEDIUM), MF(EDITTAGS_FONT_MEDIUM), MF(MOVEHISTORY_FONT_ALL) },
\r
288 { MF(CLOCK_FONT_BULKY), MF(MESSAGE_FONT_BULKY), MF(COORD_FONT_BULKY), MF(CONSOLE_FONT_BULKY), MF(COMMENT_FONT_BULKY), MF(EDITTAGS_FONT_BULKY), MF(MOVEHISTORY_FONT_ALL) },
\r
289 { MF(CLOCK_FONT_LARGE), MF(MESSAGE_FONT_LARGE), MF(COORD_FONT_LARGE), MF(CONSOLE_FONT_LARGE), MF(COMMENT_FONT_LARGE), MF(EDITTAGS_FONT_LARGE), MF(MOVEHISTORY_FONT_ALL) },
\r
290 { MF(CLOCK_FONT_BIG), MF(MESSAGE_FONT_BIG), MF(COORD_FONT_BIG), MF(CONSOLE_FONT_BIG), MF(COMMENT_FONT_BIG), MF(EDITTAGS_FONT_BIG), MF(MOVEHISTORY_FONT_ALL) },
\r
291 { MF(CLOCK_FONT_HUGE), MF(MESSAGE_FONT_HUGE), MF(COORD_FONT_HUGE), MF(CONSOLE_FONT_HUGE), MF(COMMENT_FONT_HUGE), MF(EDITTAGS_FONT_HUGE), MF(MOVEHISTORY_FONT_ALL) },
\r
292 { MF(CLOCK_FONT_GIANT), MF(MESSAGE_FONT_GIANT), MF(COORD_FONT_GIANT), MF(CONSOLE_FONT_GIANT), MF(COMMENT_FONT_GIANT), MF(EDITTAGS_FONT_GIANT), MF(MOVEHISTORY_FONT_ALL) },
\r
293 { MF(CLOCK_FONT_COLOSSAL), MF(MESSAGE_FONT_COLOSSAL), MF(COORD_FONT_COLOSSAL), MF(CONSOLE_FONT_COLOSSAL), MF(COMMENT_FONT_COLOSSAL), MF(EDITTAGS_FONT_COLOSSAL), MF(MOVEHISTORY_FONT_ALL) },
\r
294 { MF(CLOCK_FONT_TITANIC), MF(MESSAGE_FONT_TITANIC), MF(COORD_FONT_TITANIC), MF(CONSOLE_FONT_TITANIC), MF(COMMENT_FONT_TITANIC), MF(EDITTAGS_FONT_TITANIC), MF(MOVEHISTORY_FONT_ALL) },
\r
297 MyFont *font[NUM_SIZES][NUM_FONTS];
\r
306 #define BUTTON_WIDTH (tinyLayout ? 16 : 32)
\r
307 #define N_BUTTONS 5
\r
309 MyButtonDesc buttonDesc[N_BUTTONS] =
\r
311 {"<<", IDM_ToStart, NULL, NULL},
\r
312 {"<", IDM_Backward, NULL, NULL},
\r
313 {"P", IDM_Pause, NULL, NULL},
\r
314 {">", IDM_Forward, NULL, NULL},
\r
315 {">>", IDM_ToEnd, NULL, NULL},
\r
318 int tinyLayout = 0, smallLayout = 0;
\r
319 #define MENU_BAR_ITEMS 7
\r
320 char *menuBarText[2][MENU_BAR_ITEMS+1] = {
\r
321 { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },
\r
322 { "&F", "&M", "&A", "&S", "&O", "&H", NULL },
\r
326 MySound sounds[(int)NSoundClasses];
\r
327 MyTextAttribs textAttribs[(int)NColorClasses];
\r
329 MyColorizeAttribs colorizeAttribs[] = {
\r
330 { (COLORREF)0, 0, "Shout Text" },
\r
331 { (COLORREF)0, 0, "SShout/CShout" },
\r
332 { (COLORREF)0, 0, "Channel 1 Text" },
\r
333 { (COLORREF)0, 0, "Channel Text" },
\r
334 { (COLORREF)0, 0, "Kibitz Text" },
\r
335 { (COLORREF)0, 0, "Tell Text" },
\r
336 { (COLORREF)0, 0, "Challenge Text" },
\r
337 { (COLORREF)0, 0, "Request Text" },
\r
338 { (COLORREF)0, 0, "Seek Text" },
\r
339 { (COLORREF)0, 0, "Normal Text" },
\r
340 { (COLORREF)0, 0, "None" }
\r
345 static char *commentTitle;
\r
346 static char *commentText;
\r
347 static int commentIndex;
\r
348 static Boolean editComment = FALSE;
\r
349 HWND commentDialog = NULL;
\r
350 BOOLEAN commentDialogUp = FALSE;
\r
351 static int commentX, commentY, commentH, commentW;
\r
353 static char *analysisTitle;
\r
354 static char *analysisText;
\r
355 HWND analysisDialog = NULL;
\r
356 BOOLEAN analysisDialogUp = FALSE;
\r
357 static int analysisX, analysisY, analysisH, analysisW;
\r
359 char errorTitle[MSG_SIZ];
\r
360 char errorMessage[2*MSG_SIZ];
\r
361 HWND errorDialog = NULL;
\r
362 BOOLEAN moveErrorMessageUp = FALSE;
\r
363 BOOLEAN consoleEcho = TRUE;
\r
364 CHARFORMAT consoleCF;
\r
365 COLORREF consoleBackgroundColor;
\r
367 char *programVersion;
\r
373 typedef int CPKind;
\r
382 SOCKET sock2; /* stderr socket for OpenRcmd */
\r
385 #define INPUT_SOURCE_BUF_SIZE 4096
\r
387 typedef struct _InputSource {
\r
394 char buf[INPUT_SOURCE_BUF_SIZE];
\r
398 InputCallback func;
\r
399 struct _InputSource *second; /* for stderr thread on CPRcmd */
\r
403 InputSource *consoleInputSource;
\r
408 VOID ConsoleOutput(char* data, int length, int forceVisible);
\r
409 VOID ConsoleCreate();
\r
411 ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
412 VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
\r
413 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
\r
414 VOID ParseCommSettings(char *arg, DCB *dcb);
\r
416 StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
417 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
\r
418 void ParseIcsTextMenu(char *icsTextMenuString);
\r
419 VOID PopUpMoveDialog(char firstchar);
\r
420 VOID PopUpNameDialog(char firstchar);
\r
421 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
\r
425 int GameListOptions();
\r
427 HWND moveHistoryDialog = NULL;
\r
428 BOOLEAN moveHistoryDialogUp = FALSE;
\r
430 WindowPlacement wpMoveHistory;
\r
432 HWND evalGraphDialog = NULL;
\r
433 BOOLEAN evalGraphDialogUp = FALSE;
\r
435 WindowPlacement wpEvalGraph;
\r
437 HWND engineOutputDialog = NULL;
\r
438 BOOLEAN engineOutputDialogUp = FALSE;
\r
440 WindowPlacement wpEngineOutput;
\r
441 WindowPlacement wpGameList;
\r
442 WindowPlacement wpConsole;
\r
444 VOID MoveHistoryPopUp();
\r
445 VOID MoveHistoryPopDown();
\r
446 VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
447 BOOL MoveHistoryIsUp();
\r
449 VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
450 VOID EvalGraphPopUp();
\r
451 VOID EvalGraphPopDown();
\r
452 BOOL EvalGraphIsUp();
\r
454 VOID EngineOutputPopUp();
\r
455 VOID EngineOutputPopDown();
\r
456 BOOL EngineOutputIsUp();
\r
457 VOID EngineOutputUpdate( FrontEndProgramStats * stats );
\r
459 VOID EngineOptionsPopup(); // [HGM] settings
\r
461 VOID GothicPopUp(char *title, VariantClass variant);
\r
463 * Setting "frozen" should disable all user input other than deleting
\r
464 * the window. We do this while engines are initializing themselves.
\r
466 static int frozen = 0;
\r
467 static int oldMenuItemState[MENU_BAR_ITEMS];
\r
473 if (frozen) return;
\r
475 hmenu = GetMenu(hwndMain);
\r
476 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
477 oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
\r
479 DrawMenuBar(hwndMain);
\r
482 /* Undo a FreezeUI */
\r
488 if (!frozen) return;
\r
490 hmenu = GetMenu(hwndMain);
\r
491 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
492 EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
\r
494 DrawMenuBar(hwndMain);
\r
497 /*static*/ int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them
\r
499 /* JAWS preparation patch (WinBoard for the sight impaired). Define required insertions as empty */
\r
505 #define JAWS_ALT_INTERCEPT
\r
506 #define JAWS_KB_NAVIGATION
\r
507 #define JAWS_MENU_ITEMS
\r
508 #define JAWS_SILENCE
\r
509 #define JAWS_REPLAY
\r
511 #define JAWS_COPYRIGHT
\r
512 #define JAWS_DELETE(X) X
\r
513 #define SAYMACHINEMOVE()
\r
517 /*---------------------------------------------------------------------------*\
\r
521 \*---------------------------------------------------------------------------*/
\r
524 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
\r
525 LPSTR lpCmdLine, int nCmdShow)
\r
528 HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
\r
529 // INITCOMMONCONTROLSEX ex;
\r
533 LoadLibrary("RICHED32.DLL");
\r
534 consoleCF.cbSize = sizeof(CHARFORMAT);
\r
536 if (!InitApplication(hInstance)) {
\r
539 if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
\r
545 // InitCommonControlsEx(&ex);
\r
546 InitCommonControls();
\r
548 hAccelMain = LoadAccelerators (hInstance, szAppName);
\r
549 hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
\r
550 hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
\r
552 /* Acquire and dispatch messages until a WM_QUIT message is received. */
\r
554 while (GetMessage(&msg, /* message structure */
\r
555 NULL, /* handle of window receiving the message */
\r
556 0, /* lowest message to examine */
\r
557 0)) /* highest message to examine */
\r
560 if(msg.message == WM_CHAR && msg.wParam == '\t') {
\r
561 // [HGM] navigate: switch between all windows with tab
\r
562 HWND e1 = NULL, e2 = NULL, mh = NULL, hInput = NULL, hText = NULL;
\r
563 int i, currentElement = 0;
\r
565 // first determine what element of the chain we come from (if any)
\r
566 if(appData.icsActive) {
\r
567 hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);
\r
568 hText = GetDlgItem(hwndConsole, OPT_ConsoleText);
\r
570 if(engineOutputDialog && EngineOutputIsUp()) {
\r
571 e1 = GetDlgItem(engineOutputDialog, IDC_EngineMemo1);
\r
572 e2 = GetDlgItem(engineOutputDialog, IDC_EngineMemo2);
\r
574 if(moveHistoryDialog && MoveHistoryIsUp()) {
\r
575 mh = GetDlgItem(moveHistoryDialog, IDC_MoveHistory);
\r
577 if(msg.hwnd == hwndMain) currentElement = 7 ; else
\r
578 if(msg.hwnd == engineOutputDialog) currentElement = 2; else
\r
579 if(msg.hwnd == e1) currentElement = 2; else
\r
580 if(msg.hwnd == e2) currentElement = 3; else
\r
581 if(msg.hwnd == moveHistoryDialog) currentElement = 4; else
\r
582 if(msg.hwnd == mh) currentElement = 4; else
\r
583 if(msg.hwnd == evalGraphDialog) currentElement = 6; else
\r
584 if(msg.hwnd == hText) currentElement = 5; else
\r
585 if(msg.hwnd == hInput) currentElement = 6; else
\r
586 for (i = 0; i < N_BUTTONS; i++) {
\r
587 if (buttonDesc[i].hwnd == msg.hwnd) { currentElement = 1; break; }
\r
590 // determine where to go to
\r
591 if(currentElement) { HWND h = NULL; int direction = GetKeyState(VK_SHIFT) < 0 ? -1 : 1;
\r
593 currentElement = (currentElement + direction) % 7;
\r
594 switch(currentElement) {
\r
596 h = hwndMain; break; // passing this case always makes the loop exit
\r
598 h = buttonDesc[0].hwnd; break; // could be NULL
\r
600 if(!EngineOutputIsUp()) continue; // skip closed auxiliary windows
\r
603 if(!EngineOutputIsUp()) continue;
\r
606 if(!MoveHistoryIsUp()) continue;
\r
608 // case 6: // input to eval graph does not seem to get here!
\r
609 // if(!EvalGraphIsUp()) continue;
\r
610 // h = evalGraphDialog; break;
\r
612 if(!appData.icsActive) continue;
\r
616 if(!appData.icsActive) continue;
\r
622 if(currentElement > 4 && IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);
\r
623 if(currentElement < 5 && IsIconic(hwndMain)) ShowWindow(hwndMain, SW_RESTORE); // all open together
\r
626 continue; // this message now has been processed
\r
630 if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
\r
631 !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
\r
632 !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
\r
633 !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
\r
634 !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
\r
635 !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
\r
636 !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
\r
637 !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) && JAWS_ACCEL
\r
638 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
\r
639 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
\r
640 int done = 0, i; // [HGM] chat: dispatch cat-box messages
\r
641 for(i=0; i<MAX_CHAT; i++)
\r
642 if(chatHandle[i] && IsDialogMessage(chatHandle[i], &msg)) {
\r
645 if(done) continue; // [HGM] chat: end patch
\r
646 TranslateMessage(&msg); /* Translates virtual key codes */
\r
647 DispatchMessage(&msg); /* Dispatches message to window */
\r
652 return (msg.wParam); /* Returns the value from PostQuitMessage */
\r
655 /*---------------------------------------------------------------------------*\
\r
657 * Initialization functions
\r
659 \*---------------------------------------------------------------------------*/
\r
663 { // update user logo if necessary
\r
664 static char oldUserName[MSG_SIZ], *curName;
\r
666 if(appData.autoLogo) {
\r
667 curName = UserName();
\r
668 if(strcmp(curName, oldUserName)) {
\r
669 sprintf(oldUserName, "logos\\%s.bmp", curName);
\r
670 userLogo = LoadImage( 0, oldUserName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
671 strcpy(oldUserName, curName);
\r
677 InitApplication(HINSTANCE hInstance)
\r
681 /* Fill in window class structure with parameters that describe the */
\r
684 wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
\r
685 wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
\r
686 wc.cbClsExtra = 0; /* No per-class extra data. */
\r
687 wc.cbWndExtra = 0; /* No per-window extra data. */
\r
688 wc.hInstance = hInstance; /* Owner of this class */
\r
689 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
690 wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
\r
691 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
\r
692 wc.lpszMenuName = szAppName; /* Menu name from .RC */
\r
693 wc.lpszClassName = szAppName; /* Name to register as */
\r
695 /* Register the window class and return success/failure code. */
\r
696 if (!RegisterClass(&wc)) return FALSE;
\r
698 wc.style = CS_HREDRAW | CS_VREDRAW;
\r
699 wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
\r
701 wc.cbWndExtra = DLGWINDOWEXTRA;
\r
702 wc.hInstance = hInstance;
\r
703 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
704 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
\r
705 wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
\r
706 wc.lpszMenuName = NULL;
\r
707 wc.lpszClassName = szConsoleName;
\r
709 if (!RegisterClass(&wc)) return FALSE;
\r
714 /* Set by InitInstance, used by EnsureOnScreen */
\r
715 int screenHeight, screenWidth;
\r
718 EnsureOnScreen(int *x, int *y, int minX, int minY)
\r
720 // int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
\r
721 /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
\r
722 if (*x > screenWidth - 32) *x = 0;
\r
723 if (*y > screenHeight - 32) *y = 0;
\r
724 if (*x < minX) *x = minX;
\r
725 if (*y < minY) *y = minY;
\r
729 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
\r
731 HWND hwnd; /* Main window handle. */
\r
733 WINDOWPLACEMENT wp;
\r
736 hInst = hInstance; /* Store instance handle in our global variable */
\r
738 if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
\r
739 *filepart = NULLCHAR;
\r
741 GetCurrentDirectory(MSG_SIZ, installDir);
\r
743 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise
\r
744 screenWidth = screenHeight = 1000; // [HGM] placement: kludge to allow calling EnsureOnScreen from InitAppData
\r
745 InitAppData(lpCmdLine); /* Get run-time parameters */
\r
746 if (appData.debugMode) {
\r
747 debugFP = fopen(appData.nameOfDebugFile, "w");
\r
748 setbuf(debugFP, NULL);
\r
753 // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()
\r
754 // InitEngineUCI( installDir, &second );
\r
756 /* Create a main window for this application instance. */
\r
757 hwnd = CreateWindow(szAppName, szTitle,
\r
758 (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
\r
759 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
\r
760 NULL, NULL, hInstance, NULL);
\r
763 /* If window could not be created, return "failure" */
\r
768 /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */
\r
769 if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {
\r
770 first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
772 if (first.programLogo == NULL && appData.debugMode) {
\r
773 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );
\r
775 } else if(appData.autoLogo) {
\r
776 if(appData.firstDirectory && appData.firstDirectory[0]) {
\r
778 sprintf(buf, "%s/logo.bmp", appData.firstDirectory);
\r
779 first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
783 if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {
\r
784 second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
786 if (second.programLogo == NULL && appData.debugMode) {
\r
787 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );
\r
789 } else if(appData.autoLogo) {
\r
791 if(appData.icsActive) { // [HGM] logo: in ICS mode second can be used for ICS
\r
792 sprintf(buf, "logos\\%s.bmp", appData.icsHost);
\r
793 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
795 if(appData.secondDirectory && appData.secondDirectory[0]) {
\r
796 sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);
\r
797 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
803 iconWhite = LoadIcon(hInstance, "icon_white");
\r
804 iconBlack = LoadIcon(hInstance, "icon_black");
\r
805 iconCurrent = iconWhite;
\r
806 InitDrawingColors();
\r
807 screenHeight = GetSystemMetrics(SM_CYSCREEN);
\r
808 screenWidth = GetSystemMetrics(SM_CXSCREEN);
\r
809 for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
\r
810 /* Compute window size for each board size, and use the largest
\r
811 size that fits on this screen as the default. */
\r
812 InitDrawingSizes((BoardSize)(ibs+1000), 0);
\r
813 if (boardSize == (BoardSize)-1 &&
\r
814 winH <= screenHeight
\r
815 - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10
\r
816 && winW <= screenWidth) {
\r
817 boardSize = (BoardSize)ibs;
\r
821 InitDrawingSizes(boardSize, 0);
\r
823 buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
\r
825 /* [AS] Load textures if specified */
\r
826 ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );
\r
828 if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {
\r
829 liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
830 liteBackTextureMode = appData.liteBackTextureMode;
\r
832 if (liteBackTexture == NULL && appData.debugMode) {
\r
833 fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );
\r
837 if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {
\r
838 darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
839 darkBackTextureMode = appData.darkBackTextureMode;
\r
841 if (darkBackTexture == NULL && appData.debugMode) {
\r
842 fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );
\r
846 mysrandom( (unsigned) time(NULL) );
\r
848 /* [AS] Restore layout */
\r
849 if( wpMoveHistory.visible ) {
\r
850 MoveHistoryPopUp();
\r
853 if( wpEvalGraph.visible ) {
\r
857 if( wpEngineOutput.visible ) {
\r
858 EngineOutputPopUp();
\r
863 /* Make the window visible; update its client area; and return "success" */
\r
864 EnsureOnScreen(&boardX, &boardY, minX, minY);
\r
865 wp.length = sizeof(WINDOWPLACEMENT);
\r
867 wp.showCmd = nCmdShow;
\r
868 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
\r
869 wp.rcNormalPosition.left = boardX;
\r
870 wp.rcNormalPosition.right = boardX + winWidth;
\r
871 wp.rcNormalPosition.top = boardY;
\r
872 wp.rcNormalPosition.bottom = boardY + winHeight;
\r
873 SetWindowPlacement(hwndMain, &wp);
\r
875 if(!appData.noGUI) SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
876 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
880 SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
881 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
883 ShowWindow(hwndConsole, nCmdShow);
\r
885 if(!appData.noGUI) UpdateWindow(hwnd); else ShowWindow(hwnd, SW_MINIMIZE);
\r
886 if(gameListDialog) SetFocus(gameListDialog); // [HGM] jaws: for if we clicked multi-game game file
\r
894 ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
\r
895 ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
\r
896 ArgSettingsFilename,
\r
897 ArgX, ArgY, ArgZ // [HGM] placement: for window-placement options stored relative to main window
\r
905 String *pString; // ArgString
\r
906 int *pInt; // ArgInt
\r
907 float *pFloat; // ArgFloat
\r
908 Boolean *pBoolean; // ArgBoolean
\r
909 COLORREF *pColor; // ArgColor
\r
910 ColorClass cc; // ArgAttribs
\r
911 String *pFilename; // ArgFilename
\r
912 BoardSize *pBoardSize; // ArgBoardSize
\r
913 int whichFont; // ArgFont
\r
914 DCB *pDCB; // ArgCommSettings
\r
915 String *pFilename; // ArgSettingsFilename
\r
923 ArgDescriptor argDescriptors[] = {
\r
924 /* positional arguments */
\r
925 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
926 { "", ArgNone, NULL },
\r
927 /* keyword arguments */
\r
929 { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },
\r
930 { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },
\r
931 { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },
\r
932 { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },
\r
933 { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },
\r
934 { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },
\r
935 { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },
\r
936 { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },
\r
937 { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },
\r
938 { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },
\r
939 { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },
\r
940 { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },
\r
941 { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },
\r
942 { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },
\r
943 { "initString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
944 { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
945 { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },
\r
946 { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,
\r
948 { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,
\r
950 { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,
\r
952 { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },
\r
953 { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,
\r
955 { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },
\r
956 { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
957 { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
958 { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
959 { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
960 { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },
\r
961 { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },
\r
962 { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
963 { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
964 { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
965 { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
966 { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
967 { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
968 { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
969 { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
970 { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
971 { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
972 /*!!bitmapDirectory?*/
\r
973 { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
974 { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
975 { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
976 { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
977 { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },
\r
978 { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },
\r
979 { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },
\r
980 { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },
\r
981 { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },
\r
982 { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },
\r
983 { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },
\r
984 { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },
\r
985 { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
986 { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
987 { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
988 { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
989 { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
990 { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
991 { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
992 { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
993 { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
994 { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
995 { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
996 { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
997 { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },
\r
998 { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },
\r
999 { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
1000 { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
1001 { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },
\r
1002 { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },
\r
1003 { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },
\r
1004 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
1005 { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
1006 { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
1007 { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
1008 { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },
\r
1009 { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },
\r
1010 { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },
\r
1011 { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },
\r
1012 { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
1013 { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
1014 { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
1015 { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
1016 { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
1017 { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
1018 { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
1019 { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
1020 { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },
\r
1021 { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },
\r
1022 { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
1023 { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
1024 { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
1025 { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
1026 { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },
\r
1027 { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },
\r
1028 { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
1029 { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
1030 { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },
\r
1031 { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },
\r
1032 { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
1033 { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
1034 { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },
\r
1035 { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },
\r
1036 { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
1037 { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
1038 { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
1039 { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
1040 { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
1041 { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
1042 { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },
\r
1043 { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },
\r
1044 { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
1045 { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
1046 { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },
\r
1047 { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },
\r
1048 { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
1049 { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
1050 { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },
\r
1051 { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1052 { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1053 { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1054 { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },
\r
1055 { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1056 { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1057 { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1058 { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },
\r
1059 { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1060 { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1061 { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1062 { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },
\r
1063 { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1064 { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1065 { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1066 { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors,
\r
1067 FALSE }, /* only so that old WinBoard.ini files from betas can be read */
\r
1068 { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },
\r
1069 { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },
\r
1070 { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },
\r
1071 { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },
\r
1072 { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },
\r
1073 { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },
\r
1074 { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE }, /* [AS] */
\r
1075 { "boardSize", ArgBoardSize, (LPVOID) &boardSize,
\r
1076 TRUE }, /* must come after all fonts */
\r
1077 { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },
\r
1078 { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,
\r
1079 FALSE }, /* historical; kept only so old winboard.ini files will parse */
\r
1080 { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },
\r
1081 { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },
\r
1082 { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
1083 { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
1084 { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },
\r
1085 { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1086 { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1087 { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1088 { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },
\r
1089 { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },
\r
1090 { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
1091 { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
1092 { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },
\r
1093 { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },
\r
1094 { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
1095 { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
1096 { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },
\r
1097 { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },
\r
1098 { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
1099 { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
1100 { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },
\r
1101 { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },
\r
1102 { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
1103 { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
1104 { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },
\r
1105 { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1106 { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1107 { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
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
1397 // [HGM] placement: put all window layouts last in ini file, but man X,Y before all others
\r
1398 { "minX", ArgZ, (LPVOID) &minX, FALSE }, // [HGM] placement: to make suer auxialary windows can be placed
\r
1399 { "minY", ArgZ, (LPVOID) &minY, FALSE },
\r
1400 { "winWidth", ArgInt, (LPVOID) &winWidth, TRUE }, // [HGM] placement: dummies to remember right & bottom
\r
1401 { "winHeight", ArgInt, (LPVOID) &winHeight, TRUE }, // for attaching auxiliary windows to them
\r
1402 { "x", ArgInt, (LPVOID) &boardX, TRUE },
\r
1403 { "y", ArgInt, (LPVOID) &boardY, TRUE },
\r
1404 { "icsX", ArgX, (LPVOID) &wpConsole.x, TRUE },
\r
1405 { "icsY", ArgY, (LPVOID) &wpConsole.y, TRUE },
\r
1406 { "icsW", ArgInt, (LPVOID) &wpConsole.width, TRUE },
\r
1407 { "icsH", ArgInt, (LPVOID) &wpConsole.height, TRUE },
\r
1408 { "analysisX", ArgX, (LPVOID) &analysisX, FALSE }, // [HGM] placement: analysis window no longer exists
\r
1409 { "analysisY", ArgY, (LPVOID) &analysisY, FALSE }, // provided for compatibility with old ini files
\r
1410 { "analysisW", ArgInt, (LPVOID) &analysisW, FALSE },
\r
1411 { "analysisH", ArgInt, (LPVOID) &analysisH, FALSE },
\r
1412 { "commentX", ArgX, (LPVOID) &commentX, TRUE },
\r
1413 { "commentY", ArgY, (LPVOID) &commentY, TRUE },
\r
1414 { "commentW", ArgInt, (LPVOID) &commentW, TRUE },
\r
1415 { "commentH", ArgInt, (LPVOID) &commentH, TRUE },
\r
1416 { "tagsX", ArgX, (LPVOID) &editTagsX, TRUE },
\r
1417 { "tagsY", ArgY, (LPVOID) &editTagsY, TRUE },
\r
1418 { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },
\r
1419 { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },
\r
1420 { "gameListX", ArgX, (LPVOID) &wpGameList.x, TRUE },
\r
1421 { "gameListY", ArgY, (LPVOID) &wpGameList.y, TRUE },
\r
1422 { "gameListW", ArgInt, (LPVOID) &wpGameList.width, TRUE },
\r
1423 { "gameListH", ArgInt, (LPVOID) &wpGameList.height, TRUE },
\r
1424 /* [AS] Layout stuff */
\r
1425 { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },
\r
1426 { "moveHistoryX", ArgX, (LPVOID) &wpMoveHistory.x, TRUE },
\r
1427 { "moveHistoryY", ArgY, (LPVOID) &wpMoveHistory.y, TRUE },
\r
1428 { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },
\r
1429 { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },
\r
1431 { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },
\r
1432 { "evalGraphX", ArgX, (LPVOID) &wpEvalGraph.x, TRUE },
\r
1433 { "evalGraphY", ArgY, (LPVOID) &wpEvalGraph.y, TRUE },
\r
1434 { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },
\r
1435 { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },
\r
1437 { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },
\r
1438 { "engineOutputX", ArgX, (LPVOID) &wpEngineOutput.x, TRUE },
\r
1439 { "engineOutputY", ArgY, (LPVOID) &wpEngineOutput.y, TRUE },
\r
1440 { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },
\r
1441 { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },
\r
1443 { NULL, ArgNone, NULL, FALSE }
\r
1447 /* Kludge for indirection files on command line */
\r
1448 char* lastIndirectionFilename;
\r
1449 ArgDescriptor argDescriptorIndirection =
\r
1450 { "", ArgSettingsFilename, (LPVOID) NULL, FALSE };
\r
1454 ExitArgError(char *msg, char *badArg)
\r
1456 char buf[MSG_SIZ];
\r
1458 sprintf(buf, "%s %s", msg, badArg);
\r
1459 DisplayFatalError(buf, 0, 2);
\r
1463 /* Command line font name parser. NULL name means do nothing.
\r
1464 Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"
\r
1465 For backward compatibility, syntax without the colon is also
\r
1466 accepted, but font names with digits in them won't work in that case.
\r
1469 ParseFontName(char *name, MyFontParams *mfp)
\r
1472 if (name == NULL) return;
\r
1474 q = strchr(p, ':');
\r
1476 if (q - p >= sizeof(mfp->faceName))
\r
1477 ExitArgError("Font name too long:", name);
\r
1478 memcpy(mfp->faceName, p, q - p);
\r
1479 mfp->faceName[q - p] = NULLCHAR;
\r
1482 q = mfp->faceName;
\r
1483 while (*p && !isdigit(*p)) {
\r
1485 if (q - mfp->faceName >= sizeof(mfp->faceName))
\r
1486 ExitArgError("Font name too long:", name);
\r
1488 while (q > mfp->faceName && q[-1] == ' ') q--;
\r
1491 if (!*p) ExitArgError("Font point size missing:", name);
\r
1492 mfp->pointSize = (float) atof(p);
\r
1493 mfp->bold = (strchr(p, 'b') != NULL);
\r
1494 mfp->italic = (strchr(p, 'i') != NULL);
\r
1495 mfp->underline = (strchr(p, 'u') != NULL);
\r
1496 mfp->strikeout = (strchr(p, 's') != NULL);
\r
1499 /* Color name parser.
\r
1500 X version accepts X color names, but this one
\r
1501 handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */
\r
1503 ParseColorName(char *name)
\r
1505 int red, green, blue, count;
\r
1506 char buf[MSG_SIZ];
\r
1508 count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);
\r
1510 count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d",
\r
1511 &red, &green, &blue);
\r
1514 sprintf(buf, "Can't parse color name %s", name);
\r
1515 DisplayError(buf, 0);
\r
1516 return RGB(0, 0, 0);
\r
1518 return PALETTERGB(red, green, blue);
\r
1522 void ParseAttribs(COLORREF *color, int *effects, char* argValue)
\r
1524 char *e = argValue;
\r
1528 if (*e == 'b') eff |= CFE_BOLD;
\r
1529 else if (*e == 'i') eff |= CFE_ITALIC;
\r
1530 else if (*e == 'u') eff |= CFE_UNDERLINE;
\r
1531 else if (*e == 's') eff |= CFE_STRIKEOUT;
\r
1532 else if (*e == '#' || isdigit(*e)) break;
\r
1536 *color = ParseColorName(e);
\r
1541 ParseBoardSize(char *name)
\r
1543 BoardSize bs = SizeTiny;
\r
1544 while (sizeInfo[bs].name != NULL) {
\r
1545 if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;
\r
1548 ExitArgError("Unrecognized board size value", name);
\r
1549 return bs; /* not reached */
\r
1554 StringGet(void *getClosure)
\r
1556 char **p = (char **) getClosure;
\r
1561 FileGet(void *getClosure)
\r
1564 FILE* f = (FILE*) getClosure;
\r
1567 if (c == '\r') c = getc(f); // work around DOS format files by bypassing the '\r' completely
\r
1574 /* Parse settings file named "name". If file found, return the
\r
1575 full name in fullname and return TRUE; else return FALSE */
\r
1577 ParseSettingsFile(char *name, char fullname[MSG_SIZ])
\r
1581 int ok; char buf[MSG_SIZ];
\r
1583 ok = SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy);
\r
1584 if(!ok && strchr(name, '.') == NULL) { // [HGM] append default file-name extension '.ini' when needed
\r
1585 sprintf(buf, "%s.ini", name);
\r
1586 ok = SearchPath(installDir, buf, NULL, MSG_SIZ, fullname, &dummy);
\r
1589 f = fopen(fullname, "r");
\r
1591 ParseArgs(FileGet, f);
\r
1600 ParseArgs(GetFunc get, void *cl)
\r
1602 char argName[ARG_MAX];
\r
1603 char argValue[ARG_MAX];
\r
1604 ArgDescriptor *ad;
\r
1613 while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);
\r
1614 if (ch == NULLCHAR) break;
\r
1616 /* Comment to end of line */
\r
1618 while (ch != '\n' && ch != NULLCHAR) ch = get(cl);
\r
1620 } else if (ch == '/' || ch == '-') {
\r
1623 while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&
\r
1624 ch != '\n' && ch != '\t') {
\r
1630 for (ad = argDescriptors; ad->argName != NULL; ad++)
\r
1631 if (strcmp(ad->argName, argName + 1) == 0) break;
\r
1633 if (ad->argName == NULL)
\r
1634 ExitArgError("Unrecognized argument", argName);
\r
1636 } else if (ch == '@') {
\r
1637 /* Indirection file */
\r
1638 ad = &argDescriptorIndirection;
\r
1641 /* Positional argument */
\r
1642 ad = &argDescriptors[posarg++];
\r
1643 strcpy(argName, ad->argName);
\r
1646 if (ad->argType == ArgTrue) {
\r
1647 *(Boolean *) ad->argLoc = TRUE;
\r
1650 if (ad->argType == ArgFalse) {
\r
1651 *(Boolean *) ad->argLoc = FALSE;
\r
1655 while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
\r
1656 if (ch == NULLCHAR || ch == '\n') {
\r
1657 ExitArgError("No value provided for argument", argName);
\r
1661 // Quoting with { }. No characters have to (or can) be escaped.
\r
1662 // Thus the string cannot contain a '}' character.
\r
1682 } else if (ch == '\'' || ch == '"') {
\r
1683 // Quoting with ' ' or " ", with \ as escape character.
\r
1684 // Inconvenient for long strings that may contain Windows filenames.
\r
1701 if (ch == start) {
\r
1710 if (ad->argType == ArgFilename
\r
1711 || ad->argType == ArgSettingsFilename) {
\r
1717 ExitArgError("Incomplete \\ escape in value for", argName);
\r
1741 for (i = 0; i < 3; i++) {
\r
1742 if (ch >= '0' && ch <= '7') {
\r
1743 octval = octval*8 + (ch - '0');
\r
1750 *q++ = (char) octval;
\r
1761 while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {
\r
1768 switch (ad->argType) {
\r
1770 *(int *) ad->argLoc = atoi(argValue);
\r
1774 *(int *) ad->argLoc = atoi(argValue) + boardX; // [HGM] placement: translate stored relative to absolute
\r
1778 *(int *) ad->argLoc = atoi(argValue) + boardY; // (this is really kludgey, it should be done where used...)
\r
1782 *(int *) ad->argLoc = atoi(argValue);
\r
1783 EnsureOnScreen(&boardX, &boardY, minX, minY);
\r
1787 *(float *) ad->argLoc = (float) atof(argValue);
\r
1792 *(char **) ad->argLoc = strdup(argValue);
\r
1795 case ArgSettingsFilename:
\r
1797 char fullname[MSG_SIZ];
\r
1798 if (ParseSettingsFile(argValue, fullname)) {
\r
1799 if (ad->argLoc != NULL) {
\r
1800 *(char **) ad->argLoc = strdup(fullname);
\r
1803 if (ad->argLoc != NULL) {
\r
1805 ExitArgError("Failed to open indirection file", argValue);
\r
1812 switch (argValue[0]) {
\r
1815 *(Boolean *) ad->argLoc = TRUE;
\r
1819 *(Boolean *) ad->argLoc = FALSE;
\r
1822 ExitArgError("Unrecognized boolean argument value", argValue);
\r
1828 *(COLORREF *)ad->argLoc = ParseColorName(argValue);
\r
1831 case ArgAttribs: {
\r
1832 ColorClass cc = (ColorClass)ad->argLoc;
\r
1833 ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);
\r
1837 case ArgBoardSize:
\r
1838 *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);
\r
1842 ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);
\r
1845 case ArgCommSettings:
\r
1846 ParseCommSettings(argValue, &dcb);
\r
1850 ExitArgError("Unrecognized argument", argValue);
\r
1859 LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
\r
1861 HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
\r
1862 lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);
\r
1865 lf->lfEscapement = 0;
\r
1866 lf->lfOrientation = 0;
\r
1867 lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;
\r
1868 lf->lfItalic = mfp->italic;
\r
1869 lf->lfUnderline = mfp->underline;
\r
1870 lf->lfStrikeOut = mfp->strikeout;
\r
1871 lf->lfCharSet = DEFAULT_CHARSET;
\r
1872 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
1873 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
1874 lf->lfQuality = DEFAULT_QUALITY;
\r
1875 lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
\r
1876 strcpy(lf->lfFaceName, mfp->faceName);
\r
1880 CreateFontInMF(MyFont *mf)
\r
1882 LFfromMFP(&mf->lf, &mf->mfp);
\r
1883 if (mf->hf) DeleteObject(mf->hf);
\r
1884 mf->hf = CreateFontIndirect(&mf->lf);
\r
1888 SetDefaultTextAttribs()
\r
1891 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1892 ParseAttribs(&textAttribs[cc].color,
\r
1893 &textAttribs[cc].effects,
\r
1894 defaultTextAttribs[cc]);
\r
1899 SetDefaultSounds()
\r
1903 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1904 textAttribs[cc].sound.name = strdup("");
\r
1905 textAttribs[cc].sound.data = NULL;
\r
1907 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1908 sounds[sc].name = strdup("");
\r
1909 sounds[sc].data = NULL;
\r
1911 sounds[(int)SoundBell].name = strdup(SOUND_BELL);
\r
1919 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1920 MyLoadSound(&textAttribs[cc].sound);
\r
1922 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1923 MyLoadSound(&sounds[sc]);
\r
1928 InitAppData(LPSTR lpCmdLine)
\r
1931 char buf[ARG_MAX], currDir[MSG_SIZ];
\r
1934 programName = szAppName;
\r
1936 /* Initialize to defaults */
\r
1937 lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);
\r
1938 darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);
\r
1939 whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);
\r
1940 blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);
\r
1941 highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);
\r
1942 premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);
\r
1943 consoleBackgroundColor = ParseColorName(COLOR_BKGD);
\r
1944 SetDefaultTextAttribs();
\r
1945 SetDefaultSounds();
\r
1946 appData.movesPerSession = MOVES_PER_SESSION;
\r
1947 appData.initString = INIT_STRING;
\r
1948 appData.secondInitString = INIT_STRING;
\r
1949 appData.firstComputerString = COMPUTER_STRING;
\r
1950 appData.secondComputerString = COMPUTER_STRING;
\r
1951 appData.firstChessProgram = FIRST_CHESS_PROGRAM;
\r
1952 appData.secondChessProgram = SECOND_CHESS_PROGRAM;
\r
1953 appData.firstPlaysBlack = FALSE;
\r
1954 appData.noChessProgram = FALSE;
\r
1955 chessProgram = FALSE;
\r
1956 appData.firstHost = FIRST_HOST;
\r
1957 appData.secondHost = SECOND_HOST;
\r
1958 appData.firstDirectory = FIRST_DIRECTORY;
\r
1959 appData.secondDirectory = SECOND_DIRECTORY;
\r
1960 appData.bitmapDirectory = "";
\r
1961 appData.remoteShell = REMOTE_SHELL;
\r
1962 appData.remoteUser = "";
\r
1963 appData.timeDelay = TIME_DELAY;
\r
1964 appData.timeControl = TIME_CONTROL;
\r
1965 appData.timeIncrement = TIME_INCREMENT;
\r
1966 appData.icsActive = FALSE;
\r
1967 appData.icsHost = "";
\r
1968 appData.icsPort = ICS_PORT;
\r
1969 appData.icsCommPort = ICS_COMM_PORT;
\r
1970 appData.icsLogon = ICS_LOGON;
\r
1971 appData.icsHelper = "";
\r
1972 appData.useTelnet = FALSE;
\r
1973 appData.telnetProgram = TELNET_PROGRAM;
\r
1974 appData.gateway = "";
\r
1975 appData.loadGameFile = "";
\r
1976 appData.loadGameIndex = 0;
\r
1977 appData.saveGameFile = "";
\r
1978 appData.autoSaveGames = FALSE;
\r
1979 appData.loadPositionFile = "";
\r
1980 appData.loadPositionIndex = 1;
\r
1981 appData.savePositionFile = "";
\r
1982 appData.matchMode = FALSE;
\r
1983 appData.matchGames = 0;
\r
1984 appData.monoMode = FALSE;
\r
1985 appData.debugMode = FALSE;
\r
1986 appData.clockMode = TRUE;
\r
1987 boardSize = (BoardSize) -1; /* determine by screen size */
\r
1988 appData.Iconic = FALSE; /*unused*/
\r
1989 appData.searchTime = "";
\r
1990 appData.searchDepth = 0;
\r
1991 appData.showCoords = FALSE;
\r
1992 appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/
\r
1993 appData.autoCallFlag = FALSE;
\r
1994 appData.flipView = FALSE;
\r
1995 appData.autoFlipView = TRUE;
\r
1996 appData.cmailGameName = "";
\r
1997 appData.alwaysPromoteToQueen = FALSE;
\r
1998 appData.oldSaveStyle = FALSE;
\r
1999 appData.quietPlay = FALSE;
\r
2000 appData.showThinking = FALSE;
\r
2001 appData.ponderNextMove = TRUE;
\r
2002 appData.periodicUpdates = TRUE;
\r
2003 appData.popupExitMessage = TRUE;
\r
2004 appData.popupMoveErrors = FALSE;
\r
2005 appData.autoObserve = FALSE;
\r
2006 appData.autoComment = FALSE;
\r
2007 appData.animate = TRUE;
\r
2008 appData.animSpeed = 10;
\r
2009 appData.animateDragging = TRUE;
\r
2010 appData.highlightLastMove = TRUE;
\r
2011 appData.getMoveList = TRUE;
\r
2012 appData.testLegality = TRUE;
\r
2013 appData.premove = TRUE;
\r
2014 appData.premoveWhite = FALSE;
\r
2015 appData.premoveWhiteText = "";
\r
2016 appData.premoveBlack = FALSE;
\r
2017 appData.premoveBlackText = "";
\r
2018 appData.icsAlarm = TRUE;
\r
2019 appData.icsAlarmTime = 5000;
\r
2020 appData.autoRaiseBoard = TRUE;
\r
2021 appData.localLineEditing = TRUE;
\r
2022 appData.colorize = TRUE;
\r
2023 appData.reuseFirst = TRUE;
\r
2024 appData.reuseSecond = TRUE;
\r
2025 appData.blindfold = FALSE;
\r
2026 appData.icsEngineAnalyze = FALSE;
\r
2027 memset(&dcb, 0, sizeof(DCB)); // required by VS 2002 +
\r
2028 dcb.DCBlength = sizeof(DCB);
\r
2029 dcb.BaudRate = 9600;
\r
2030 dcb.fBinary = TRUE;
\r
2031 dcb.fParity = FALSE;
\r
2032 dcb.fOutxCtsFlow = FALSE;
\r
2033 dcb.fOutxDsrFlow = FALSE;
\r
2034 dcb.fDtrControl = DTR_CONTROL_ENABLE;
\r
2035 dcb.fDsrSensitivity = FALSE;
\r
2036 dcb.fTXContinueOnXoff = TRUE;
\r
2037 dcb.fOutX = FALSE;
\r
2039 dcb.fNull = FALSE;
\r
2040 dcb.fRtsControl = RTS_CONTROL_ENABLE;
\r
2041 dcb.fAbortOnError = FALSE;
\r
2043 dcb.Parity = SPACEPARITY;
\r
2044 dcb.StopBits = ONESTOPBIT;
\r
2045 settingsFileName = SETTINGS_FILE;
\r
2046 saveSettingsOnExit = TRUE;
\r
2047 boardX = CW_USEDEFAULT;
\r
2048 boardY = CW_USEDEFAULT;
\r
2049 analysisX = CW_USEDEFAULT;
\r
2050 analysisY = CW_USEDEFAULT;
\r
2051 analysisW = CW_USEDEFAULT;
\r
2052 analysisH = CW_USEDEFAULT;
\r
2053 commentX = CW_USEDEFAULT;
\r
2054 commentY = CW_USEDEFAULT;
\r
2055 commentW = CW_USEDEFAULT;
\r
2056 commentH = CW_USEDEFAULT;
\r
2057 editTagsX = CW_USEDEFAULT;
\r
2058 editTagsY = CW_USEDEFAULT;
\r
2059 editTagsW = CW_USEDEFAULT;
\r
2060 editTagsH = CW_USEDEFAULT;
\r
2061 icsTextMenuString = ICS_TEXT_MENU_DEFAULT;
\r
2062 icsNames = ICS_NAMES;
\r
2063 firstChessProgramNames = FCP_NAMES;
\r
2064 secondChessProgramNames = SCP_NAMES;
\r
2065 appData.initialMode = "";
\r
2066 appData.variant = "normal";
\r
2067 appData.firstProtocolVersion = PROTOVER;
\r
2068 appData.secondProtocolVersion = PROTOVER;
\r
2069 appData.showButtonBar = TRUE;
\r
2071 /* [AS] New properties (see comments in header file) */
\r
2072 appData.firstScoreIsAbsolute = FALSE;
\r
2073 appData.secondScoreIsAbsolute = FALSE;
\r
2074 appData.saveExtendedInfoInPGN = FALSE;
\r
2075 appData.hideThinkingFromHuman = FALSE;
\r
2076 appData.liteBackTextureFile = "";
\r
2077 appData.liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
2078 appData.darkBackTextureFile = "";
\r
2079 appData.darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
2080 appData.renderPiecesWithFont = "";
\r
2081 appData.fontToPieceTable = "";
\r
2082 appData.fontBackColorWhite = 0;
\r
2083 appData.fontForeColorWhite = 0;
\r
2084 appData.fontBackColorBlack = 0;
\r
2085 appData.fontForeColorBlack = 0;
\r
2086 appData.fontPieceSize = 80;
\r
2087 appData.overrideLineGap = 1;
\r
2088 appData.adjudicateLossThreshold = 0;
\r
2089 appData.delayBeforeQuit = 0;
\r
2090 appData.delayAfterQuit = 0;
\r
2091 appData.nameOfDebugFile = "winboard.debug";
\r
2092 appData.pgnEventHeader = "Computer Chess Game";
\r
2093 appData.defaultFrcPosition = -1;
\r
2094 appData.gameListTags = GLT_DEFAULT_TAGS;
\r
2095 appData.saveOutOfBookInfo = TRUE;
\r
2096 appData.showEvalInMoveHistory = TRUE;
\r
2097 appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );
\r
2098 appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );
\r
2099 appData.highlightMoveWithArrow = FALSE;
\r
2100 appData.highlightArrowColor = ParseColorName( "#FFFF80" );
\r
2101 appData.useStickyWindows = TRUE;
\r
2102 appData.adjudicateDrawMoves = 0;
\r
2103 appData.autoDisplayComment = TRUE;
\r
2104 appData.autoDisplayTags = TRUE;
\r
2105 appData.firstIsUCI = FALSE;
\r
2106 appData.secondIsUCI = FALSE;
\r
2107 appData.firstHasOwnBookUCI = TRUE;
\r
2108 appData.secondHasOwnBookUCI = TRUE;
\r
2109 appData.polyglotDir = "";
\r
2110 appData.usePolyglotBook = FALSE;
\r
2111 appData.polyglotBook = "";
\r
2112 appData.defaultHashSize = 64;
\r
2113 appData.defaultCacheSizeEGTB = 4;
\r
2114 appData.defaultPathEGTB = "c:\\egtb";
\r
2115 appData.firstOptions = "";
\r
2116 appData.secondOptions = "";
\r
2118 InitWindowPlacement( &wpGameList );
\r
2119 InitWindowPlacement( &wpMoveHistory );
\r
2120 InitWindowPlacement( &wpEvalGraph );
\r
2121 InitWindowPlacement( &wpEngineOutput );
\r
2122 InitWindowPlacement( &wpConsole );
\r
2124 /* [HGM] User-selectable board size, adjudication control, miscellaneous */
\r
2125 appData.NrFiles = -1;
\r
2126 appData.NrRanks = -1;
\r
2127 appData.holdingsSize = -1;
\r
2128 appData.testClaims = FALSE;
\r
2129 appData.checkMates = FALSE;
\r
2130 appData.materialDraws= FALSE;
\r
2131 appData.trivialDraws = FALSE;
\r
2132 appData.ruleMoves = 51;
\r
2133 appData.drawRepeats = 6;
\r
2134 appData.matchPause = 10000;
\r
2135 appData.alphaRank = FALSE;
\r
2136 appData.allWhite = FALSE;
\r
2137 appData.upsideDown = FALSE;
\r
2138 appData.serverPause = 15;
\r
2139 appData.serverMovesName = NULL;
\r
2140 appData.suppressLoadMoves = FALSE;
\r
2141 appData.firstTimeOdds = 1;
\r
2142 appData.secondTimeOdds = 1;
\r
2143 appData.firstAccumulateTC = 1; // combine previous and current sessions
\r
2144 appData.secondAccumulateTC = 1;
\r
2145 appData.firstNPS = -1; // [HGM] nps: use wall-clock time
\r
2146 appData.secondNPS = -1;
\r
2147 appData.engineComments = 1;
\r
2148 appData.smpCores = 1; // [HGM] SMP: max nr of cores
\r
2149 appData.egtFormats = "";
\r
2152 appData.zippyTalk = ZIPPY_TALK;
\r
2153 appData.zippyPlay = ZIPPY_PLAY;
\r
2154 appData.zippyLines = ZIPPY_LINES;
\r
2155 appData.zippyPinhead = ZIPPY_PINHEAD;
\r
2156 appData.zippyPassword = ZIPPY_PASSWORD;
\r
2157 appData.zippyPassword2 = ZIPPY_PASSWORD2;
\r
2158 appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;
\r
2159 appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;
\r
2160 appData.zippyUseI = ZIPPY_USE_I;
\r
2161 appData.zippyBughouse = ZIPPY_BUGHOUSE;
\r
2162 appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;
\r
2163 appData.zippyGameEnd = ZIPPY_GAME_END;
\r
2164 appData.zippyGameStart = ZIPPY_GAME_START;
\r
2165 appData.zippyAdjourn = ZIPPY_ADJOURN;
\r
2166 appData.zippyAbort = ZIPPY_ABORT;
\r
2167 appData.zippyVariants = ZIPPY_VARIANTS;
\r
2168 appData.zippyMaxGames = ZIPPY_MAX_GAMES;
\r
2169 appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;
\r
2172 /* Point font array elements to structures and
\r
2173 parse default font names */
\r
2174 for (i=0; i<NUM_FONTS; i++) {
\r
2175 for (j=0; j<NUM_SIZES; j++) {
\r
2176 font[j][i] = &fontRec[j][i];
\r
2177 ParseFontName(font[j][i]->def, &font[j][i]->mfp);
\r
2181 /* Parse default settings file if any */
\r
2182 if (ParseSettingsFile(settingsFileName, buf)) {
\r
2183 settingsFileName = strdup(buf);
\r
2186 /* Parse command line */
\r
2187 ParseArgs(StringGet, &lpCmdLine);
\r
2189 /* [HGM] make sure board size is acceptable */
\r
2190 if(appData.NrFiles > BOARD_SIZE ||
\r
2191 appData.NrRanks > BOARD_SIZE )
\r
2192 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
2194 /* [HGM] After parsing the options from the .ini file, and overruling them
\r
2195 * with options from the command line, we now make an even higher priority
\r
2196 * overrule by WB options attached to the engine command line. This so that
\r
2197 * tournament managers can use WB options (such as /timeOdds) that follow
\r
2200 if(appData.firstChessProgram != NULL) {
\r
2201 char *p = StrStr(appData.firstChessProgram, "WBopt");
\r
2202 static char *f = "first";
\r
2203 char buf[MSG_SIZ], *q = buf;
\r
2204 if(p != NULL) { // engine command line contains WinBoard options
\r
2205 sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"
\r
2206 ParseArgs(StringGet, &q);
\r
2207 p[-1] = 0; // cut them offengine command line
\r
2210 // now do same for second chess program
\r
2211 if(appData.secondChessProgram != NULL) {
\r
2212 char *p = StrStr(appData.secondChessProgram, "WBopt");
\r
2213 static char *s = "second";
\r
2214 char buf[MSG_SIZ], *q = buf;
\r
2215 if(p != NULL) { // engine command line contains WinBoard options
\r
2216 sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"
\r
2217 ParseArgs(StringGet, &q);
\r
2218 p[-1] = 0; // cut them offengine command line
\r
2223 /* Propagate options that affect others */
\r
2224 if (appData.matchMode || appData.matchGames) chessProgram = TRUE;
\r
2225 if (appData.icsActive || appData.noChessProgram) {
\r
2226 chessProgram = FALSE; /* not local chess program mode */
\r
2229 /* Open startup dialog if needed */
\r
2230 if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||
\r
2231 (appData.icsActive && *appData.icsHost == NULLCHAR) ||
\r
2232 (chessProgram && (*appData.firstChessProgram == NULLCHAR ||
\r
2233 *appData.secondChessProgram == NULLCHAR))) {
\r
2236 lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);
\r
2237 DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);
\r
2238 FreeProcInstance(lpProc);
\r
2241 /* Make sure save files land in the right (?) directory */
\r
2242 if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {
\r
2243 appData.saveGameFile = strdup(buf);
\r
2245 if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {
\r
2246 appData.savePositionFile = strdup(buf);
\r
2249 /* Finish initialization for fonts and sounds */
\r
2250 for (i=0; i<NUM_FONTS; i++) {
\r
2251 for (j=0; j<NUM_SIZES; j++) {
\r
2252 CreateFontInMF(font[j][i]);
\r
2255 /* xboard, and older WinBoards, controlled the move sound with the
\r
2256 appData.ringBellAfterMoves option. In the current WinBoard, we
\r
2257 always turn the option on (so that the backend will call us),
\r
2258 then let the user turn the sound off by setting it to silence if
\r
2259 desired. To accommodate old winboard.ini files saved by old
\r
2260 versions of WinBoard, we also turn off the sound if the option
\r
2261 was initially set to false. */
\r
2262 if (!appData.ringBellAfterMoves) {
\r
2263 sounds[(int)SoundMove].name = strdup("");
\r
2264 appData.ringBellAfterMoves = TRUE;
\r
2266 GetCurrentDirectory(MSG_SIZ, currDir);
\r
2267 SetCurrentDirectory(installDir);
\r
2269 SetCurrentDirectory(currDir);
\r
2271 p = icsTextMenuString;
\r
2272 if (p[0] == '@') {
\r
2273 FILE* f = fopen(p + 1, "r");
\r
2275 DisplayFatalError(p + 1, errno, 2);
\r
2278 i = fread(buf, 1, sizeof(buf)-1, f);
\r
2280 buf[i] = NULLCHAR;
\r
2283 ParseIcsTextMenu(strdup(p));
\r
2290 HMENU hmenu = GetMenu(hwndMain);
\r
2292 (void) EnableMenuItem(hmenu, IDM_CommPort,
\r
2293 MF_BYCOMMAND|((appData.icsActive &&
\r
2294 *appData.icsCommPort != NULLCHAR) ?
\r
2295 MF_ENABLED : MF_GRAYED));
\r
2296 (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,
\r
2297 MF_BYCOMMAND|(saveSettingsOnExit ?
\r
2298 MF_CHECKED : MF_UNCHECKED));
\r
2303 SaveSettings(char* name)
\r
2306 ArgDescriptor *ad;
\r
2307 WINDOWPLACEMENT wp;
\r
2308 char dir[MSG_SIZ];
\r
2310 if (!hwndMain) return;
\r
2312 GetCurrentDirectory(MSG_SIZ, dir);
\r
2313 SetCurrentDirectory(installDir);
\r
2314 f = fopen(name, "w");
\r
2315 SetCurrentDirectory(dir);
\r
2317 DisplayError(name, errno);
\r
2320 fprintf(f, ";\n");
\r
2321 fprintf(f, "; %s Save Settings file\n", PACKAGE_STRING);
\r
2322 fprintf(f, ";\n");
\r
2323 fprintf(f, "; You can edit the values of options that are already set in this file,\n");
\r
2324 fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");
\r
2325 fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");
\r
2326 fprintf(f, ";\n");
\r
2328 wp.length = sizeof(WINDOWPLACEMENT);
\r
2329 GetWindowPlacement(hwndMain, &wp);
\r
2330 boardX = wp.rcNormalPosition.left;
\r
2331 boardY = wp.rcNormalPosition.top;
\r
2333 if (hwndConsole) {
\r
2334 GetWindowPlacement(hwndConsole, &wp);
\r
2335 wpConsole.x = wp.rcNormalPosition.left;
\r
2336 wpConsole.y = wp.rcNormalPosition.top;
\r
2337 wpConsole.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2338 wpConsole.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2341 if (analysisDialog) {
\r
2342 GetWindowPlacement(analysisDialog, &wp);
\r
2343 analysisX = wp.rcNormalPosition.left;
\r
2344 analysisY = wp.rcNormalPosition.top;
\r
2345 analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2346 analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2349 if (commentDialog) {
\r
2350 GetWindowPlacement(commentDialog, &wp);
\r
2351 commentX = wp.rcNormalPosition.left;
\r
2352 commentY = wp.rcNormalPosition.top;
\r
2353 commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2354 commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2357 if (editTagsDialog) {
\r
2358 GetWindowPlacement(editTagsDialog, &wp);
\r
2359 editTagsX = wp.rcNormalPosition.left;
\r
2360 editTagsY = wp.rcNormalPosition.top;
\r
2361 editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2362 editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2365 if (gameListDialog) {
\r
2366 GetWindowPlacement(gameListDialog, &wp);
\r
2367 wpGameList.x = wp.rcNormalPosition.left;
\r
2368 wpGameList.y = wp.rcNormalPosition.top;
\r
2369 wpGameList.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2370 wpGameList.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2373 /* [AS] Move history */
\r
2374 wpMoveHistory.visible = MoveHistoryIsUp();
\r
2376 if( moveHistoryDialog ) {
\r
2377 GetWindowPlacement(moveHistoryDialog, &wp);
\r
2378 wpMoveHistory.x = wp.rcNormalPosition.left;
\r
2379 wpMoveHistory.y = wp.rcNormalPosition.top;
\r
2380 wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2381 wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2384 /* [AS] Eval graph */
\r
2385 wpEvalGraph.visible = EvalGraphIsUp();
\r
2387 if( evalGraphDialog ) {
\r
2388 GetWindowPlacement(evalGraphDialog, &wp);
\r
2389 wpEvalGraph.x = wp.rcNormalPosition.left;
\r
2390 wpEvalGraph.y = wp.rcNormalPosition.top;
\r
2391 wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2392 wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2395 /* [AS] Engine output */
\r
2396 wpEngineOutput.visible = EngineOutputIsUp();
\r
2398 if( engineOutputDialog ) {
\r
2399 GetWindowPlacement(engineOutputDialog, &wp);
\r
2400 wpEngineOutput.x = wp.rcNormalPosition.left;
\r
2401 wpEngineOutput.y = wp.rcNormalPosition.top;
\r
2402 wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2403 wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2406 for (ad = argDescriptors; ad->argName != NULL; ad++) {
\r
2407 if (!ad->save) continue;
\r
2408 switch (ad->argType) {
\r
2411 char *p = *(char **)ad->argLoc;
\r
2412 if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {
\r
2413 /* Quote multiline values or \-containing values
\r
2414 with { } if possible */
\r
2415 fprintf(f, "/%s={%s}\n", ad->argName, p);
\r
2417 /* Else quote with " " */
\r
2418 fprintf(f, "/%s=\"", ad->argName);
\r
2420 if (*p == '\n') fprintf(f, "\n");
\r
2421 else if (*p == '\r') fprintf(f, "\\r");
\r
2422 else if (*p == '\t') fprintf(f, "\\t");
\r
2423 else if (*p == '\b') fprintf(f, "\\b");
\r
2424 else if (*p == '\f') fprintf(f, "\\f");
\r
2425 else if (*p < ' ') fprintf(f, "\\%03o", *p);
\r
2426 else if (*p == '\"') fprintf(f, "\\\"");
\r
2427 else if (*p == '\\') fprintf(f, "\\\\");
\r
2431 fprintf(f, "\"\n");
\r
2437 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);
\r
2440 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardX); // [HGM] placement: stor relative value
\r
2443 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardY);
\r
2446 fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);
\r
2449 fprintf(f, "/%s=%s\n", ad->argName,
\r
2450 (*(Boolean *)ad->argLoc) ? "true" : "false");
\r
2453 if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2456 if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2460 COLORREF color = *(COLORREF *)ad->argLoc;
\r
2461 fprintf(f, "/%s=#%02lx%02lx%02lx\n", ad->argName,
\r
2462 color&0xff, (color>>8)&0xff, (color>>16)&0xff);
\r
2467 MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];
\r
2468 fprintf(f, "/%s=\"%s%s%s%s%s#%02lx%02lx%02lx\"\n", ad->argName,
\r
2469 (ta->effects & CFE_BOLD) ? "b" : "",
\r
2470 (ta->effects & CFE_ITALIC) ? "i" : "",
\r
2471 (ta->effects & CFE_UNDERLINE) ? "u" : "",
\r
2472 (ta->effects & CFE_STRIKEOUT) ? "s" : "",
\r
2473 (ta->effects) ? " " : "",
\r
2474 ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);
\r
2478 if (strchr(*(char **)ad->argLoc, '\"')) {
\r
2479 fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);
\r
2481 fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);
\r
2484 case ArgBoardSize:
\r
2485 fprintf(f, "/%s=%s\n", ad->argName,
\r
2486 sizeInfo[*(BoardSize *)ad->argLoc].name);
\r
2491 for (bs=0; bs<NUM_SIZES; bs++) {
\r
2492 MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;
\r
2493 fprintf(f, "/size=%s ", sizeInfo[bs].name);
\r
2494 fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n",
\r
2495 ad->argName, mfp->faceName, mfp->pointSize,
\r
2496 mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",
\r
2497 mfp->bold ? "b" : "",
\r
2498 mfp->italic ? "i" : "",
\r
2499 mfp->underline ? "u" : "",
\r
2500 mfp->strikeout ? "s" : "");
\r
2504 case ArgCommSettings:
\r
2505 PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);
\r
2507 case ArgSettingsFilename: ;
\r
2515 /*---------------------------------------------------------------------------*\
\r
2517 * GDI board drawing routines
\r
2519 \*---------------------------------------------------------------------------*/
\r
2521 /* [AS] Draw square using background texture */
\r
2522 static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )
\r
2527 return; /* Should never happen! */
\r
2530 SetGraphicsMode( dst, GM_ADVANCED );
\r
2537 /* X reflection */
\r
2542 x.eDx = (FLOAT) dw + dx - 1;
\r
2545 SetWorldTransform( dst, &x );
\r
2548 /* Y reflection */
\r
2554 x.eDy = (FLOAT) dh + dy - 1;
\r
2556 SetWorldTransform( dst, &x );
\r
2564 x.eDx = (FLOAT) dx;
\r
2565 x.eDy = (FLOAT) dy;
\r
2568 SetWorldTransform( dst, &x );
\r
2572 BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );
\r
2580 SetWorldTransform( dst, &x );
\r
2582 ModifyWorldTransform( dst, 0, MWT_IDENTITY );
\r
2585 /* [AS] [HGM] Make room for more piece types, so all pieces can be different */
\r
2587 PM_WP = (int) WhitePawn,
\r
2588 PM_WN = (int) WhiteKnight,
\r
2589 PM_WB = (int) WhiteBishop,
\r
2590 PM_WR = (int) WhiteRook,
\r
2591 PM_WQ = (int) WhiteQueen,
\r
2592 PM_WF = (int) WhiteFerz,
\r
2593 PM_WW = (int) WhiteWazir,
\r
2594 PM_WE = (int) WhiteAlfil,
\r
2595 PM_WM = (int) WhiteMan,
\r
2596 PM_WO = (int) WhiteCannon,
\r
2597 PM_WU = (int) WhiteUnicorn,
\r
2598 PM_WH = (int) WhiteNightrider,
\r
2599 PM_WA = (int) WhiteAngel,
\r
2600 PM_WC = (int) WhiteMarshall,
\r
2601 PM_WAB = (int) WhiteCardinal,
\r
2602 PM_WD = (int) WhiteDragon,
\r
2603 PM_WL = (int) WhiteLance,
\r
2604 PM_WS = (int) WhiteCobra,
\r
2605 PM_WV = (int) WhiteFalcon,
\r
2606 PM_WSG = (int) WhiteSilver,
\r
2607 PM_WG = (int) WhiteGrasshopper,
\r
2608 PM_WK = (int) WhiteKing,
\r
2609 PM_BP = (int) BlackPawn,
\r
2610 PM_BN = (int) BlackKnight,
\r
2611 PM_BB = (int) BlackBishop,
\r
2612 PM_BR = (int) BlackRook,
\r
2613 PM_BQ = (int) BlackQueen,
\r
2614 PM_BF = (int) BlackFerz,
\r
2615 PM_BW = (int) BlackWazir,
\r
2616 PM_BE = (int) BlackAlfil,
\r
2617 PM_BM = (int) BlackMan,
\r
2618 PM_BO = (int) BlackCannon,
\r
2619 PM_BU = (int) BlackUnicorn,
\r
2620 PM_BH = (int) BlackNightrider,
\r
2621 PM_BA = (int) BlackAngel,
\r
2622 PM_BC = (int) BlackMarshall,
\r
2623 PM_BG = (int) BlackGrasshopper,
\r
2624 PM_BAB = (int) BlackCardinal,
\r
2625 PM_BD = (int) BlackDragon,
\r
2626 PM_BL = (int) BlackLance,
\r
2627 PM_BS = (int) BlackCobra,
\r
2628 PM_BV = (int) BlackFalcon,
\r
2629 PM_BSG = (int) BlackSilver,
\r
2630 PM_BK = (int) BlackKing
\r
2633 static HFONT hPieceFont = NULL;
\r
2634 static HBITMAP hPieceMask[(int) EmptySquare];
\r
2635 static HBITMAP hPieceFace[(int) EmptySquare];
\r
2636 static int fontBitmapSquareSize = 0;
\r
2637 static char pieceToFontChar[(int) EmptySquare] =
\r
2638 { 'p', 'n', 'b', 'r', 'q',
\r
2639 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',
\r
2640 'k', 'o', 'm', 'v', 't', 'w',
\r
2641 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',
\r
2644 extern BOOL SetCharTable( char *table, const char * map );
\r
2645 /* [HGM] moved to backend.c */
\r
2647 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )
\r
2650 BYTE r1 = GetRValue( color );
\r
2651 BYTE g1 = GetGValue( color );
\r
2652 BYTE b1 = GetBValue( color );
\r
2658 /* Create a uniform background first */
\r
2659 hbrush = CreateSolidBrush( color );
\r
2660 SetRect( &rc, 0, 0, squareSize, squareSize );
\r
2661 FillRect( hdc, &rc, hbrush );
\r
2662 DeleteObject( hbrush );
\r
2665 /* Vertical gradient, good for pawn, knight and rook, less for queen and king */
\r
2666 int steps = squareSize / 2;
\r
2669 for( i=0; i<steps; i++ ) {
\r
2670 BYTE r = r1 - (r1-r2) * i / steps;
\r
2671 BYTE g = g1 - (g1-g2) * i / steps;
\r
2672 BYTE b = b1 - (b1-b2) * i / steps;
\r
2674 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2675 SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );
\r
2676 FillRect( hdc, &rc, hbrush );
\r
2677 DeleteObject(hbrush);
\r
2680 else if( mode == 2 ) {
\r
2681 /* Diagonal gradient, good more or less for every piece */
\r
2682 POINT triangle[3];
\r
2683 HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );
\r
2684 HBRUSH hbrush_old;
\r
2685 int steps = squareSize;
\r
2688 triangle[0].x = squareSize - steps;
\r
2689 triangle[0].y = squareSize;
\r
2690 triangle[1].x = squareSize;
\r
2691 triangle[1].y = squareSize;
\r
2692 triangle[2].x = squareSize;
\r
2693 triangle[2].y = squareSize - steps;
\r
2695 for( i=0; i<steps; i++ ) {
\r
2696 BYTE r = r1 - (r1-r2) * i / steps;
\r
2697 BYTE g = g1 - (g1-g2) * i / steps;
\r
2698 BYTE b = b1 - (b1-b2) * i / steps;
\r
2700 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2701 hbrush_old = SelectObject( hdc, hbrush );
\r
2702 Polygon( hdc, triangle, 3 );
\r
2703 SelectObject( hdc, hbrush_old );
\r
2704 DeleteObject(hbrush);
\r
2709 SelectObject( hdc, hpen );
\r
2714 [AS] The method I use to create the bitmaps it a bit tricky, but it
\r
2715 seems to work ok. The main problem here is to find the "inside" of a chess
\r
2716 piece: follow the steps as explained below.
\r
2718 static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
\r
2722 COLORREF chroma = RGB(0xFF,0x00,0xFF);
\r
2726 int backColor = whitePieceColor;
\r
2727 int foreColor = blackPieceColor;
\r
2729 if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {
\r
2730 backColor = appData.fontBackColorWhite;
\r
2731 foreColor = appData.fontForeColorWhite;
\r
2733 else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {
\r
2734 backColor = appData.fontBackColorBlack;
\r
2735 foreColor = appData.fontForeColorBlack;
\r
2739 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2741 hbm_old = SelectObject( hdc, hbm );
\r
2745 rc.right = squareSize;
\r
2746 rc.bottom = squareSize;
\r
2748 /* Step 1: background is now black */
\r
2749 FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );
\r
2751 GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );
\r
2753 pt.x = (squareSize - sz.cx) / 2;
\r
2754 pt.y = (squareSize - sz.cy) / 2;
\r
2756 SetBkMode( hdc, TRANSPARENT );
\r
2757 SetTextColor( hdc, chroma );
\r
2758 /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */
\r
2759 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2761 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
\r
2762 /* Step 3: the area outside the piece is filled with white */
\r
2763 // FloodFill( hdc, 0, 0, chroma );
\r
2764 ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );
\r
2765 ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big
\r
2766 ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );
\r
2767 ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );
\r
2768 SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
\r
2770 Step 4: this is the tricky part, the area inside the piece is filled with black,
\r
2771 but if the start point is not inside the piece we're lost!
\r
2772 There should be a better way to do this... if we could create a region or path
\r
2773 from the fill operation we would be fine for example.
\r
2775 // FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );
\r
2776 ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );
\r
2778 { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */
\r
2779 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2780 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2782 SelectObject( dc2, bm2 );
\r
2783 BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy
\r
2784 BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2785 BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2786 BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2787 BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2790 DeleteObject( bm2 );
\r
2793 SetTextColor( hdc, 0 );
\r
2795 Step 5: some fonts have "disconnected" areas that are skipped by the fill:
\r
2796 draw the piece again in black for safety.
\r
2798 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2800 SelectObject( hdc, hbm_old );
\r
2802 if( hPieceMask[index] != NULL ) {
\r
2803 DeleteObject( hPieceMask[index] );
\r
2806 hPieceMask[index] = hbm;
\r
2809 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2811 SelectObject( hdc, hbm );
\r
2814 HDC dc1 = CreateCompatibleDC( hdc_window );
\r
2815 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2816 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2818 SelectObject( dc1, hPieceMask[index] );
\r
2819 SelectObject( dc2, bm2 );
\r
2820 FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );
\r
2821 BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );
\r
2824 Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves
\r
2825 the piece background and deletes (makes transparent) the rest.
\r
2826 Thanks to that mask, we are free to paint the background with the greates
\r
2827 freedom, as we'll be able to mask off the unwanted parts when finished.
\r
2828 We use this, to make gradients and give the pieces a "roundish" look.
\r
2830 SetPieceBackground( hdc, backColor, 2 );
\r
2831 BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );
\r
2835 DeleteObject( bm2 );
\r
2838 SetTextColor( hdc, foreColor );
\r
2839 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2841 SelectObject( hdc, hbm_old );
\r
2843 if( hPieceFace[index] != NULL ) {
\r
2844 DeleteObject( hPieceFace[index] );
\r
2847 hPieceFace[index] = hbm;
\r
2850 static int TranslatePieceToFontPiece( int piece )
\r
2880 case BlackMarshall:
\r
2884 case BlackNightrider:
\r
2890 case BlackUnicorn:
\r
2894 case BlackGrasshopper:
\r
2906 case BlackCardinal:
\r
2913 case WhiteMarshall:
\r
2917 case WhiteNightrider:
\r
2923 case WhiteUnicorn:
\r
2927 case WhiteGrasshopper:
\r
2939 case WhiteCardinal:
\r
2948 void CreatePiecesFromFont()
\r
2951 HDC hdc_window = NULL;
\r
2957 if( fontBitmapSquareSize < 0 ) {
\r
2958 /* Something went seriously wrong in the past: do not try to recreate fonts! */
\r
2962 if( appData.renderPiecesWithFont == NULL || appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {
\r
2963 fontBitmapSquareSize = -1;
\r
2967 if( fontBitmapSquareSize != squareSize ) {
\r
2968 hdc_window = GetDC( hwndMain );
\r
2969 hdc = CreateCompatibleDC( hdc_window );
\r
2971 if( hPieceFont != NULL ) {
\r
2972 DeleteObject( hPieceFont );
\r
2975 for( i=0; i<=(int)BlackKing; i++ ) {
\r
2976 hPieceMask[i] = NULL;
\r
2977 hPieceFace[i] = NULL;
\r
2983 if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {
\r
2984 fontHeight = appData.fontPieceSize;
\r
2987 fontHeight = (fontHeight * squareSize) / 100;
\r
2989 lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
\r
2991 lf.lfEscapement = 0;
\r
2992 lf.lfOrientation = 0;
\r
2993 lf.lfWeight = FW_NORMAL;
\r
2995 lf.lfUnderline = 0;
\r
2996 lf.lfStrikeOut = 0;
\r
2997 lf.lfCharSet = DEFAULT_CHARSET;
\r
2998 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
2999 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
3000 lf.lfQuality = PROOF_QUALITY;
\r
3001 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
\r
3002 strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );
\r
3003 lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';
\r
3005 hPieceFont = CreateFontIndirect( &lf );
\r
3007 if( hPieceFont == NULL ) {
\r
3008 fontBitmapSquareSize = -2;
\r
3011 /* Setup font-to-piece character table */
\r
3012 if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {
\r
3013 /* No (or wrong) global settings, try to detect the font */
\r
3014 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {
\r
3016 SetCharTable(pieceToFontChar, "phbrqkojntwl");
\r
3018 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {
\r
3019 /* DiagramTT* family */
\r
3020 SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");
\r
3022 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {
\r
3023 /* Fairy symbols */
\r
3024 SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
\r
3026 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {
\r
3027 /* Good Companion (Some characters get warped as literal :-( */
\r
3028 char s[] = "1cmWG0ñueOS¯®oYI23wgQU";
\r
3029 s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;
\r
3030 SetCharTable(pieceToFontChar, s);
\r
3033 /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */
\r
3034 SetCharTable(pieceToFontChar, "pnbrqkomvtwl");
\r
3038 /* Create bitmaps */
\r
3039 hfont_old = SelectObject( hdc, hPieceFont );
\r
3040 for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */
\r
3041 if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */
\r
3042 CreatePieceMaskFromFont( hdc_window, hdc, i );
\r
3044 SelectObject( hdc, hfont_old );
\r
3046 fontBitmapSquareSize = squareSize;
\r
3050 if( hdc != NULL ) {
\r
3054 if( hdc_window != NULL ) {
\r
3055 ReleaseDC( hwndMain, hdc_window );
\r
3060 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)
\r
3064 sprintf(name, "%s%d%s", piece, squareSize, suffix);
\r
3065 if (gameInfo.event &&
\r
3066 strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&
\r
3067 strcmp(name, "k80s") == 0) {
\r
3068 strcpy(name, "tim");
\r
3070 return LoadBitmap(hinst, name);
\r
3074 /* Insert a color into the program's logical palette
\r
3075 structure. This code assumes the given color is
\r
3076 the result of the RGB or PALETTERGB macro, and it
\r
3077 knows how those macros work (which is documented).
\r
3080 InsertInPalette(COLORREF color)
\r
3082 LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);
\r
3084 if (pLogPal->palNumEntries++ >= PALETTESIZE) {
\r
3085 DisplayFatalError("Too many colors", 0, 1);
\r
3086 pLogPal->palNumEntries--;
\r
3090 pe->peFlags = (char) 0;
\r
3091 pe->peRed = (char) (0xFF & color);
\r
3092 pe->peGreen = (char) (0xFF & (color >> 8));
\r
3093 pe->peBlue = (char) (0xFF & (color >> 16));
\r
3099 InitDrawingColors()
\r
3101 if (pLogPal == NULL) {
\r
3102 /* Allocate enough memory for a logical palette with
\r
3103 * PALETTESIZE entries and set the size and version fields
\r
3104 * of the logical palette structure.
\r
3106 pLogPal = (NPLOGPALETTE)
\r
3107 LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +
\r
3108 (sizeof(PALETTEENTRY) * (PALETTESIZE))));
\r
3109 pLogPal->palVersion = 0x300;
\r
3111 pLogPal->palNumEntries = 0;
\r
3113 InsertInPalette(lightSquareColor);
\r
3114 InsertInPalette(darkSquareColor);
\r
3115 InsertInPalette(whitePieceColor);
\r
3116 InsertInPalette(blackPieceColor);
\r
3117 InsertInPalette(highlightSquareColor);
\r
3118 InsertInPalette(premoveHighlightColor);
\r
3120 /* create a logical color palette according the information
\r
3121 * in the LOGPALETTE structure.
\r
3123 hPal = CreatePalette((LPLOGPALETTE) pLogPal);
\r
3125 lightSquareBrush = CreateSolidBrush(lightSquareColor);
\r
3126 blackSquareBrush = CreateSolidBrush(blackPieceColor);
\r
3127 darkSquareBrush = CreateSolidBrush(darkSquareColor);
\r
3128 whitePieceBrush = CreateSolidBrush(whitePieceColor);
\r
3129 blackPieceBrush = CreateSolidBrush(blackPieceColor);
\r
3130 iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
\r
3131 explodeBrush = CreateSolidBrush(highlightSquareColor); // [HGM] atomic
\r
3132 /* [AS] Force rendering of the font-based pieces */
\r
3133 if( fontBitmapSquareSize > 0 ) {
\r
3134 fontBitmapSquareSize = 0;
\r
3140 BoardWidth(int boardSize, int n)
\r
3141 { /* [HGM] argument n added to allow different width and height */
\r
3142 int lineGap = sizeInfo[boardSize].lineGap;
\r
3144 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3145 lineGap = appData.overrideLineGap;
\r
3148 return (n + 1) * lineGap +
\r
3149 n * sizeInfo[boardSize].squareSize;
\r
3152 /* Respond to board resize by dragging edge */
\r
3154 ResizeBoard(int newSizeX, int newSizeY, int flags)
\r
3156 BoardSize newSize = NUM_SIZES - 1;
\r
3157 static int recurse = 0;
\r
3158 if (IsIconic(hwndMain)) return;
\r
3159 if (recurse > 0) return;
\r
3161 while (newSize > 0) {
\r
3162 InitDrawingSizes(newSize+1000, 0); // [HGM] kludge to update sizeInfo without visible effects
\r
3163 if(newSizeX >= sizeInfo[newSize].cliWidth &&
\r
3164 newSizeY >= sizeInfo[newSize].cliHeight) break;
\r
3167 boardSize = newSize;
\r
3168 InitDrawingSizes(boardSize, flags);
\r
3175 InitDrawingSizes(BoardSize boardSize, int flags)
\r
3177 int i, boardWidth, boardHeight; /* [HGM] height treated separately */
\r
3178 ChessSquare piece;
\r
3179 static int oldBoardSize = -1, oldTinyLayout = 0;
\r
3181 SIZE clockSize, messageSize;
\r
3183 char buf[MSG_SIZ];
\r
3185 HMENU hmenu = GetMenu(hwndMain);
\r
3186 RECT crect, wrect, oldRect;
\r
3188 LOGBRUSH logbrush;
\r
3190 int suppressVisibleEffects = 0; // [HGM] kludge to request updating sizeInfo only
\r
3191 if((int)boardSize >= 1000 ) { boardSize -= 1000; suppressVisibleEffects = 1; }
\r
3193 /* [HGM] call with -2 uses old size (for if nr of files, ranks changes) */
\r
3194 if(boardSize == (BoardSize)(-2) ) boardSize = oldBoardSize;
\r
3196 oldRect.left = boardX; //[HGM] placement: remember previous window params
\r
3197 oldRect.top = boardY;
\r
3198 oldRect.right = boardX + winWidth;
\r
3199 oldRect.bottom = boardY + winHeight;
\r
3201 tinyLayout = sizeInfo[boardSize].tinyLayout;
\r
3202 smallLayout = sizeInfo[boardSize].smallLayout;
\r
3203 squareSize = sizeInfo[boardSize].squareSize;
\r
3204 lineGap = sizeInfo[boardSize].lineGap;
\r
3205 minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted */
\r
3207 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3208 lineGap = appData.overrideLineGap;
\r
3211 if (tinyLayout != oldTinyLayout) {
\r
3212 long style = GetWindowLong(hwndMain, GWL_STYLE);
\r
3214 style &= ~WS_SYSMENU;
\r
3215 InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize,
\r
3216 "&Minimize\tCtrl+F4");
\r
3218 style |= WS_SYSMENU;
\r
3219 RemoveMenu(hmenu, IDM_Minimize, MF_BYCOMMAND);
\r
3221 SetWindowLong(hwndMain, GWL_STYLE, style);
\r
3223 for (i=0; menuBarText[tinyLayout][i]; i++) {
\r
3224 ModifyMenu(hmenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP,
\r
3225 (UINT)GetSubMenu(hmenu, i), menuBarText[tinyLayout][i]);
\r
3227 DrawMenuBar(hwndMain);
\r
3230 boardWidth = BoardWidth(boardSize, BOARD_WIDTH);
\r
3231 boardHeight = BoardWidth(boardSize, BOARD_HEIGHT);
\r
3233 /* Get text area sizes */
\r
3234 hdc = GetDC(hwndMain);
\r
3235 if (appData.clockMode) {
\r
3236 sprintf(buf, "White: %s", TimeString(23*60*60*1000L));
\r
3238 sprintf(buf, "White");
\r
3240 oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);
\r
3241 GetTextExtentPoint(hdc, buf, strlen(buf), &clockSize);
\r
3242 SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);
\r
3243 str = "We only care about the height here";
\r
3244 GetTextExtentPoint(hdc, str, strlen(str), &messageSize);
\r
3245 SelectObject(hdc, oldFont);
\r
3246 ReleaseDC(hwndMain, hdc);
\r
3248 /* Compute where everything goes */
\r
3249 if((first.programLogo || second.programLogo) && !tinyLayout) {
\r
3250 /* [HGM] logo: if either logo is on, reserve space for it */
\r
3251 logoHeight = 2*clockSize.cy;
\r
3252 leftLogoRect.left = OUTER_MARGIN;
\r
3253 leftLogoRect.right = leftLogoRect.left + 4*clockSize.cy;
\r
3254 leftLogoRect.top = OUTER_MARGIN;
\r
3255 leftLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3257 rightLogoRect.right = OUTER_MARGIN + boardWidth;
\r
3258 rightLogoRect.left = rightLogoRect.right - 4*clockSize.cy;
\r
3259 rightLogoRect.top = OUTER_MARGIN;
\r
3260 rightLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3263 whiteRect.left = leftLogoRect.right;
\r
3264 whiteRect.right = OUTER_MARGIN + boardWidth/2 - INNER_MARGIN/2;
\r
3265 whiteRect.top = OUTER_MARGIN;
\r
3266 whiteRect.bottom = whiteRect.top + logoHeight;
\r
3268 blackRect.right = rightLogoRect.left;
\r
3269 blackRect.left = whiteRect.right + INNER_MARGIN;
\r
3270 blackRect.top = whiteRect.top;
\r
3271 blackRect.bottom = whiteRect.bottom;
\r
3273 whiteRect.left = OUTER_MARGIN;
\r
3274 whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2;
\r
3275 whiteRect.top = OUTER_MARGIN;
\r
3276 whiteRect.bottom = whiteRect.top + clockSize.cy;
\r
3278 blackRect.left = whiteRect.right + INNER_MARGIN;
\r
3279 blackRect.right = blackRect.left + boardWidth/2 - 1;
\r
3280 blackRect.top = whiteRect.top;
\r
3281 blackRect.bottom = whiteRect.bottom;
\r
3284 messageRect.left = OUTER_MARGIN + MESSAGE_LINE_LEFTMARGIN;
\r
3285 if (appData.showButtonBar) {
\r
3286 messageRect.right = OUTER_MARGIN + boardWidth // [HGM] logo: expressed independent of clock placement
\r
3287 - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN;
\r
3289 messageRect.right = OUTER_MARGIN + boardWidth;
\r
3291 messageRect.top = whiteRect.bottom + INNER_MARGIN;
\r
3292 messageRect.bottom = messageRect.top + messageSize.cy;
\r
3294 boardRect.left = OUTER_MARGIN;
\r
3295 boardRect.right = boardRect.left + boardWidth;
\r
3296 boardRect.top = messageRect.bottom + INNER_MARGIN;
\r
3297 boardRect.bottom = boardRect.top + boardHeight;
\r
3299 sizeInfo[boardSize].cliWidth = boardRect.right + OUTER_MARGIN;
\r
3300 sizeInfo[boardSize].cliHeight = boardRect.bottom + OUTER_MARGIN;
\r
3301 oldBoardSize = boardSize;
\r
3302 oldTinyLayout = tinyLayout;
\r
3303 winW = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN;
\r
3304 winH = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) +
\r
3305 GetSystemMetrics(SM_CYCAPTION) + boardRect.bottom + OUTER_MARGIN;
\r
3306 if(suppressVisibleEffects) return; // [HGM] when called for filling sizeInfo only
\r
3307 winWidth = winW; // [HGM] placement: set through temporary which can used by initial sizing choice
\r
3308 winHeight = winH; // without disturbing window attachments
\r
3309 GetWindowRect(hwndMain, &wrect);
\r
3310 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3311 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3313 // [HGM] placement: let attached windows follow size change.
\r
3314 ReattachAfterSize( &oldRect, winWidth, winHeight, moveHistoryDialog, &wpMoveHistory );
\r
3315 ReattachAfterSize( &oldRect, winWidth, winHeight, evalGraphDialog, &wpEvalGraph );
\r
3316 ReattachAfterSize( &oldRect, winWidth, winHeight, engineOutputDialog, &wpEngineOutput );
\r
3317 ReattachAfterSize( &oldRect, winWidth, winHeight, gameListDialog, &wpGameList );
\r
3318 ReattachAfterSize( &oldRect, winWidth, winHeight, hwndConsole, &wpConsole );
\r
3320 /* compensate if menu bar wrapped */
\r
3321 GetClientRect(hwndMain, &crect);
\r
3322 offby = boardRect.bottom + OUTER_MARGIN - crect.bottom;
\r
3323 winHeight += offby;
\r
3325 case WMSZ_TOPLEFT:
\r
3326 SetWindowPos(hwndMain, NULL,
\r
3327 wrect.right - winWidth, wrect.bottom - winHeight,
\r
3328 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3331 case WMSZ_TOPRIGHT:
\r
3333 SetWindowPos(hwndMain, NULL,
\r
3334 wrect.left, wrect.bottom - winHeight,
\r
3335 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3338 case WMSZ_BOTTOMLEFT:
\r
3340 SetWindowPos(hwndMain, NULL,
\r
3341 wrect.right - winWidth, wrect.top,
\r
3342 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3345 case WMSZ_BOTTOMRIGHT:
\r
3349 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3350 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3355 for (i = 0; i < N_BUTTONS; i++) {
\r
3356 if (buttonDesc[i].hwnd != NULL) {
\r
3357 DestroyWindow(buttonDesc[i].hwnd);
\r
3358 buttonDesc[i].hwnd = NULL;
\r
3360 if (appData.showButtonBar) {
\r
3361 buttonDesc[i].hwnd =
\r
3362 CreateWindow("BUTTON", buttonDesc[i].label,
\r
3363 WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
\r
3364 boardRect.right - BUTTON_WIDTH*(N_BUTTONS-i),
\r
3365 messageRect.top, BUTTON_WIDTH, messageSize.cy, hwndMain,
\r
3366 (HMENU) buttonDesc[i].id,
\r
3367 (HINSTANCE) GetWindowLong(hwndMain, GWL_HINSTANCE), NULL);
\r
3369 SendMessage(buttonDesc[i].hwnd, WM_SETFONT,
\r
3370 (WPARAM)font[boardSize][MESSAGE_FONT]->hf,
\r
3371 MAKELPARAM(FALSE, 0));
\r
3373 if (buttonDesc[i].id == IDM_Pause)
\r
3374 hwndPause = buttonDesc[i].hwnd;
\r
3375 buttonDesc[i].wndproc = (WNDPROC)
\r
3376 SetWindowLong(buttonDesc[i].hwnd, GWL_WNDPROC, (LONG) ButtonProc);
\r
3379 if (gridPen != NULL) DeleteObject(gridPen);
\r
3380 if (highlightPen != NULL) DeleteObject(highlightPen);
\r
3381 if (premovePen != NULL) DeleteObject(premovePen);
\r
3382 if (lineGap != 0) {
\r
3383 logbrush.lbStyle = BS_SOLID;
\r
3384 logbrush.lbColor = RGB(0, 0, 0); /* grid pen color = black */
\r
3386 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3387 lineGap, &logbrush, 0, NULL);
\r
3388 logbrush.lbColor = highlightSquareColor;
\r
3390 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3391 lineGap, &logbrush, 0, NULL);
\r
3393 logbrush.lbColor = premoveHighlightColor;
\r
3395 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3396 lineGap, &logbrush, 0, NULL);
\r
3398 /* [HGM] Loop had to be split in part for vert. and hor. lines */
\r
3399 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
\r
3400 gridEndpoints[i*2].x = boardRect.left + lineGap / 2;
\r
3401 gridEndpoints[i*2].y = gridEndpoints[i*2 + 1].y =
\r
3402 boardRect.top + lineGap / 2 + (i * (squareSize + lineGap));
\r
3403 gridEndpoints[i*2 + 1].x = boardRect.left + lineGap / 2 +
\r
3404 BOARD_WIDTH * (squareSize + lineGap);
\r
3405 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3407 for (i = 0; i < BOARD_WIDTH + 1; i++) {
\r
3408 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].y = boardRect.top + lineGap / 2;
\r
3409 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].x =
\r
3410 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].x = boardRect.left +
\r
3411 lineGap / 2 + (i * (squareSize + lineGap));
\r
3412 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].y =
\r
3413 boardRect.top + BOARD_HEIGHT * (squareSize + lineGap);
\r
3414 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3418 /* [HGM] Licensing requirement */
\r
3420 if(gameInfo.variant == VariantGothic) GothicPopUp( GOTHIC, VariantGothic); else
\r
3423 if(gameInfo.variant == VariantFalcon) GothicPopUp( FALCON, VariantFalcon); else
\r
3425 GothicPopUp( "", VariantNormal);
\r
3428 /* if (boardSize == oldBoardSize) return; [HGM] variant might have changed */
\r
3430 /* Load piece bitmaps for this board size */
\r
3431 for (i=0; i<=2; i++) {
\r
3432 for (piece = WhitePawn;
\r
3433 (int) piece < (int) BlackPawn;
\r
3434 piece = (ChessSquare) ((int) piece + 1)) {
\r
3435 if (pieceBitmap[i][piece] != NULL)
\r
3436 DeleteObject(pieceBitmap[i][piece]);
\r
3440 fontBitmapSquareSize = 0; /* [HGM] render: make sure pieces will be recreated, as we might need others now */
\r
3441 // Orthodox Chess pieces
\r
3442 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s");
\r
3443 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s");
\r
3444 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "s");
\r
3445 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "s");
\r
3446 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "s");
\r
3447 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "o");
\r
3448 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "o");
\r
3449 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "o");
\r
3450 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "o");
\r
3451 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "o");
\r
3452 pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "w");
\r
3453 pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "w");
\r
3454 pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "w");
\r
3455 pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w");
\r
3456 pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w");
\r
3457 if( !strcmp(appData.variant, "shogi") && (squareSize==72 || squareSize==49)) {
\r
3458 // in Shogi, Hijack the unused Queen for Lance
\r
3459 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3460 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3461 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3463 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s");
\r
3464 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o");
\r
3465 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w");
\r
3468 if(squareSize <= 72 && squareSize >= 33) {
\r
3469 /* A & C are available in most sizes now */
\r
3470 if(squareSize != 49 && squareSize != 72 && squareSize != 33) { // Vortex-like
\r
3471 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3472 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3473 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3474 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3475 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3476 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3477 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3478 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3479 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3480 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3481 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3482 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3483 } else { // Smirf-like
\r
3484 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "s");
\r
3485 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "o");
\r
3486 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "w");
\r
3488 if(gameInfo.variant == VariantGothic) { // Vortex-like
\r
3489 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3490 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3491 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3492 } else { // WinBoard standard
\r
3493 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s");
\r
3494 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o");
\r
3495 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "w");
\r
3500 if(squareSize==72 || squareSize==49 || squareSize==33) { /* experiment with some home-made bitmaps */
\r
3501 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "s");
\r
3502 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "o");
\r
3503 pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "w");
\r
3504 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "s");
\r
3505 pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "o");
\r
3506 pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3507 pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "s");
\r
3508 pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "o");
\r
3509 pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "w");
\r
3510 pieceBitmap[0][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "s");
\r
3511 pieceBitmap[1][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "o");
\r
3512 pieceBitmap[2][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "w");
\r
3513 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3514 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3515 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3516 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "s");
\r
3517 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "o");
\r
3518 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "w");
\r
3519 pieceBitmap[0][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "s");
\r
3520 pieceBitmap[1][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "o");
\r
3521 pieceBitmap[2][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "w");
\r
3522 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "s");
\r
3523 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "o");
\r
3524 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "w");
\r
3525 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3526 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3527 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3528 pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s");
\r
3529 pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o");
\r
3530 pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w");
\r
3532 if(gameInfo.variant == VariantShogi) { /* promoted Gold represemtations */
\r
3533 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s");
\r
3534 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "o");
\r
3535 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3536 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "s");
\r
3537 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "o");
\r
3538 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3539 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "s");
\r
3540 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "o");
\r
3541 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3542 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "s");
\r
3543 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "o");
\r
3544 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3546 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "s");
\r
3547 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "o");
\r
3548 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "w");
\r
3549 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "s");
\r
3550 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "o");
\r
3551 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "w");
\r
3552 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3553 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3554 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3555 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "s");
\r
3556 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "o");
\r
3557 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "w");
\r
3560 } else { /* other size, no special bitmaps available. Use smaller symbols */
\r
3561 if((int)boardSize < 2) minorSize = sizeInfo[0].squareSize;
\r
3562 else minorSize = sizeInfo[(int)boardSize - 2].squareSize;
\r
3563 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "s");
\r
3564 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "o");
\r
3565 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "w");
\r
3566 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "s");
\r
3567 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "o");
\r
3568 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "w");
\r
3569 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "s");
\r
3570 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "o");
\r
3571 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "w");
\r
3572 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "s");
\r
3573 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "o");
\r
3574 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "w");
\r
3578 if(gameInfo.variant == VariantShogi && squareSize == 58)
\r
3579 /* special Shogi support in this size */
\r
3580 { for (i=0; i<=2; i++) { /* replace all bitmaps */
\r
3581 for (piece = WhitePawn;
\r
3582 (int) piece < (int) BlackPawn;
\r
3583 piece = (ChessSquare) ((int) piece + 1)) {
\r
3584 if (pieceBitmap[i][piece] != NULL)
\r
3585 DeleteObject(pieceBitmap[i][piece]);
\r
3588 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3589 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3590 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3591 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3592 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3593 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3594 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r
3595 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");
\r
3596 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");
\r
3597 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");
\r
3598 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");
\r
3599 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");
\r
3600 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");
\r
3601 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");
\r
3602 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3603 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3604 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3605 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3606 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3607 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3608 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r
3609 pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");
\r
3610 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");
\r
3611 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");
\r
3612 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");
\r
3613 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");
\r
3614 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");
\r
3615 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");
\r
3616 pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "w");
\r
3617 pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "w");
\r
3618 pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3619 pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3620 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "w");
\r
3621 pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "w");
\r
3622 pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3623 pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3624 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "sp", squareSize, "w");
\r
3625 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "sn", squareSize, "w");
\r
3626 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3627 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "sr", squareSize, "w");
\r
3628 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "sl", squareSize, "w");
\r
3629 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "sw", squareSize, "w");
\r
3635 PieceBitmap(ChessSquare p, int kind)
\r
3637 if ((int) p >= (int) BlackPawn)
\r
3638 p = (ChessSquare) ((int) p - (int) BlackPawn + (int) WhitePawn);
\r
3640 return pieceBitmap[kind][(int) p];
\r
3643 /***************************************************************/
\r
3645 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
\r