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