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
104 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);
\r
105 VOID NewVariantPopup(HWND hwnd);
\r
106 int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,
\r
107 /*char*/int promoChar));
\r
108 void AnimateAtomicCapture(int fromX, int fromY, int toX, int toY, int nFrames);
\r
109 void DisplayMove P((int moveNumber));
\r
110 Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen));
\r
112 ChessSquare piece;
\r
113 POINT pos; /* window coordinates of current pos */
\r
114 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
115 POINT from; /* board coordinates of the piece's orig pos */
\r
116 POINT to; /* board coordinates of the piece's new pos */
\r
119 static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };
\r
122 POINT start; /* window coordinates of start pos */
\r
123 POINT pos; /* window coordinates of current pos */
\r
124 POINT lastpos; /* window coordinates of last pos - used for clipping */
\r
125 POINT from; /* board coordinates of the piece's orig pos */
\r
128 static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} };
\r
131 POINT sq[2]; /* board coordinates of from, to squares */
\r
134 static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} };
\r
135 static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };
\r
137 typedef struct { // [HGM] atomic
\r
138 int fromX, fromY, toX, toY, radius;
\r
141 static ExplodeInfo explodeInfo;
\r
143 /* Window class names */
\r
144 char szAppName[] = "WinBoard";
\r
145 char szConsoleName[] = "WBConsole";
\r
147 /* Title bar text */
\r
148 char szTitle[] = "WinBoard";
\r
149 char szConsoleTitle[] = "I C S Interaction";
\r
152 char *settingsFileName;
\r
153 BOOLEAN saveSettingsOnExit;
\r
154 char installDir[MSG_SIZ];
\r
156 BoardSize boardSize;
\r
157 BOOLEAN chessProgram;
\r
158 static int boardX, boardY;
\r
159 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
\r
160 static int squareSize, lineGap, minorSize;
\r
161 static int winWidth, winHeight, winW, winH;
\r
162 static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo
\r
163 static int logoHeight = 0;
\r
164 static char messageText[MESSAGE_TEXT_MAX];
\r
165 static int clockTimerEvent = 0;
\r
166 static int loadGameTimerEvent = 0;
\r
167 static int analysisTimerEvent = 0;
\r
168 static DelayedEventCallback delayedTimerCallback;
\r
169 static int delayedTimerEvent = 0;
\r
170 static int buttonCount = 2;
\r
171 char *icsTextMenuString;
\r
173 char *firstChessProgramNames;
\r
174 char *secondChessProgramNames;
\r
176 #define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */
\r
178 #define PALETTESIZE 256
\r
180 HINSTANCE hInst; /* current instance */
\r
181 HWND hwndMain = NULL; /* root window*/
\r
182 HWND hwndConsole = NULL;
\r
183 BOOLEAN alwaysOnTop = FALSE;
\r
185 COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
\r
186 blackPieceColor, highlightSquareColor, premoveHighlightColor;
\r
188 ColorClass currentColorClass;
\r
190 HWND hCommPort = NULL; /* currently open comm port */
\r
191 static HWND hwndPause; /* pause button */
\r
192 static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */
\r
193 static HBRUSH lightSquareBrush, darkSquareBrush,
\r
194 blackSquareBrush, /* [HGM] for band between board and holdings */
\r
195 explodeBrush, /* [HGM] atomic */
\r
196 whitePieceBrush, blackPieceBrush, iconBkgndBrush /*, outlineBrush*/;
\r
197 static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];
\r
198 static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];
\r
199 static HPEN gridPen = NULL;
\r
200 static HPEN highlightPen = NULL;
\r
201 static HPEN premovePen = NULL;
\r
202 static NPLOGPALETTE pLogPal;
\r
203 static BOOL paletteChanged = FALSE;
\r
204 static HICON iconWhite, iconBlack, iconCurrent;
\r
205 static int doingSizing = FALSE;
\r
206 static int lastSizing = 0;
\r
207 static int prevStderrPort;
\r
208 static HBITMAP userLogo;
\r
210 /* [AS] Support for background textures */
\r
211 #define BACK_TEXTURE_MODE_DISABLED 0
\r
212 #define BACK_TEXTURE_MODE_PLAIN 1
\r
213 #define BACK_TEXTURE_MODE_FULL_RANDOM 2
\r
215 static HBITMAP liteBackTexture = NULL;
\r
216 static HBITMAP darkBackTexture = NULL;
\r
217 static int liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
218 static int darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
219 static int backTextureSquareSize = 0;
\r
220 static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_SIZE][BOARD_SIZE];
\r
222 #if __GNUC__ && !defined(_winmajor)
\r
223 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */
\r
225 #define oldDialog (_winmajor < 4)
\r
228 char *defaultTextAttribs[] =
\r
230 COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,
\r
231 COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,
\r
241 int cliWidth, cliHeight;
\r
244 SizeInfo sizeInfo[] =
\r
246 { "tiny", 21, 0, 1, 1, 0, 0 },
\r
247 { "teeny", 25, 1, 1, 1, 0, 0 },
\r
248 { "dinky", 29, 1, 1, 1, 0, 0 },
\r
249 { "petite", 33, 1, 1, 1, 0, 0 },
\r
250 { "slim", 37, 2, 1, 0, 0, 0 },
\r
251 { "small", 40, 2, 1, 0, 0, 0 },
\r
252 { "mediocre", 45, 2, 1, 0, 0, 0 },
\r
253 { "middling", 49, 2, 0, 0, 0, 0 },
\r
254 { "average", 54, 2, 0, 0, 0, 0 },
\r
255 { "moderate", 58, 3, 0, 0, 0, 0 },
\r
256 { "medium", 64, 3, 0, 0, 0, 0 },
\r
257 { "bulky", 72, 3, 0, 0, 0, 0 },
\r
258 { "large", 80, 3, 0, 0, 0, 0 },
\r
259 { "big", 87, 3, 0, 0, 0, 0 },
\r
260 { "huge", 95, 3, 0, 0, 0, 0 },
\r
261 { "giant", 108, 3, 0, 0, 0, 0 },
\r
262 { "colossal", 116, 4, 0, 0, 0, 0 },
\r
263 { "titanic", 129, 4, 0, 0, 0, 0 },
\r
264 { NULL, 0, 0, 0, 0, 0, 0 }
\r
267 #define MF(x) {x, {{0,}, 0. }, {0, }, 0}
\r
268 MyFont fontRec[NUM_SIZES][NUM_FONTS] =
\r
270 { 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
271 { 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
272 { 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
273 { 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
274 { 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
275 { 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
276 { 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
277 { 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
278 { 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
279 { 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
280 { 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
281 { 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
282 { 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
283 { 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
284 { 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
285 { 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
286 { 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
287 { 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
290 MyFont *font[NUM_SIZES][NUM_FONTS];
\r
299 #define BUTTON_WIDTH (tinyLayout ? 16 : 32)
\r
300 #define N_BUTTONS 5
\r
302 MyButtonDesc buttonDesc[N_BUTTONS] =
\r
304 {"<<", IDM_ToStart, NULL, NULL},
\r
305 {"<", IDM_Backward, NULL, NULL},
\r
306 {"P", IDM_Pause, NULL, NULL},
\r
307 {">", IDM_Forward, NULL, NULL},
\r
308 {">>", IDM_ToEnd, NULL, NULL},
\r
311 int tinyLayout = 0, smallLayout = 0;
\r
312 #define MENU_BAR_ITEMS 7
\r
313 char *menuBarText[2][MENU_BAR_ITEMS+1] = {
\r
314 { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },
\r
315 { "&F", "&M", "&A", "&S", "&O", "&H", NULL },
\r
319 MySound sounds[(int)NSoundClasses];
\r
320 MyTextAttribs textAttribs[(int)NColorClasses];
\r
322 MyColorizeAttribs colorizeAttribs[] = {
\r
323 { (COLORREF)0, 0, "Shout Text" },
\r
324 { (COLORREF)0, 0, "SShout/CShout" },
\r
325 { (COLORREF)0, 0, "Channel 1 Text" },
\r
326 { (COLORREF)0, 0, "Channel Text" },
\r
327 { (COLORREF)0, 0, "Kibitz Text" },
\r
328 { (COLORREF)0, 0, "Tell Text" },
\r
329 { (COLORREF)0, 0, "Challenge Text" },
\r
330 { (COLORREF)0, 0, "Request Text" },
\r
331 { (COLORREF)0, 0, "Seek Text" },
\r
332 { (COLORREF)0, 0, "Normal Text" },
\r
333 { (COLORREF)0, 0, "None" }
\r
338 static char *commentTitle;
\r
339 static char *commentText;
\r
340 static int commentIndex;
\r
341 static Boolean editComment = FALSE;
\r
342 HWND commentDialog = NULL;
\r
343 BOOLEAN commentDialogUp = FALSE;
\r
344 static int commentX, commentY, commentH, commentW;
\r
346 static char *analysisTitle;
\r
347 static char *analysisText;
\r
348 HWND analysisDialog = NULL;
\r
349 BOOLEAN analysisDialogUp = FALSE;
\r
350 static int analysisX, analysisY, analysisH, analysisW;
\r
352 char errorTitle[MSG_SIZ];
\r
353 char errorMessage[2*MSG_SIZ];
\r
354 HWND errorDialog = NULL;
\r
355 BOOLEAN moveErrorMessageUp = FALSE;
\r
356 BOOLEAN consoleEcho = TRUE;
\r
357 CHARFORMAT consoleCF;
\r
358 COLORREF consoleBackgroundColor;
\r
360 char *programVersion;
\r
366 typedef int CPKind;
\r
375 SOCKET sock2; /* stderr socket for OpenRcmd */
\r
378 #define INPUT_SOURCE_BUF_SIZE 4096
\r
380 typedef struct _InputSource {
\r
387 char buf[INPUT_SOURCE_BUF_SIZE];
\r
391 InputCallback func;
\r
392 struct _InputSource *second; /* for stderr thread on CPRcmd */
\r
396 InputSource *consoleInputSource;
\r
401 VOID ConsoleOutput(char* data, int length, int forceVisible);
\r
402 VOID ConsoleCreate();
\r
404 ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
405 VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
\r
406 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
\r
407 VOID ParseCommSettings(char *arg, DCB *dcb);
\r
409 StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
\r
410 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
\r
411 void ParseIcsTextMenu(char *icsTextMenuString);
\r
412 VOID PopUpMoveDialog(char firstchar);
\r
413 VOID PopUpNameDialog(char firstchar);
\r
414 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
\r
418 int GameListOptions();
\r
420 HWND moveHistoryDialog = NULL;
\r
421 BOOLEAN moveHistoryDialogUp = FALSE;
\r
423 WindowPlacement wpMoveHistory;
\r
425 HWND evalGraphDialog = NULL;
\r
426 BOOLEAN evalGraphDialogUp = FALSE;
\r
428 WindowPlacement wpEvalGraph;
\r
430 HWND engineOutputDialog = NULL;
\r
431 BOOLEAN engineOutputDialogUp = FALSE;
\r
433 WindowPlacement wpEngineOutput;
\r
434 WindowPlacement wpGameList;
\r
435 WindowPlacement wpConsole;
\r
437 VOID MoveHistoryPopUp();
\r
438 VOID MoveHistoryPopDown();
\r
439 VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
440 BOOL MoveHistoryIsUp();
\r
442 VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );
\r
443 VOID EvalGraphPopUp();
\r
444 VOID EvalGraphPopDown();
\r
445 BOOL EvalGraphIsUp();
\r
447 VOID EngineOutputPopUp();
\r
448 VOID EngineOutputPopDown();
\r
449 BOOL EngineOutputIsUp();
\r
450 VOID EngineOutputUpdate( FrontEndProgramStats * stats );
\r
452 VOID GothicPopUp(char *title, VariantClass variant);
\r
454 * Setting "frozen" should disable all user input other than deleting
\r
455 * the window. We do this while engines are initializing themselves.
\r
457 static int frozen = 0;
\r
458 static int oldMenuItemState[MENU_BAR_ITEMS];
\r
464 if (frozen) return;
\r
466 hmenu = GetMenu(hwndMain);
\r
467 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
468 oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
\r
470 DrawMenuBar(hwndMain);
\r
473 /* Undo a FreezeUI */
\r
479 if (!frozen) return;
\r
481 hmenu = GetMenu(hwndMain);
\r
482 for (i=0; i<MENU_BAR_ITEMS; i++) {
\r
483 EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
\r
485 DrawMenuBar(hwndMain);
\r
488 static int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them
\r
490 /* JAWS preparation patch (WinBoard for the sight impaired). Define required insertions as empty */
\r
495 #define JAWS_ALT_INTERCEPT
\r
496 #define JAWS_KB_NAVIGATION
\r
497 #define JAWS_MENU_ITEMS
\r
498 #define JAWS_SILENCE
\r
499 #define JAWS_REPLAY
\r
501 #define JAWS_COPYRIGHT
\r
502 #define JAWS_DELETE(X) X
\r
503 #define SAYMACHINEMOVE()
\r
507 /*---------------------------------------------------------------------------*\
\r
511 \*---------------------------------------------------------------------------*/
\r
514 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
\r
515 LPSTR lpCmdLine, int nCmdShow)
\r
518 HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
\r
519 // INITCOMMONCONTROLSEX ex;
\r
523 LoadLibrary("RICHED32.DLL");
\r
524 consoleCF.cbSize = sizeof(CHARFORMAT);
\r
526 if (!InitApplication(hInstance)) {
\r
529 if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
\r
535 // InitCommonControlsEx(&ex);
\r
536 InitCommonControls();
\r
538 hAccelMain = LoadAccelerators (hInstance, szAppName);
\r
539 hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
\r
540 hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
\r
542 /* Acquire and dispatch messages until a WM_QUIT message is received. */
\r
544 while (GetMessage(&msg, /* message structure */
\r
545 NULL, /* handle of window receiving the message */
\r
546 0, /* lowest message to examine */
\r
547 0)) /* highest message to examine */
\r
550 if(msg.message == WM_CHAR && msg.wParam == '\t') {
\r
551 // [HGM] navigate: switch between all windows with tab
\r
552 HWND e1 = NULL, e2 = NULL, mh = NULL, hInput = NULL, hText = NULL;
\r
553 int i, currentElement = 0;
\r
555 // first determine what element of the chain we come from (if any)
\r
556 if(appData.icsActive) {
\r
557 hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);
\r
558 hText = GetDlgItem(hwndConsole, OPT_ConsoleText);
\r
560 if(engineOutputDialog && EngineOutputIsUp()) {
\r
561 e1 = GetDlgItem(engineOutputDialog, IDC_EngineMemo1);
\r
562 e2 = GetDlgItem(engineOutputDialog, IDC_EngineMemo2);
\r
564 if(moveHistoryDialog && MoveHistoryIsUp()) {
\r
565 mh = GetDlgItem(moveHistoryDialog, IDC_MoveHistory);
\r
567 if(msg.hwnd == hwndMain) currentElement = 7 ; else
\r
568 if(msg.hwnd == engineOutputDialog) currentElement = 2; else
\r
569 if(msg.hwnd == e1) currentElement = 2; else
\r
570 if(msg.hwnd == e2) currentElement = 3; else
\r
571 if(msg.hwnd == moveHistoryDialog) currentElement = 4; else
\r
572 if(msg.hwnd == mh) currentElement = 4; else
\r
573 if(msg.hwnd == evalGraphDialog) currentElement = 7; else
\r
574 if(msg.hwnd == hText) currentElement = 5; else
\r
575 if(msg.hwnd == hInput) currentElement = 6; else
\r
576 for (i = 0; i < N_BUTTONS; i++) {
\r
577 if (buttonDesc[i].hwnd == msg.hwnd) { currentElement = 1; break; }
\r
580 // determine where to go to
\r
581 if(currentElement) { HWND h = NULL; int direction = GetKeyState(VK_SHIFT) < 0 ? -1 : 1;
\r
583 currentElement = (currentElement + direction) % 7;
\r
584 switch(currentElement) {
\r
586 h = hwndMain; break; // passing this case always makes the loop exit
\r
588 h = buttonDesc[0].hwnd; break; // could be NULL
\r
590 if(!EngineOutputIsUp()) continue; // skip closed auxiliary windows
\r
593 if(!EngineOutputIsUp()) continue;
\r
596 if(!MoveHistoryIsUp()) continue;
\r
598 // case 5: // input to eval graph does not seem to get here!
\r
599 // if(!EvalGraphIsUp()) continue;
\r
600 // h = evalGraphDialog; break;
\r
602 if(!appData.icsActive) continue;
\r
606 if(!appData.icsActive) continue;
\r
612 if(currentElement > 4 && IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);
\r
613 if(currentElement < 5 && IsIconic(hwndMain)) ShowWindow(hwndMain, SW_RESTORE); // all open together
\r
616 continue; // this message now has been processed
\r
620 if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
\r
621 !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
\r
622 !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
\r
623 !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
\r
624 !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
\r
625 !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
\r
626 !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
\r
627 !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) && JAWS_ACCEL
\r
628 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
\r
629 !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
\r
630 TranslateMessage(&msg); /* Translates virtual key codes */
\r
631 DispatchMessage(&msg); /* Dispatches message to window */
\r
636 return (msg.wParam); /* Returns the value from PostQuitMessage */
\r
639 /*---------------------------------------------------------------------------*\
\r
641 * Initialization functions
\r
643 \*---------------------------------------------------------------------------*/
\r
647 { // update user logo if necessary
\r
648 static char oldUserName[MSG_SIZ], *curName;
\r
650 if(appData.autoLogo) {
\r
651 curName = UserName();
\r
652 if(strcmp(curName, oldUserName)) {
\r
653 sprintf(oldUserName, "logos\\%s.bmp", curName);
\r
654 userLogo = LoadImage( 0, oldUserName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
655 strcpy(oldUserName, curName);
\r
661 InitApplication(HINSTANCE hInstance)
\r
665 /* Fill in window class structure with parameters that describe the */
\r
668 wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
\r
669 wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
\r
670 wc.cbClsExtra = 0; /* No per-class extra data. */
\r
671 wc.cbWndExtra = 0; /* No per-window extra data. */
\r
672 wc.hInstance = hInstance; /* Owner of this class */
\r
673 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
674 wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
\r
675 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
\r
676 wc.lpszMenuName = szAppName; /* Menu name from .RC */
\r
677 wc.lpszClassName = szAppName; /* Name to register as */
\r
679 /* Register the window class and return success/failure code. */
\r
680 if (!RegisterClass(&wc)) return FALSE;
\r
682 wc.style = CS_HREDRAW | CS_VREDRAW;
\r
683 wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
\r
685 wc.cbWndExtra = DLGWINDOWEXTRA;
\r
686 wc.hInstance = hInstance;
\r
687 wc.hIcon = LoadIcon(hInstance, "icon_white");
\r
688 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
\r
689 wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
\r
690 wc.lpszMenuName = NULL;
\r
691 wc.lpszClassName = szConsoleName;
\r
693 if (!RegisterClass(&wc)) return FALSE;
\r
698 /* Set by InitInstance, used by EnsureOnScreen */
\r
699 int screenHeight, screenWidth;
\r
702 EnsureOnScreen(int *x, int *y, int minX, int minY)
\r
704 // int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
\r
705 /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
\r
706 if (*x > screenWidth - 32) *x = 0;
\r
707 if (*y > screenHeight - 32) *y = 0;
\r
708 if (*x < minX) *x = minX;
\r
709 if (*y < minY) *y = minY;
\r
713 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
\r
715 HWND hwnd; /* Main window handle. */
\r
717 WINDOWPLACEMENT wp;
\r
720 hInst = hInstance; /* Store instance handle in our global variable */
\r
722 if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
\r
723 *filepart = NULLCHAR;
\r
725 GetCurrentDirectory(MSG_SIZ, installDir);
\r
727 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise
\r
728 screenWidth = screenHeight = 1000; // [HGM] placement: kludge to allow calling EnsureOnScreen from InitAppData
\r
729 InitAppData(lpCmdLine); /* Get run-time parameters */
\r
730 if (appData.debugMode) {
\r
731 debugFP = fopen(appData.nameOfDebugFile, "w");
\r
732 setbuf(debugFP, NULL);
\r
737 // InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()
\r
738 // InitEngineUCI( installDir, &second );
\r
740 /* Create a main window for this application instance. */
\r
741 hwnd = CreateWindow(szAppName, szTitle,
\r
742 (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
\r
743 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
\r
744 NULL, NULL, hInstance, NULL);
\r
747 /* If window could not be created, return "failure" */
\r
752 /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */
\r
753 if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {
\r
754 first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
756 if (first.programLogo == NULL && appData.debugMode) {
\r
757 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );
\r
759 } else if(appData.autoLogo) {
\r
760 if(appData.firstDirectory && appData.firstDirectory[0]) {
\r
762 sprintf(buf, "%s/logo.bmp", appData.firstDirectory);
\r
763 first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
767 if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {
\r
768 second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
770 if (second.programLogo == NULL && appData.debugMode) {
\r
771 fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );
\r
773 } else if(appData.autoLogo) {
\r
775 if(appData.icsActive) { // [HGM] logo: in ICS mode second can be used for ICS
\r
776 sprintf(buf, "logos\\%s.bmp", appData.icsHost);
\r
777 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
779 if(appData.secondDirectory && appData.secondDirectory[0]) {
\r
780 sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);
\r
781 second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
787 iconWhite = LoadIcon(hInstance, "icon_white");
\r
788 iconBlack = LoadIcon(hInstance, "icon_black");
\r
789 iconCurrent = iconWhite;
\r
790 InitDrawingColors();
\r
791 screenHeight = GetSystemMetrics(SM_CYSCREEN);
\r
792 screenWidth = GetSystemMetrics(SM_CXSCREEN);
\r
793 for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
\r
794 /* Compute window size for each board size, and use the largest
\r
795 size that fits on this screen as the default. */
\r
796 InitDrawingSizes((BoardSize)(ibs+1000), 0);
\r
797 if (boardSize == (BoardSize)-1 &&
\r
798 winH <= screenHeight
\r
799 - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10
\r
800 && winW <= screenWidth) {
\r
801 boardSize = (BoardSize)ibs;
\r
805 InitDrawingSizes(boardSize, 0);
\r
807 buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
\r
809 /* [AS] Load textures if specified */
\r
810 ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );
\r
812 if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {
\r
813 liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
814 liteBackTextureMode = appData.liteBackTextureMode;
\r
816 if (liteBackTexture == NULL && appData.debugMode) {
\r
817 fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );
\r
821 if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {
\r
822 darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
\r
823 darkBackTextureMode = appData.darkBackTextureMode;
\r
825 if (darkBackTexture == NULL && appData.debugMode) {
\r
826 fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );
\r
830 mysrandom( (unsigned) time(NULL) );
\r
832 /* [AS] Restore layout */
\r
833 if( wpMoveHistory.visible ) {
\r
834 MoveHistoryPopUp();
\r
837 if( wpEvalGraph.visible ) {
\r
841 if( wpEngineOutput.visible ) {
\r
842 EngineOutputPopUp();
\r
847 /* Make the window visible; update its client area; and return "success" */
\r
848 EnsureOnScreen(&boardX, &boardY, minX, minY);
\r
849 wp.length = sizeof(WINDOWPLACEMENT);
\r
851 wp.showCmd = nCmdShow;
\r
852 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
\r
853 wp.rcNormalPosition.left = boardX;
\r
854 wp.rcNormalPosition.right = boardX + winWidth;
\r
855 wp.rcNormalPosition.top = boardY;
\r
856 wp.rcNormalPosition.bottom = boardY + winHeight;
\r
857 SetWindowPlacement(hwndMain, &wp);
\r
859 if(!appData.noGUI) SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
860 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
864 SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
\r
865 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
\r
867 ShowWindow(hwndConsole, nCmdShow);
\r
869 if(!appData.noGUI) UpdateWindow(hwnd); else ShowWindow(hwnd, SW_MINIMIZE);
\r
877 ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
\r
878 ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
\r
879 ArgSettingsFilename,
\r
880 ArgX, ArgY, ArgZ // [HGM] placement: for window-placement options stored relative to main window
\r
888 String *pString; // ArgString
\r
889 int *pInt; // ArgInt
\r
890 float *pFloat; // ArgFloat
\r
891 Boolean *pBoolean; // ArgBoolean
\r
892 COLORREF *pColor; // ArgColor
\r
893 ColorClass cc; // ArgAttribs
\r
894 String *pFilename; // ArgFilename
\r
895 BoardSize *pBoardSize; // ArgBoardSize
\r
896 int whichFont; // ArgFont
\r
897 DCB *pDCB; // ArgCommSettings
\r
898 String *pFilename; // ArgSettingsFilename
\r
906 ArgDescriptor argDescriptors[] = {
\r
907 /* positional arguments */
\r
908 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
909 { "", ArgNone, NULL },
\r
910 /* keyword arguments */
\r
911 { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },
\r
912 { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },
\r
913 { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },
\r
914 { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },
\r
915 { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },
\r
916 { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },
\r
917 { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },
\r
918 { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },
\r
919 { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },
\r
920 { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },
\r
921 { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },
\r
922 { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },
\r
923 { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },
\r
924 { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },
\r
925 { "initString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
926 { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },
\r
927 { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },
\r
928 { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,
\r
930 { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,
\r
932 { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,
\r
934 { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },
\r
935 { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,
\r
937 { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },
\r
938 { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
939 { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
940 { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
941 { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
\r
942 { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },
\r
943 { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },
\r
944 { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
945 { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
\r
946 { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
947 { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },
\r
948 { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
949 { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },
\r
950 { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
951 { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
\r
952 { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
953 { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
\r
954 /*!!bitmapDirectory?*/
\r
955 { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
956 { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
\r
957 { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
958 { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
\r
959 { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },
\r
960 { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },
\r
961 { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },
\r
962 { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },
\r
963 { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },
\r
964 { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },
\r
965 { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },
\r
966 { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },
\r
967 { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
968 { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
\r
969 { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
970 { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },
\r
971 { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
972 { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },
\r
973 { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
974 { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
975 { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
976 { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
\r
977 { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
978 { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
\r
979 { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },
\r
980 { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },
\r
981 { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
982 { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
\r
983 { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },
\r
984 { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },
\r
985 { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },
\r
986 { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
987 { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
\r
988 { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
989 { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
\r
990 { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },
\r
991 { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },
\r
992 { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },
\r
993 { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },
\r
994 { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
995 { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
\r
996 { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
997 { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
\r
998 { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
999 { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
\r
1000 { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
1001 { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
\r
1002 { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },
\r
1003 { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },
\r
1004 { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
1005 { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
\r
1006 { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
1007 { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },
\r
1008 { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },
\r
1009 { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },
\r
1010 { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
1011 { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
\r
1012 { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },
\r
1013 { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },
\r
1014 { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
1015 { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
\r
1016 { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },
\r
1017 { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },
\r
1018 { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
1019 { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
\r
1020 { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
1021 { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },
\r
1022 { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
1023 { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
\r
1024 { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },
\r
1025 { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },
\r
1026 { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
1027 { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
\r
1028 { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },
\r
1029 { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },
\r
1030 { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
1031 { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
\r
1032 { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },
\r
1033 { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1034 { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1035 { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
\r
1036 { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },
\r
1037 { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1038 { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1039 { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
\r
1040 { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },
\r
1041 { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1042 { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1043 { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
\r
1044 { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },
\r
1045 { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1046 { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1047 { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
\r
1048 { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors,
\r
1049 FALSE }, /* only so that old WinBoard.ini files from betas can be read */
\r
1050 { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },
\r
1051 { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },
\r
1052 { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },
\r
1053 { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },
\r
1054 { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },
\r
1055 { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },
\r
1056 { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE }, /* [AS] */
\r
1057 { "boardSize", ArgBoardSize, (LPVOID) &boardSize,
\r
1058 TRUE }, /* must come after all fonts */
\r
1059 { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },
\r
1060 { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,
\r
1061 FALSE }, /* historical; kept only so old winboard.ini files will parse */
\r
1062 { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },
\r
1063 { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },
\r
1064 { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
1065 { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
\r
1066 { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },
\r
1067 { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1068 { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1069 { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
\r
1070 { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },
\r
1071 { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },
\r
1072 { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
1073 { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
\r
1074 { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },
\r
1075 { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },
\r
1076 { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
1077 { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
\r
1078 { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },
\r
1079 { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },
\r
1080 { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
1081 { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
\r
1082 { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },
\r
1083 { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },
\r
1084 { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
1085 { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
\r
1086 { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },
\r
1087 { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1088 { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1089 { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
\r
1091 { "cmailGameName", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
1092 { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
\r
1094 { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },
\r
1095 { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1096 { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1097 { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
\r
1098 { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },
\r
1099 { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1100 { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1101 { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
\r
1102 { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },
\r
1103 { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },
\r
1104 { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
1105 { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
\r
1106 { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },
\r
1107 { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },
\r
1108 { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
1109 { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
\r
1110 { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },
\r
1111 { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },
\r
1112 { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
1113 { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
\r
1114 { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },
\r
1115 { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },
\r
1116 { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
1117 { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },
\r
1118 { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },
\r
1119 { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },
\r
1120 { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
1121 { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
\r
1122 { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },
\r
1123 { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },
\r
1124 { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },
\r
1125 { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1126 { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
\r
1127 { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },
\r
1128 { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},
\r
1129 { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},
\r
1130 { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1131 { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
\r
1132 { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},
\r
1133 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1134 { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
\r
1135 { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },
\r
1136 { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1137 { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
\r
1138 { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },
\r
1139 { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },
\r
1140 { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1141 { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },
\r
1142 { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },
\r
1143 { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },
\r
1144 { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },
\r
1145 { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1146 { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
\r
1147 { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },
\r
1148 { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },
\r
1149 { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1150 { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
\r
1151 { "highlightLastMove", ArgBoolean,
\r
1152 (LPVOID) &appData.highlightLastMove, TRUE },
\r
1153 { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1154 { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1155 { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
\r
1156 { "highlightDragging", ArgBoolean,
\r
1157 (LPVOID) &appData.highlightDragging, TRUE },
\r
1158 { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },
\r
1159 { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1160 { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
\r
1161 { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },
\r
1162 { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },
\r
1163 { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1164 { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
\r
1165 { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },
\r
1166 { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },
\r
1167 { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },
\r
1168 { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },
\r
1169 { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },
\r
1170 { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },
\r
1171 { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },
\r
1172 { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },
\r
1173 { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },
\r
1174 { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },
\r
1175 { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },
\r
1176 { "soundShout", ArgFilename,
\r
1177 (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },
\r
1178 { "soundSShout", ArgFilename,
\r
1179 (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },
\r
1180 { "soundChannel1", ArgFilename,
\r
1181 (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },
\r
1182 { "soundChannel", ArgFilename,
\r
1183 (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },
\r
1184 { "soundKibitz", ArgFilename,
\r
1185 (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },
\r
1186 { "soundTell", ArgFilename,
\r
1187 (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },
\r
1188 { "soundChallenge", ArgFilename,
\r
1189 (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },
\r
1190 { "soundRequest", ArgFilename,
\r
1191 (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },
\r
1192 { "soundSeek", ArgFilename,
\r
1193 (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },
\r
1194 { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },
\r
1195 { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },
\r
1196 { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },
\r
1197 { "soundIcsLoss", ArgFilename,
\r
1198 (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },
\r
1199 { "soundIcsDraw", ArgFilename,
\r
1200 (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },
\r
1201 { "soundIcsUnfinished", ArgFilename,
\r
1202 (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},
\r
1203 { "soundIcsAlarm", ArgFilename,
\r
1204 (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },
\r
1205 { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },
\r
1206 { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },
\r
1207 { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1208 { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
\r
1209 { "reuseChessPrograms", ArgBoolean,
\r
1210 (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */
\r
1211 { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },
\r
1212 { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },
\r
1213 { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1214 { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
\r
1215 { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },
\r
1216 { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1217 { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
\r
1218 { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },
\r
1219 { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },
\r
1220 { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },
\r
1221 { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1222 { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },
\r
1223 { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },
\r
1224 { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },
\r
1225 { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,
\r
1227 { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,
\r
1229 { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1230 { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },
\r
1231 { "variant", ArgString, (LPVOID) &appData.variant, FALSE },
\r
1232 { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion, FALSE },
\r
1233 { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,FALSE },
\r
1234 { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },
\r
1235 { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },
\r
1236 { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1237 { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
\r
1238 /* [AS] New features */
\r
1239 { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE },
\r
1240 { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE },
\r
1241 { "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE },
\r
1242 { "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE },
\r
1243 { "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE },
\r
1244 { "darkBackTextureFile", ArgString, (LPVOID) &appData.darkBackTextureFile, TRUE },
\r
1245 { "liteBackTextureMode", ArgInt, (LPVOID) &appData.liteBackTextureMode, TRUE },
\r
1246 { "darkBackTextureMode", ArgInt, (LPVOID) &appData.darkBackTextureMode, TRUE },
\r
1247 { "renderPiecesWithFont", ArgString, (LPVOID) &appData.renderPiecesWithFont, TRUE },
\r
1248 { "fontPieceToCharTable", ArgString, (LPVOID) &appData.fontToPieceTable, TRUE },
\r
1249 { "fontPieceBackColorWhite", ArgColor, (LPVOID) &appData.fontBackColorWhite, TRUE },
\r
1250 { "fontPieceForeColorWhite", ArgColor, (LPVOID) &appData.fontForeColorWhite, TRUE },
\r
1251 { "fontPieceBackColorBlack", ArgColor, (LPVOID) &appData.fontBackColorBlack, TRUE },
\r
1252 { "fontPieceForeColorBlack", ArgColor, (LPVOID) &appData.fontForeColorBlack, TRUE },
\r
1253 { "fontPieceSize", ArgInt, (LPVOID) &appData.fontPieceSize, TRUE },
\r
1254 { "overrideLineGap", ArgInt, (LPVOID) &appData.overrideLineGap, TRUE },
\r
1255 { "adjudicateLossThreshold", ArgInt, (LPVOID) &appData.adjudicateLossThreshold, TRUE },
\r
1256 { "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE },
\r
1257 { "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE },
\r
1258 { "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1259 { "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
\r
1260 { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },
\r
1261 { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE },
\r
1262 { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE },
\r
1263 { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE },
\r
1264 { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE },
\r
1265 { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE },
\r
1266 { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE },
\r
1267 { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE },
\r
1268 { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE },
\r
1269 { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE },
\r
1270 { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE },
\r
1271 { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE },
\r
1272 { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE },
\r
1273 { "firstIsUCI", ArgBoolean, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1274 { "fUCI", ArgTrue, (LPVOID) &appData.firstIsUCI, FALSE },
\r
1275 { "secondIsUCI", ArgBoolean, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1276 { "sUCI", ArgTrue, (LPVOID) &appData.secondIsUCI, FALSE },
\r
1277 { "firstHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1278 { "fNoOwnBookUCI", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1279 { "firstXBook", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },
\r
1280 { "secondHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1281 { "sNoOwnBookUCI", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1282 { "secondXBook", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },
\r
1283 { "polyglotDir", ArgFilename, (LPVOID) &appData.polyglotDir, TRUE },
\r
1284 { "usePolyglotBook", ArgBoolean, (LPVOID) &appData.usePolyglotBook, TRUE },
\r
1285 { "polyglotBook", ArgFilename, (LPVOID) &appData.polyglotBook, TRUE },
\r
1286 { "defaultHashSize", ArgInt, (LPVOID) &appData.defaultHashSize, TRUE },
\r
1287 { "defaultCacheSizeEGTB", ArgInt, (LPVOID) &appData.defaultCacheSizeEGTB, TRUE },
\r
1288 { "defaultPathEGTB", ArgFilename, (LPVOID) &appData.defaultPathEGTB, TRUE },
\r
1290 /* [HGM] board-size, adjudication and misc. options */
\r
1291 { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE },
\r
1292 { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE },
\r
1293 { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE },
\r
1294 { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE },
\r
1295 { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE },
\r
1296 { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE },
\r
1297 { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE },
\r
1298 { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE },
\r
1299 { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE },
\r
1300 { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE },
\r
1301 { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE },
\r
1302 { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE },
\r
1303 { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE },
\r
1304 { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE },
\r
1305 { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE },
\r
1306 { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE },
\r
1307 { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE },
\r
1308 { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE },
\r
1309 { "userName", ArgString, (LPVOID) &appData.userName, FALSE },
\r
1310 { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE },
\r
1311 { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE },
\r
1312 { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE },
\r
1313 { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE },
\r
1314 { "niceEngines", ArgInt, (LPVOID) &appData.niceEngines, TRUE },
\r
1315 { "firstLogo", ArgFilename, (LPVOID) &appData.firstLogo, FALSE },
\r
1316 { "secondLogo", ArgFilename, (LPVOID) &appData.secondLogo, FALSE },
\r
1317 { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE },
\r
1318 { "firstOptions", ArgString, (LPVOID) &appData.firstOptions, FALSE },
\r
1319 { "secondOptions", ArgString, (LPVOID) &appData.secondOptions, FALSE },
\r
1320 { "firstNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride1, FALSE },
\r
1321 { "secondNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride2, FALSE },
\r
1324 { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },
\r
1325 { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },
\r
1326 { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1327 { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
\r
1328 { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },
\r
1329 { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },
\r
1330 { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1331 { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
\r
1332 { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },
\r
1333 { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },
\r
1334 { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },
\r
1335 { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE },
\r
1336 { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,
\r
1338 { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE },
\r
1339 { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE },
\r
1340 { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE },
\r
1341 { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1342 { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },
\r
1343 { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE },
\r
1344 { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,
\r
1346 { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1347 { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1348 { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },
\r
1349 { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE },
\r
1350 { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE },
\r
1351 { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1352 { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1353 { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1354 { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },
\r
1355 { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE },
\r
1356 { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE },
\r
1357 { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1358 { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },
\r
1359 { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },
\r
1360 { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },
\r
1361 { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },
\r
1362 { "zippyShortGame", ArgInt, (LPVOID)&appData.zippyShortGame, FALSE },
\r
1363 /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */
\r
1364 { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },
\r
1366 /* [HGM] options for broadcasting and time odds */
\r
1367 { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },
\r
1368 { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },
\r
1369 { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },
\r
1370 { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },
\r
1371 { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },
\r
1372 { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },
\r
1373 { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },
\r
1374 { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },
\r
1375 { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },
\r
1376 { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },
\r
1377 { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE },
\r
1379 // [HGM] placement: put all window layouts last in ini file, but man X,Y before all others
\r
1380 { "minX", ArgZ, (LPVOID) &minX, FALSE }, // [HGM] placement: to make suer auxialary windows can be placed
\r
1381 { "minY", ArgZ, (LPVOID) &minY, FALSE },
\r
1382 { "winWidth", ArgInt, (LPVOID) &winWidth, TRUE }, // [HGM] placement: dummies to remember right & bottom
\r
1383 { "winHeight", ArgInt, (LPVOID) &winHeight, TRUE }, // for attaching auxiliary windows to them
\r
1384 { "x", ArgInt, (LPVOID) &boardX, TRUE },
\r
1385 { "y", ArgInt, (LPVOID) &boardY, TRUE },
\r
1386 { "icsX", ArgX, (LPVOID) &wpConsole.x, TRUE },
\r
1387 { "icsY", ArgY, (LPVOID) &wpConsole.y, TRUE },
\r
1388 { "icsW", ArgInt, (LPVOID) &wpConsole.width, TRUE },
\r
1389 { "icsH", ArgInt, (LPVOID) &wpConsole.height, TRUE },
\r
1390 { "analysisX", ArgX, (LPVOID) &analysisX, FALSE }, // [HGM] placement: analysis window no longer exists
\r
1391 { "analysisY", ArgY, (LPVOID) &analysisY, FALSE }, // provided for compatibility with old ini files
\r
1392 { "analysisW", ArgInt, (LPVOID) &analysisW, FALSE },
\r
1393 { "analysisH", ArgInt, (LPVOID) &analysisH, FALSE },
\r
1394 { "commentX", ArgX, (LPVOID) &commentX, TRUE },
\r
1395 { "commentY", ArgY, (LPVOID) &commentY, TRUE },
\r
1396 { "commentW", ArgInt, (LPVOID) &commentW, TRUE },
\r
1397 { "commentH", ArgInt, (LPVOID) &commentH, TRUE },
\r
1398 { "tagsX", ArgX, (LPVOID) &editTagsX, TRUE },
\r
1399 { "tagsY", ArgY, (LPVOID) &editTagsY, TRUE },
\r
1400 { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },
\r
1401 { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },
\r
1402 { "gameListX", ArgX, (LPVOID) &wpGameList.x, TRUE },
\r
1403 { "gameListY", ArgY, (LPVOID) &wpGameList.y, TRUE },
\r
1404 { "gameListW", ArgInt, (LPVOID) &wpGameList.width, TRUE },
\r
1405 { "gameListH", ArgInt, (LPVOID) &wpGameList.height, TRUE },
\r
1406 /* [AS] Layout stuff */
\r
1407 { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },
\r
1408 { "moveHistoryX", ArgX, (LPVOID) &wpMoveHistory.x, TRUE },
\r
1409 { "moveHistoryY", ArgY, (LPVOID) &wpMoveHistory.y, TRUE },
\r
1410 { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },
\r
1411 { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },
\r
1413 { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },
\r
1414 { "evalGraphX", ArgX, (LPVOID) &wpEvalGraph.x, TRUE },
\r
1415 { "evalGraphY", ArgY, (LPVOID) &wpEvalGraph.y, TRUE },
\r
1416 { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },
\r
1417 { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },
\r
1419 { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },
\r
1420 { "engineOutputX", ArgX, (LPVOID) &wpEngineOutput.x, TRUE },
\r
1421 { "engineOutputY", ArgY, (LPVOID) &wpEngineOutput.y, TRUE },
\r
1422 { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },
\r
1423 { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },
\r
1425 { NULL, ArgNone, NULL, FALSE }
\r
1429 /* Kludge for indirection files on command line */
\r
1430 char* lastIndirectionFilename;
\r
1431 ArgDescriptor argDescriptorIndirection =
\r
1432 { "", ArgSettingsFilename, (LPVOID) NULL, FALSE };
\r
1436 ExitArgError(char *msg, char *badArg)
\r
1438 char buf[MSG_SIZ];
\r
1440 sprintf(buf, "%s %s", msg, badArg);
\r
1441 DisplayFatalError(buf, 0, 2);
\r
1445 /* Command line font name parser. NULL name means do nothing.
\r
1446 Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"
\r
1447 For backward compatibility, syntax without the colon is also
\r
1448 accepted, but font names with digits in them won't work in that case.
\r
1451 ParseFontName(char *name, MyFontParams *mfp)
\r
1454 if (name == NULL) return;
\r
1456 q = strchr(p, ':');
\r
1458 if (q - p >= sizeof(mfp->faceName))
\r
1459 ExitArgError("Font name too long:", name);
\r
1460 memcpy(mfp->faceName, p, q - p);
\r
1461 mfp->faceName[q - p] = NULLCHAR;
\r
1464 q = mfp->faceName;
\r
1465 while (*p && !isdigit(*p)) {
\r
1467 if (q - mfp->faceName >= sizeof(mfp->faceName))
\r
1468 ExitArgError("Font name too long:", name);
\r
1470 while (q > mfp->faceName && q[-1] == ' ') q--;
\r
1473 if (!*p) ExitArgError("Font point size missing:", name);
\r
1474 mfp->pointSize = (float) atof(p);
\r
1475 mfp->bold = (strchr(p, 'b') != NULL);
\r
1476 mfp->italic = (strchr(p, 'i') != NULL);
\r
1477 mfp->underline = (strchr(p, 'u') != NULL);
\r
1478 mfp->strikeout = (strchr(p, 's') != NULL);
\r
1481 /* Color name parser.
\r
1482 X version accepts X color names, but this one
\r
1483 handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */
\r
1485 ParseColorName(char *name)
\r
1487 int red, green, blue, count;
\r
1488 char buf[MSG_SIZ];
\r
1490 count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);
\r
1492 count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d",
\r
1493 &red, &green, &blue);
\r
1496 sprintf(buf, "Can't parse color name %s", name);
\r
1497 DisplayError(buf, 0);
\r
1498 return RGB(0, 0, 0);
\r
1500 return PALETTERGB(red, green, blue);
\r
1504 void ParseAttribs(COLORREF *color, int *effects, char* argValue)
\r
1506 char *e = argValue;
\r
1510 if (*e == 'b') eff |= CFE_BOLD;
\r
1511 else if (*e == 'i') eff |= CFE_ITALIC;
\r
1512 else if (*e == 'u') eff |= CFE_UNDERLINE;
\r
1513 else if (*e == 's') eff |= CFE_STRIKEOUT;
\r
1514 else if (*e == '#' || isdigit(*e)) break;
\r
1518 *color = ParseColorName(e);
\r
1523 ParseBoardSize(char *name)
\r
1525 BoardSize bs = SizeTiny;
\r
1526 while (sizeInfo[bs].name != NULL) {
\r
1527 if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;
\r
1530 ExitArgError("Unrecognized board size value", name);
\r
1531 return bs; /* not reached */
\r
1536 StringGet(void *getClosure)
\r
1538 char **p = (char **) getClosure;
\r
1543 FileGet(void *getClosure)
\r
1546 FILE* f = (FILE*) getClosure;
\r
1549 if (c == '\r') c = getc(f); // work around DOS format files by bypassing the '\r' completely
\r
1556 /* Parse settings file named "name". If file found, return the
\r
1557 full name in fullname and return TRUE; else return FALSE */
\r
1559 ParseSettingsFile(char *name, char fullname[MSG_SIZ])
\r
1563 int ok; char buf[MSG_SIZ];
\r
1565 ok = SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy);
\r
1566 if(!ok && strchr(name, '.') == NULL) { // [HGM] append default file-name extension '.ini' when needed
\r
1567 sprintf(buf, "%s.ini", name);
\r
1568 ok = SearchPath(installDir, buf, NULL, MSG_SIZ, fullname, &dummy);
\r
1571 f = fopen(fullname, "r");
\r
1573 ParseArgs(FileGet, f);
\r
1582 ParseArgs(GetFunc get, void *cl)
\r
1584 char argName[ARG_MAX];
\r
1585 char argValue[ARG_MAX];
\r
1586 ArgDescriptor *ad;
\r
1595 while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);
\r
1596 if (ch == NULLCHAR) break;
\r
1598 /* Comment to end of line */
\r
1600 while (ch != '\n' && ch != NULLCHAR) ch = get(cl);
\r
1602 } else if (ch == '/' || ch == '-') {
\r
1605 while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&
\r
1606 ch != '\n' && ch != '\t') {
\r
1612 for (ad = argDescriptors; ad->argName != NULL; ad++)
\r
1613 if (strcmp(ad->argName, argName + 1) == 0) break;
\r
1615 if (ad->argName == NULL)
\r
1616 ExitArgError("Unrecognized argument", argName);
\r
1618 } else if (ch == '@') {
\r
1619 /* Indirection file */
\r
1620 ad = &argDescriptorIndirection;
\r
1623 /* Positional argument */
\r
1624 ad = &argDescriptors[posarg++];
\r
1625 strcpy(argName, ad->argName);
\r
1628 if (ad->argType == ArgTrue) {
\r
1629 *(Boolean *) ad->argLoc = TRUE;
\r
1632 if (ad->argType == ArgFalse) {
\r
1633 *(Boolean *) ad->argLoc = FALSE;
\r
1637 while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
\r
1638 if (ch == NULLCHAR || ch == '\n') {
\r
1639 ExitArgError("No value provided for argument", argName);
\r
1643 // Quoting with { }. No characters have to (or can) be escaped.
\r
1644 // Thus the string cannot contain a '}' character.
\r
1664 } else if (ch == '\'' || ch == '"') {
\r
1665 // Quoting with ' ' or " ", with \ as escape character.
\r
1666 // Inconvenient for long strings that may contain Windows filenames.
\r
1683 if (ch == start) {
\r
1692 if (ad->argType == ArgFilename
\r
1693 || ad->argType == ArgSettingsFilename) {
\r
1699 ExitArgError("Incomplete \\ escape in value for", argName);
\r
1723 for (i = 0; i < 3; i++) {
\r
1724 if (ch >= '0' && ch <= '7') {
\r
1725 octval = octval*8 + (ch - '0');
\r
1732 *q++ = (char) octval;
\r
1743 while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {
\r
1750 switch (ad->argType) {
\r
1752 *(int *) ad->argLoc = atoi(argValue);
\r
1756 *(int *) ad->argLoc = atoi(argValue) + boardX; // [HGM] placement: translate stored relative to absolute
\r
1760 *(int *) ad->argLoc = atoi(argValue) + boardY; // (this is really kludgey, it should be done where used...)
\r
1764 *(int *) ad->argLoc = atoi(argValue);
\r
1765 EnsureOnScreen(&boardX, &boardY, minX, minY);
\r
1769 *(float *) ad->argLoc = (float) atof(argValue);
\r
1774 *(char **) ad->argLoc = strdup(argValue);
\r
1777 case ArgSettingsFilename:
\r
1779 char fullname[MSG_SIZ];
\r
1780 if (ParseSettingsFile(argValue, fullname)) {
\r
1781 if (ad->argLoc != NULL) {
\r
1782 *(char **) ad->argLoc = strdup(fullname);
\r
1785 if (ad->argLoc != NULL) {
\r
1787 ExitArgError("Failed to open indirection file", argValue);
\r
1794 switch (argValue[0]) {
\r
1797 *(Boolean *) ad->argLoc = TRUE;
\r
1801 *(Boolean *) ad->argLoc = FALSE;
\r
1804 ExitArgError("Unrecognized boolean argument value", argValue);
\r
1810 *(COLORREF *)ad->argLoc = ParseColorName(argValue);
\r
1813 case ArgAttribs: {
\r
1814 ColorClass cc = (ColorClass)ad->argLoc;
\r
1815 ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);
\r
1819 case ArgBoardSize:
\r
1820 *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);
\r
1824 ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);
\r
1827 case ArgCommSettings:
\r
1828 ParseCommSettings(argValue, &dcb);
\r
1832 ExitArgError("Unrecognized argument", argValue);
\r
1841 LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
\r
1843 HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
\r
1844 lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);
\r
1847 lf->lfEscapement = 0;
\r
1848 lf->lfOrientation = 0;
\r
1849 lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;
\r
1850 lf->lfItalic = mfp->italic;
\r
1851 lf->lfUnderline = mfp->underline;
\r
1852 lf->lfStrikeOut = mfp->strikeout;
\r
1853 lf->lfCharSet = DEFAULT_CHARSET;
\r
1854 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
1855 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
1856 lf->lfQuality = DEFAULT_QUALITY;
\r
1857 lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
\r
1858 strcpy(lf->lfFaceName, mfp->faceName);
\r
1862 CreateFontInMF(MyFont *mf)
\r
1864 LFfromMFP(&mf->lf, &mf->mfp);
\r
1865 if (mf->hf) DeleteObject(mf->hf);
\r
1866 mf->hf = CreateFontIndirect(&mf->lf);
\r
1870 SetDefaultTextAttribs()
\r
1873 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1874 ParseAttribs(&textAttribs[cc].color,
\r
1875 &textAttribs[cc].effects,
\r
1876 defaultTextAttribs[cc]);
\r
1881 SetDefaultSounds()
\r
1885 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1886 textAttribs[cc].sound.name = strdup("");
\r
1887 textAttribs[cc].sound.data = NULL;
\r
1889 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1890 sounds[sc].name = strdup("");
\r
1891 sounds[sc].data = NULL;
\r
1893 sounds[(int)SoundBell].name = strdup(SOUND_BELL);
\r
1901 for (cc = (ColorClass)0; cc < NColorClasses; cc++) {
\r
1902 MyLoadSound(&textAttribs[cc].sound);
\r
1904 for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {
\r
1905 MyLoadSound(&sounds[sc]);
\r
1910 InitAppData(LPSTR lpCmdLine)
\r
1913 char buf[ARG_MAX], currDir[MSG_SIZ];
\r
1916 programName = szAppName;
\r
1918 /* Initialize to defaults */
\r
1919 lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);
\r
1920 darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);
\r
1921 whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);
\r
1922 blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);
\r
1923 highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);
\r
1924 premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);
\r
1925 consoleBackgroundColor = ParseColorName(COLOR_BKGD);
\r
1926 SetDefaultTextAttribs();
\r
1927 SetDefaultSounds();
\r
1928 appData.movesPerSession = MOVES_PER_SESSION;
\r
1929 appData.initString = INIT_STRING;
\r
1930 appData.secondInitString = INIT_STRING;
\r
1931 appData.firstComputerString = COMPUTER_STRING;
\r
1932 appData.secondComputerString = COMPUTER_STRING;
\r
1933 appData.firstChessProgram = FIRST_CHESS_PROGRAM;
\r
1934 appData.secondChessProgram = SECOND_CHESS_PROGRAM;
\r
1935 appData.firstPlaysBlack = FALSE;
\r
1936 appData.noChessProgram = FALSE;
\r
1937 chessProgram = FALSE;
\r
1938 appData.firstHost = FIRST_HOST;
\r
1939 appData.secondHost = SECOND_HOST;
\r
1940 appData.firstDirectory = FIRST_DIRECTORY;
\r
1941 appData.secondDirectory = SECOND_DIRECTORY;
\r
1942 appData.bitmapDirectory = "";
\r
1943 appData.remoteShell = REMOTE_SHELL;
\r
1944 appData.remoteUser = "";
\r
1945 appData.timeDelay = TIME_DELAY;
\r
1946 appData.timeControl = TIME_CONTROL;
\r
1947 appData.timeIncrement = TIME_INCREMENT;
\r
1948 appData.icsActive = FALSE;
\r
1949 appData.icsHost = "";
\r
1950 appData.icsPort = ICS_PORT;
\r
1951 appData.icsCommPort = ICS_COMM_PORT;
\r
1952 appData.icsLogon = ICS_LOGON;
\r
1953 appData.icsHelper = "";
\r
1954 appData.useTelnet = FALSE;
\r
1955 appData.telnetProgram = TELNET_PROGRAM;
\r
1956 appData.gateway = "";
\r
1957 appData.loadGameFile = "";
\r
1958 appData.loadGameIndex = 0;
\r
1959 appData.saveGameFile = "";
\r
1960 appData.autoSaveGames = FALSE;
\r
1961 appData.loadPositionFile = "";
\r
1962 appData.loadPositionIndex = 1;
\r
1963 appData.savePositionFile = "";
\r
1964 appData.matchMode = FALSE;
\r
1965 appData.matchGames = 0;
\r
1966 appData.monoMode = FALSE;
\r
1967 appData.debugMode = FALSE;
\r
1968 appData.clockMode = TRUE;
\r
1969 boardSize = (BoardSize) -1; /* determine by screen size */
\r
1970 appData.Iconic = FALSE; /*unused*/
\r
1971 appData.searchTime = "";
\r
1972 appData.searchDepth = 0;
\r
1973 appData.showCoords = FALSE;
\r
1974 appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/
\r
1975 appData.autoCallFlag = FALSE;
\r
1976 appData.flipView = FALSE;
\r
1977 appData.autoFlipView = TRUE;
\r
1978 appData.cmailGameName = "";
\r
1979 appData.alwaysPromoteToQueen = FALSE;
\r
1980 appData.oldSaveStyle = FALSE;
\r
1981 appData.quietPlay = FALSE;
\r
1982 appData.showThinking = FALSE;
\r
1983 appData.ponderNextMove = TRUE;
\r
1984 appData.periodicUpdates = TRUE;
\r
1985 appData.popupExitMessage = TRUE;
\r
1986 appData.popupMoveErrors = FALSE;
\r
1987 appData.autoObserve = FALSE;
\r
1988 appData.autoComment = FALSE;
\r
1989 appData.animate = TRUE;
\r
1990 appData.animSpeed = 10;
\r
1991 appData.animateDragging = TRUE;
\r
1992 appData.highlightLastMove = TRUE;
\r
1993 appData.getMoveList = TRUE;
\r
1994 appData.testLegality = TRUE;
\r
1995 appData.premove = TRUE;
\r
1996 appData.premoveWhite = FALSE;
\r
1997 appData.premoveWhiteText = "";
\r
1998 appData.premoveBlack = FALSE;
\r
1999 appData.premoveBlackText = "";
\r
2000 appData.icsAlarm = TRUE;
\r
2001 appData.icsAlarmTime = 5000;
\r
2002 appData.autoRaiseBoard = TRUE;
\r
2003 appData.localLineEditing = TRUE;
\r
2004 appData.colorize = TRUE;
\r
2005 appData.reuseFirst = TRUE;
\r
2006 appData.reuseSecond = TRUE;
\r
2007 appData.blindfold = FALSE;
\r
2008 appData.icsEngineAnalyze = FALSE;
\r
2009 memset(&dcb, 0, sizeof(DCB)); // required by VS 2002 +
\r
2010 dcb.DCBlength = sizeof(DCB);
\r
2011 dcb.BaudRate = 9600;
\r
2012 dcb.fBinary = TRUE;
\r
2013 dcb.fParity = FALSE;
\r
2014 dcb.fOutxCtsFlow = FALSE;
\r
2015 dcb.fOutxDsrFlow = FALSE;
\r
2016 dcb.fDtrControl = DTR_CONTROL_ENABLE;
\r
2017 dcb.fDsrSensitivity = FALSE;
\r
2018 dcb.fTXContinueOnXoff = TRUE;
\r
2019 dcb.fOutX = FALSE;
\r
2021 dcb.fNull = FALSE;
\r
2022 dcb.fRtsControl = RTS_CONTROL_ENABLE;
\r
2023 dcb.fAbortOnError = FALSE;
\r
2025 dcb.Parity = SPACEPARITY;
\r
2026 dcb.StopBits = ONESTOPBIT;
\r
2027 settingsFileName = SETTINGS_FILE;
\r
2028 saveSettingsOnExit = TRUE;
\r
2029 boardX = CW_USEDEFAULT;
\r
2030 boardY = CW_USEDEFAULT;
\r
2031 analysisX = CW_USEDEFAULT;
\r
2032 analysisY = CW_USEDEFAULT;
\r
2033 analysisW = CW_USEDEFAULT;
\r
2034 analysisH = CW_USEDEFAULT;
\r
2035 commentX = CW_USEDEFAULT;
\r
2036 commentY = CW_USEDEFAULT;
\r
2037 commentW = CW_USEDEFAULT;
\r
2038 commentH = CW_USEDEFAULT;
\r
2039 editTagsX = CW_USEDEFAULT;
\r
2040 editTagsY = CW_USEDEFAULT;
\r
2041 editTagsW = CW_USEDEFAULT;
\r
2042 editTagsH = CW_USEDEFAULT;
\r
2043 icsTextMenuString = ICS_TEXT_MENU_DEFAULT;
\r
2044 icsNames = ICS_NAMES;
\r
2045 firstChessProgramNames = FCP_NAMES;
\r
2046 secondChessProgramNames = SCP_NAMES;
\r
2047 appData.initialMode = "";
\r
2048 appData.variant = "normal";
\r
2049 appData.firstProtocolVersion = PROTOVER;
\r
2050 appData.secondProtocolVersion = PROTOVER;
\r
2051 appData.showButtonBar = TRUE;
\r
2053 /* [AS] New properties (see comments in header file) */
\r
2054 appData.firstScoreIsAbsolute = FALSE;
\r
2055 appData.secondScoreIsAbsolute = FALSE;
\r
2056 appData.saveExtendedInfoInPGN = FALSE;
\r
2057 appData.hideThinkingFromHuman = FALSE;
\r
2058 appData.liteBackTextureFile = "";
\r
2059 appData.liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
2060 appData.darkBackTextureFile = "";
\r
2061 appData.darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;
\r
2062 appData.renderPiecesWithFont = "";
\r
2063 appData.fontToPieceTable = "";
\r
2064 appData.fontBackColorWhite = 0;
\r
2065 appData.fontForeColorWhite = 0;
\r
2066 appData.fontBackColorBlack = 0;
\r
2067 appData.fontForeColorBlack = 0;
\r
2068 appData.fontPieceSize = 80;
\r
2069 appData.overrideLineGap = 1;
\r
2070 appData.adjudicateLossThreshold = 0;
\r
2071 appData.delayBeforeQuit = 0;
\r
2072 appData.delayAfterQuit = 0;
\r
2073 appData.nameOfDebugFile = "winboard.debug";
\r
2074 appData.pgnEventHeader = "Computer Chess Game";
\r
2075 appData.defaultFrcPosition = -1;
\r
2076 appData.gameListTags = GLT_DEFAULT_TAGS;
\r
2077 appData.saveOutOfBookInfo = TRUE;
\r
2078 appData.showEvalInMoveHistory = TRUE;
\r
2079 appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );
\r
2080 appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );
\r
2081 appData.highlightMoveWithArrow = FALSE;
\r
2082 appData.highlightArrowColor = ParseColorName( "#FFFF80" );
\r
2083 appData.useStickyWindows = TRUE;
\r
2084 appData.adjudicateDrawMoves = 0;
\r
2085 appData.autoDisplayComment = TRUE;
\r
2086 appData.autoDisplayTags = TRUE;
\r
2087 appData.firstIsUCI = FALSE;
\r
2088 appData.secondIsUCI = FALSE;
\r
2089 appData.firstHasOwnBookUCI = TRUE;
\r
2090 appData.secondHasOwnBookUCI = TRUE;
\r
2091 appData.polyglotDir = "";
\r
2092 appData.usePolyglotBook = FALSE;
\r
2093 appData.polyglotBook = "";
\r
2094 appData.defaultHashSize = 64;
\r
2095 appData.defaultCacheSizeEGTB = 4;
\r
2096 appData.defaultPathEGTB = "c:\\egtb";
\r
2097 appData.firstOptions = "";
\r
2098 appData.secondOptions = "";
\r
2100 InitWindowPlacement( &wpGameList );
\r
2101 InitWindowPlacement( &wpMoveHistory );
\r
2102 InitWindowPlacement( &wpEvalGraph );
\r
2103 InitWindowPlacement( &wpEngineOutput );
\r
2104 InitWindowPlacement( &wpConsole );
\r
2106 /* [HGM] User-selectable board size, adjudication control, miscellaneous */
\r
2107 appData.NrFiles = -1;
\r
2108 appData.NrRanks = -1;
\r
2109 appData.holdingsSize = -1;
\r
2110 appData.testClaims = FALSE;
\r
2111 appData.checkMates = FALSE;
\r
2112 appData.materialDraws= FALSE;
\r
2113 appData.trivialDraws = FALSE;
\r
2114 appData.ruleMoves = 51;
\r
2115 appData.drawRepeats = 6;
\r
2116 appData.matchPause = 10000;
\r
2117 appData.alphaRank = FALSE;
\r
2118 appData.allWhite = FALSE;
\r
2119 appData.upsideDown = FALSE;
\r
2120 appData.serverPause = 15;
\r
2121 appData.serverMovesName = NULL;
\r
2122 appData.suppressLoadMoves = FALSE;
\r
2123 appData.firstTimeOdds = 1;
\r
2124 appData.secondTimeOdds = 1;
\r
2125 appData.firstAccumulateTC = 1; // combine previous and current sessions
\r
2126 appData.secondAccumulateTC = 1;
\r
2127 appData.firstNPS = -1; // [HGM] nps: use wall-clock time
\r
2128 appData.secondNPS = -1;
\r
2129 appData.engineComments = 1;
\r
2130 appData.smpCores = 1; // [HGM] SMP: max nr of cores
\r
2131 appData.egtFormats = "";
\r
2134 appData.zippyTalk = ZIPPY_TALK;
\r
2135 appData.zippyPlay = ZIPPY_PLAY;
\r
2136 appData.zippyLines = ZIPPY_LINES;
\r
2137 appData.zippyPinhead = ZIPPY_PINHEAD;
\r
2138 appData.zippyPassword = ZIPPY_PASSWORD;
\r
2139 appData.zippyPassword2 = ZIPPY_PASSWORD2;
\r
2140 appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;
\r
2141 appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;
\r
2142 appData.zippyUseI = ZIPPY_USE_I;
\r
2143 appData.zippyBughouse = ZIPPY_BUGHOUSE;
\r
2144 appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;
\r
2145 appData.zippyGameEnd = ZIPPY_GAME_END;
\r
2146 appData.zippyGameStart = ZIPPY_GAME_START;
\r
2147 appData.zippyAdjourn = ZIPPY_ADJOURN;
\r
2148 appData.zippyAbort = ZIPPY_ABORT;
\r
2149 appData.zippyVariants = ZIPPY_VARIANTS;
\r
2150 appData.zippyMaxGames = ZIPPY_MAX_GAMES;
\r
2151 appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;
\r
2154 /* Point font array elements to structures and
\r
2155 parse default font names */
\r
2156 for (i=0; i<NUM_FONTS; i++) {
\r
2157 for (j=0; j<NUM_SIZES; j++) {
\r
2158 font[j][i] = &fontRec[j][i];
\r
2159 ParseFontName(font[j][i]->def, &font[j][i]->mfp);
\r
2163 /* Parse default settings file if any */
\r
2164 if (ParseSettingsFile(settingsFileName, buf)) {
\r
2165 settingsFileName = strdup(buf);
\r
2168 /* Parse command line */
\r
2169 ParseArgs(StringGet, &lpCmdLine);
\r
2171 /* [HGM] make sure board size is acceptable */
\r
2172 if(appData.NrFiles > BOARD_SIZE ||
\r
2173 appData.NrRanks > BOARD_SIZE )
\r
2174 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
2176 /* [HGM] After parsing the options from the .ini file, and overruling them
\r
2177 * with options from the command line, we now make an even higher priority
\r
2178 * overrule by WB options attached to the engine command line. This so that
\r
2179 * tournament managers can use WB options (such as /timeOdds) that follow
\r
2182 if(appData.firstChessProgram != NULL) {
\r
2183 char *p = StrStr(appData.firstChessProgram, "WBopt");
\r
2184 static char *f = "first";
\r
2185 char buf[MSG_SIZ], *q = buf;
\r
2186 if(p != NULL) { // engine command line contains WinBoard options
\r
2187 sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"
\r
2188 ParseArgs(StringGet, &q);
\r
2189 p[-1] = 0; // cut them offengine command line
\r
2192 // now do same for second chess program
\r
2193 if(appData.secondChessProgram != NULL) {
\r
2194 char *p = StrStr(appData.secondChessProgram, "WBopt");
\r
2195 static char *s = "second";
\r
2196 char buf[MSG_SIZ], *q = buf;
\r
2197 if(p != NULL) { // engine command line contains WinBoard options
\r
2198 sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"
\r
2199 ParseArgs(StringGet, &q);
\r
2200 p[-1] = 0; // cut them offengine command line
\r
2205 /* Propagate options that affect others */
\r
2206 if (appData.matchMode || appData.matchGames) chessProgram = TRUE;
\r
2207 if (appData.icsActive || appData.noChessProgram) {
\r
2208 chessProgram = FALSE; /* not local chess program mode */
\r
2211 /* Open startup dialog if needed */
\r
2212 if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||
\r
2213 (appData.icsActive && *appData.icsHost == NULLCHAR) ||
\r
2214 (chessProgram && (*appData.firstChessProgram == NULLCHAR ||
\r
2215 *appData.secondChessProgram == NULLCHAR))) {
\r
2218 lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);
\r
2219 DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);
\r
2220 FreeProcInstance(lpProc);
\r
2223 /* Make sure save files land in the right (?) directory */
\r
2224 if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {
\r
2225 appData.saveGameFile = strdup(buf);
\r
2227 if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {
\r
2228 appData.savePositionFile = strdup(buf);
\r
2231 /* Finish initialization for fonts and sounds */
\r
2232 for (i=0; i<NUM_FONTS; i++) {
\r
2233 for (j=0; j<NUM_SIZES; j++) {
\r
2234 CreateFontInMF(font[j][i]);
\r
2237 /* xboard, and older WinBoards, controlled the move sound with the
\r
2238 appData.ringBellAfterMoves option. In the current WinBoard, we
\r
2239 always turn the option on (so that the backend will call us),
\r
2240 then let the user turn the sound off by setting it to silence if
\r
2241 desired. To accommodate old winboard.ini files saved by old
\r
2242 versions of WinBoard, we also turn off the sound if the option
\r
2243 was initially set to false. */
\r
2244 if (!appData.ringBellAfterMoves) {
\r
2245 sounds[(int)SoundMove].name = strdup("");
\r
2246 appData.ringBellAfterMoves = TRUE;
\r
2248 GetCurrentDirectory(MSG_SIZ, currDir);
\r
2249 SetCurrentDirectory(installDir);
\r
2251 SetCurrentDirectory(currDir);
\r
2253 p = icsTextMenuString;
\r
2254 if (p[0] == '@') {
\r
2255 FILE* f = fopen(p + 1, "r");
\r
2257 DisplayFatalError(p + 1, errno, 2);
\r
2260 i = fread(buf, 1, sizeof(buf)-1, f);
\r
2262 buf[i] = NULLCHAR;
\r
2265 ParseIcsTextMenu(strdup(p));
\r
2272 HMENU hmenu = GetMenu(hwndMain);
\r
2274 (void) EnableMenuItem(hmenu, IDM_CommPort,
\r
2275 MF_BYCOMMAND|((appData.icsActive &&
\r
2276 *appData.icsCommPort != NULLCHAR) ?
\r
2277 MF_ENABLED : MF_GRAYED));
\r
2278 (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,
\r
2279 MF_BYCOMMAND|(saveSettingsOnExit ?
\r
2280 MF_CHECKED : MF_UNCHECKED));
\r
2285 SaveSettings(char* name)
\r
2288 ArgDescriptor *ad;
\r
2289 WINDOWPLACEMENT wp;
\r
2290 char dir[MSG_SIZ];
\r
2292 if (!hwndMain) return;
\r
2294 GetCurrentDirectory(MSG_SIZ, dir);
\r
2295 SetCurrentDirectory(installDir);
\r
2296 f = fopen(name, "w");
\r
2297 SetCurrentDirectory(dir);
\r
2299 DisplayError(name, errno);
\r
2302 fprintf(f, ";\n");
\r
2303 fprintf(f, "; %s Save Settings file\n", PACKAGE_STRING);
\r
2304 fprintf(f, ";\n");
\r
2305 fprintf(f, "; You can edit the values of options that are already set in this file,\n");
\r
2306 fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");
\r
2307 fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");
\r
2308 fprintf(f, ";\n");
\r
2310 wp.length = sizeof(WINDOWPLACEMENT);
\r
2311 GetWindowPlacement(hwndMain, &wp);
\r
2312 boardX = wp.rcNormalPosition.left;
\r
2313 boardY = wp.rcNormalPosition.top;
\r
2315 if (hwndConsole) {
\r
2316 GetWindowPlacement(hwndConsole, &wp);
\r
2317 wpConsole.x = wp.rcNormalPosition.left;
\r
2318 wpConsole.y = wp.rcNormalPosition.top;
\r
2319 wpConsole.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2320 wpConsole.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2323 if (analysisDialog) {
\r
2324 GetWindowPlacement(analysisDialog, &wp);
\r
2325 analysisX = wp.rcNormalPosition.left;
\r
2326 analysisY = wp.rcNormalPosition.top;
\r
2327 analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2328 analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2331 if (commentDialog) {
\r
2332 GetWindowPlacement(commentDialog, &wp);
\r
2333 commentX = wp.rcNormalPosition.left;
\r
2334 commentY = wp.rcNormalPosition.top;
\r
2335 commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2336 commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2339 if (editTagsDialog) {
\r
2340 GetWindowPlacement(editTagsDialog, &wp);
\r
2341 editTagsX = wp.rcNormalPosition.left;
\r
2342 editTagsY = wp.rcNormalPosition.top;
\r
2343 editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2344 editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2347 if (gameListDialog) {
\r
2348 GetWindowPlacement(gameListDialog, &wp);
\r
2349 wpGameList.x = wp.rcNormalPosition.left;
\r
2350 wpGameList.y = wp.rcNormalPosition.top;
\r
2351 wpGameList.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2352 wpGameList.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2355 /* [AS] Move history */
\r
2356 wpMoveHistory.visible = MoveHistoryIsUp();
\r
2358 if( moveHistoryDialog ) {
\r
2359 GetWindowPlacement(moveHistoryDialog, &wp);
\r
2360 wpMoveHistory.x = wp.rcNormalPosition.left;
\r
2361 wpMoveHistory.y = wp.rcNormalPosition.top;
\r
2362 wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2363 wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2366 /* [AS] Eval graph */
\r
2367 wpEvalGraph.visible = EvalGraphIsUp();
\r
2369 if( evalGraphDialog ) {
\r
2370 GetWindowPlacement(evalGraphDialog, &wp);
\r
2371 wpEvalGraph.x = wp.rcNormalPosition.left;
\r
2372 wpEvalGraph.y = wp.rcNormalPosition.top;
\r
2373 wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2374 wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2377 /* [AS] Engine output */
\r
2378 wpEngineOutput.visible = EngineOutputIsUp();
\r
2380 if( engineOutputDialog ) {
\r
2381 GetWindowPlacement(engineOutputDialog, &wp);
\r
2382 wpEngineOutput.x = wp.rcNormalPosition.left;
\r
2383 wpEngineOutput.y = wp.rcNormalPosition.top;
\r
2384 wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
\r
2385 wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
\r
2388 for (ad = argDescriptors; ad->argName != NULL; ad++) {
\r
2389 if (!ad->save) continue;
\r
2390 switch (ad->argType) {
\r
2393 char *p = *(char **)ad->argLoc;
\r
2394 if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {
\r
2395 /* Quote multiline values or \-containing values
\r
2396 with { } if possible */
\r
2397 fprintf(f, "/%s={%s}\n", ad->argName, p);
\r
2399 /* Else quote with " " */
\r
2400 fprintf(f, "/%s=\"", ad->argName);
\r
2402 if (*p == '\n') fprintf(f, "\n");
\r
2403 else if (*p == '\r') fprintf(f, "\\r");
\r
2404 else if (*p == '\t') fprintf(f, "\\t");
\r
2405 else if (*p == '\b') fprintf(f, "\\b");
\r
2406 else if (*p == '\f') fprintf(f, "\\f");
\r
2407 else if (*p < ' ') fprintf(f, "\\%03o", *p);
\r
2408 else if (*p == '\"') fprintf(f, "\\\"");
\r
2409 else if (*p == '\\') fprintf(f, "\\\\");
\r
2413 fprintf(f, "\"\n");
\r
2419 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);
\r
2422 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardX); // [HGM] placement: stor relative value
\r
2425 fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardY);
\r
2428 fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);
\r
2431 fprintf(f, "/%s=%s\n", ad->argName,
\r
2432 (*(Boolean *)ad->argLoc) ? "true" : "false");
\r
2435 if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2438 if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);
\r
2442 COLORREF color = *(COLORREF *)ad->argLoc;
\r
2443 fprintf(f, "/%s=#%02lx%02lx%02lx\n", ad->argName,
\r
2444 color&0xff, (color>>8)&0xff, (color>>16)&0xff);
\r
2449 MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];
\r
2450 fprintf(f, "/%s=\"%s%s%s%s%s#%02lx%02lx%02lx\"\n", ad->argName,
\r
2451 (ta->effects & CFE_BOLD) ? "b" : "",
\r
2452 (ta->effects & CFE_ITALIC) ? "i" : "",
\r
2453 (ta->effects & CFE_UNDERLINE) ? "u" : "",
\r
2454 (ta->effects & CFE_STRIKEOUT) ? "s" : "",
\r
2455 (ta->effects) ? " " : "",
\r
2456 ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);
\r
2460 if (strchr(*(char **)ad->argLoc, '\"')) {
\r
2461 fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);
\r
2463 fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);
\r
2466 case ArgBoardSize:
\r
2467 fprintf(f, "/%s=%s\n", ad->argName,
\r
2468 sizeInfo[*(BoardSize *)ad->argLoc].name);
\r
2473 for (bs=0; bs<NUM_SIZES; bs++) {
\r
2474 MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;
\r
2475 fprintf(f, "/size=%s ", sizeInfo[bs].name);
\r
2476 fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n",
\r
2477 ad->argName, mfp->faceName, mfp->pointSize,
\r
2478 mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",
\r
2479 mfp->bold ? "b" : "",
\r
2480 mfp->italic ? "i" : "",
\r
2481 mfp->underline ? "u" : "",
\r
2482 mfp->strikeout ? "s" : "");
\r
2486 case ArgCommSettings:
\r
2487 PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);
\r
2489 case ArgSettingsFilename: ;
\r
2497 /*---------------------------------------------------------------------------*\
\r
2499 * GDI board drawing routines
\r
2501 \*---------------------------------------------------------------------------*/
\r
2503 /* [AS] Draw square using background texture */
\r
2504 static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )
\r
2509 return; /* Should never happen! */
\r
2512 SetGraphicsMode( dst, GM_ADVANCED );
\r
2519 /* X reflection */
\r
2524 x.eDx = (FLOAT) dw + dx - 1;
\r
2527 SetWorldTransform( dst, &x );
\r
2530 /* Y reflection */
\r
2536 x.eDy = (FLOAT) dh + dy - 1;
\r
2538 SetWorldTransform( dst, &x );
\r
2546 x.eDx = (FLOAT) dx;
\r
2547 x.eDy = (FLOAT) dy;
\r
2550 SetWorldTransform( dst, &x );
\r
2554 BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );
\r
2562 SetWorldTransform( dst, &x );
\r
2564 ModifyWorldTransform( dst, 0, MWT_IDENTITY );
\r
2567 /* [AS] [HGM] Make room for more piece types, so all pieces can be different */
\r
2569 PM_WP = (int) WhitePawn,
\r
2570 PM_WN = (int) WhiteKnight,
\r
2571 PM_WB = (int) WhiteBishop,
\r
2572 PM_WR = (int) WhiteRook,
\r
2573 PM_WQ = (int) WhiteQueen,
\r
2574 PM_WF = (int) WhiteFerz,
\r
2575 PM_WW = (int) WhiteWazir,
\r
2576 PM_WE = (int) WhiteAlfil,
\r
2577 PM_WM = (int) WhiteMan,
\r
2578 PM_WO = (int) WhiteCannon,
\r
2579 PM_WU = (int) WhiteUnicorn,
\r
2580 PM_WH = (int) WhiteNightrider,
\r
2581 PM_WA = (int) WhiteAngel,
\r
2582 PM_WC = (int) WhiteMarshall,
\r
2583 PM_WAB = (int) WhiteCardinal,
\r
2584 PM_WD = (int) WhiteDragon,
\r
2585 PM_WL = (int) WhiteLance,
\r
2586 PM_WS = (int) WhiteCobra,
\r
2587 PM_WV = (int) WhiteFalcon,
\r
2588 PM_WSG = (int) WhiteSilver,
\r
2589 PM_WG = (int) WhiteGrasshopper,
\r
2590 PM_WK = (int) WhiteKing,
\r
2591 PM_BP = (int) BlackPawn,
\r
2592 PM_BN = (int) BlackKnight,
\r
2593 PM_BB = (int) BlackBishop,
\r
2594 PM_BR = (int) BlackRook,
\r
2595 PM_BQ = (int) BlackQueen,
\r
2596 PM_BF = (int) BlackFerz,
\r
2597 PM_BW = (int) BlackWazir,
\r
2598 PM_BE = (int) BlackAlfil,
\r
2599 PM_BM = (int) BlackMan,
\r
2600 PM_BO = (int) BlackCannon,
\r
2601 PM_BU = (int) BlackUnicorn,
\r
2602 PM_BH = (int) BlackNightrider,
\r
2603 PM_BA = (int) BlackAngel,
\r
2604 PM_BC = (int) BlackMarshall,
\r
2605 PM_BG = (int) BlackGrasshopper,
\r
2606 PM_BAB = (int) BlackCardinal,
\r
2607 PM_BD = (int) BlackDragon,
\r
2608 PM_BL = (int) BlackLance,
\r
2609 PM_BS = (int) BlackCobra,
\r
2610 PM_BV = (int) BlackFalcon,
\r
2611 PM_BSG = (int) BlackSilver,
\r
2612 PM_BK = (int) BlackKing
\r
2615 static HFONT hPieceFont = NULL;
\r
2616 static HBITMAP hPieceMask[(int) EmptySquare];
\r
2617 static HBITMAP hPieceFace[(int) EmptySquare];
\r
2618 static int fontBitmapSquareSize = 0;
\r
2619 static char pieceToFontChar[(int) EmptySquare] =
\r
2620 { 'p', 'n', 'b', 'r', 'q',
\r
2621 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',
\r
2622 'k', 'o', 'm', 'v', 't', 'w',
\r
2623 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',
\r
2626 extern BOOL SetCharTable( char *table, const char * map );
\r
2627 /* [HGM] moved to backend.c */
\r
2629 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )
\r
2632 BYTE r1 = GetRValue( color );
\r
2633 BYTE g1 = GetGValue( color );
\r
2634 BYTE b1 = GetBValue( color );
\r
2640 /* Create a uniform background first */
\r
2641 hbrush = CreateSolidBrush( color );
\r
2642 SetRect( &rc, 0, 0, squareSize, squareSize );
\r
2643 FillRect( hdc, &rc, hbrush );
\r
2644 DeleteObject( hbrush );
\r
2647 /* Vertical gradient, good for pawn, knight and rook, less for queen and king */
\r
2648 int steps = squareSize / 2;
\r
2651 for( i=0; i<steps; i++ ) {
\r
2652 BYTE r = r1 - (r1-r2) * i / steps;
\r
2653 BYTE g = g1 - (g1-g2) * i / steps;
\r
2654 BYTE b = b1 - (b1-b2) * i / steps;
\r
2656 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2657 SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );
\r
2658 FillRect( hdc, &rc, hbrush );
\r
2659 DeleteObject(hbrush);
\r
2662 else if( mode == 2 ) {
\r
2663 /* Diagonal gradient, good more or less for every piece */
\r
2664 POINT triangle[3];
\r
2665 HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );
\r
2666 HBRUSH hbrush_old;
\r
2667 int steps = squareSize;
\r
2670 triangle[0].x = squareSize - steps;
\r
2671 triangle[0].y = squareSize;
\r
2672 triangle[1].x = squareSize;
\r
2673 triangle[1].y = squareSize;
\r
2674 triangle[2].x = squareSize;
\r
2675 triangle[2].y = squareSize - steps;
\r
2677 for( i=0; i<steps; i++ ) {
\r
2678 BYTE r = r1 - (r1-r2) * i / steps;
\r
2679 BYTE g = g1 - (g1-g2) * i / steps;
\r
2680 BYTE b = b1 - (b1-b2) * i / steps;
\r
2682 hbrush = CreateSolidBrush( RGB(r,g,b) );
\r
2683 hbrush_old = SelectObject( hdc, hbrush );
\r
2684 Polygon( hdc, triangle, 3 );
\r
2685 SelectObject( hdc, hbrush_old );
\r
2686 DeleteObject(hbrush);
\r
2691 SelectObject( hdc, hpen );
\r
2696 [AS] The method I use to create the bitmaps it a bit tricky, but it
\r
2697 seems to work ok. The main problem here is to find the "inside" of a chess
\r
2698 piece: follow the steps as explained below.
\r
2700 static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
\r
2704 COLORREF chroma = RGB(0xFF,0x00,0xFF);
\r
2708 int backColor = whitePieceColor;
\r
2709 int foreColor = blackPieceColor;
\r
2711 if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {
\r
2712 backColor = appData.fontBackColorWhite;
\r
2713 foreColor = appData.fontForeColorWhite;
\r
2715 else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {
\r
2716 backColor = appData.fontBackColorBlack;
\r
2717 foreColor = appData.fontForeColorBlack;
\r
2721 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2723 hbm_old = SelectObject( hdc, hbm );
\r
2727 rc.right = squareSize;
\r
2728 rc.bottom = squareSize;
\r
2730 /* Step 1: background is now black */
\r
2731 FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );
\r
2733 GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );
\r
2735 pt.x = (squareSize - sz.cx) / 2;
\r
2736 pt.y = (squareSize - sz.cy) / 2;
\r
2738 SetBkMode( hdc, TRANSPARENT );
\r
2739 SetTextColor( hdc, chroma );
\r
2740 /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */
\r
2741 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2743 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
\r
2744 /* Step 3: the area outside the piece is filled with white */
\r
2745 // FloodFill( hdc, 0, 0, chroma );
\r
2746 ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );
\r
2747 ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big
\r
2748 ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );
\r
2749 ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );
\r
2750 SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
\r
2752 Step 4: this is the tricky part, the area inside the piece is filled with black,
\r
2753 but if the start point is not inside the piece we're lost!
\r
2754 There should be a better way to do this... if we could create a region or path
\r
2755 from the fill operation we would be fine for example.
\r
2757 // FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );
\r
2758 ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );
\r
2760 { /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */
\r
2761 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2762 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2764 SelectObject( dc2, bm2 );
\r
2765 BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy
\r
2766 BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2767 BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2768 BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2769 BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );
\r
2772 DeleteObject( bm2 );
\r
2775 SetTextColor( hdc, 0 );
\r
2777 Step 5: some fonts have "disconnected" areas that are skipped by the fill:
\r
2778 draw the piece again in black for safety.
\r
2780 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2782 SelectObject( hdc, hbm_old );
\r
2784 if( hPieceMask[index] != NULL ) {
\r
2785 DeleteObject( hPieceMask[index] );
\r
2788 hPieceMask[index] = hbm;
\r
2791 hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2793 SelectObject( hdc, hbm );
\r
2796 HDC dc1 = CreateCompatibleDC( hdc_window );
\r
2797 HDC dc2 = CreateCompatibleDC( hdc_window );
\r
2798 HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );
\r
2800 SelectObject( dc1, hPieceMask[index] );
\r
2801 SelectObject( dc2, bm2 );
\r
2802 FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );
\r
2803 BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );
\r
2806 Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves
\r
2807 the piece background and deletes (makes transparent) the rest.
\r
2808 Thanks to that mask, we are free to paint the background with the greates
\r
2809 freedom, as we'll be able to mask off the unwanted parts when finished.
\r
2810 We use this, to make gradients and give the pieces a "roundish" look.
\r
2812 SetPieceBackground( hdc, backColor, 2 );
\r
2813 BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );
\r
2817 DeleteObject( bm2 );
\r
2820 SetTextColor( hdc, foreColor );
\r
2821 TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );
\r
2823 SelectObject( hdc, hbm_old );
\r
2825 if( hPieceFace[index] != NULL ) {
\r
2826 DeleteObject( hPieceFace[index] );
\r
2829 hPieceFace[index] = hbm;
\r
2832 static int TranslatePieceToFontPiece( int piece )
\r
2862 case BlackMarshall:
\r
2866 case BlackNightrider:
\r
2872 case BlackUnicorn:
\r
2876 case BlackGrasshopper:
\r
2888 case BlackCardinal:
\r
2895 case WhiteMarshall:
\r
2899 case WhiteNightrider:
\r
2905 case WhiteUnicorn:
\r
2909 case WhiteGrasshopper:
\r
2921 case WhiteCardinal:
\r
2930 void CreatePiecesFromFont()
\r
2933 HDC hdc_window = NULL;
\r
2939 if( fontBitmapSquareSize < 0 ) {
\r
2940 /* Something went seriously wrong in the past: do not try to recreate fonts! */
\r
2944 if( appData.renderPiecesWithFont == NULL || appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {
\r
2945 fontBitmapSquareSize = -1;
\r
2949 if( fontBitmapSquareSize != squareSize ) {
\r
2950 hdc_window = GetDC( hwndMain );
\r
2951 hdc = CreateCompatibleDC( hdc_window );
\r
2953 if( hPieceFont != NULL ) {
\r
2954 DeleteObject( hPieceFont );
\r
2957 for( i=0; i<=(int)BlackKing; i++ ) {
\r
2958 hPieceMask[i] = NULL;
\r
2959 hPieceFace[i] = NULL;
\r
2965 if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {
\r
2966 fontHeight = appData.fontPieceSize;
\r
2969 fontHeight = (fontHeight * squareSize) / 100;
\r
2971 lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
\r
2973 lf.lfEscapement = 0;
\r
2974 lf.lfOrientation = 0;
\r
2975 lf.lfWeight = FW_NORMAL;
\r
2977 lf.lfUnderline = 0;
\r
2978 lf.lfStrikeOut = 0;
\r
2979 lf.lfCharSet = DEFAULT_CHARSET;
\r
2980 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
2981 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
2982 lf.lfQuality = PROOF_QUALITY;
\r
2983 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
\r
2984 strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );
\r
2985 lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';
\r
2987 hPieceFont = CreateFontIndirect( &lf );
\r
2989 if( hPieceFont == NULL ) {
\r
2990 fontBitmapSquareSize = -2;
\r
2993 /* Setup font-to-piece character table */
\r
2994 if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {
\r
2995 /* No (or wrong) global settings, try to detect the font */
\r
2996 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {
\r
2998 SetCharTable(pieceToFontChar, "phbrqkojntwl");
\r
3000 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {
\r
3001 /* DiagramTT* family */
\r
3002 SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");
\r
3004 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {
\r
3005 /* Fairy symbols */
\r
3006 SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
\r
3008 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {
\r
3009 /* Good Companion (Some characters get warped as literal :-( */
\r
3010 char s[] = "1cmWG0ñueOS¯®oYI23wgQU";
\r
3011 s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;
\r
3012 SetCharTable(pieceToFontChar, s);
\r
3015 /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */
\r
3016 SetCharTable(pieceToFontChar, "pnbrqkomvtwl");
\r
3020 /* Create bitmaps */
\r
3021 hfont_old = SelectObject( hdc, hPieceFont );
\r
3023 CreatePieceMaskFromFont( hdc_window, hdc, PM_WP );
\r
3024 CreatePieceMaskFromFont( hdc_window, hdc, PM_WN );
\r
3025 CreatePieceMaskFromFont( hdc_window, hdc, PM_WB );
\r
3026 CreatePieceMaskFromFont( hdc_window, hdc, PM_WR );
\r
3027 CreatePieceMaskFromFont( hdc_window, hdc, PM_WQ );
\r
3028 CreatePieceMaskFromFont( hdc_window, hdc, PM_WK );
\r
3029 CreatePieceMaskFromFont( hdc_window, hdc, PM_BP );
\r
3030 CreatePieceMaskFromFont( hdc_window, hdc, PM_BN );
\r
3031 CreatePieceMaskFromFont( hdc_window, hdc, PM_BB );
\r
3032 CreatePieceMaskFromFont( hdc_window, hdc, PM_BR );
\r
3033 CreatePieceMaskFromFont( hdc_window, hdc, PM_BQ );
\r
3034 CreatePieceMaskFromFont( hdc_window, hdc, PM_BK );
\r
3036 CreatePieceMaskFromFont( hdc_window, hdc, PM_WA );
\r
3037 CreatePieceMaskFromFont( hdc_window, hdc, PM_WC );
\r
3038 CreatePieceMaskFromFont( hdc_window, hdc, PM_WF );
\r
3039 CreatePieceMaskFromFont( hdc_window, hdc, PM_WH );
\r
3040 CreatePieceMaskFromFont( hdc_window, hdc, PM_WE );
\r
3041 CreatePieceMaskFromFont( hdc_window, hdc, PM_WW );
\r
3042 CreatePieceMaskFromFont( hdc_window, hdc, PM_WU );
\r
3043 CreatePieceMaskFromFont( hdc_window, hdc, PM_WO );
\r
3044 CreatePieceMaskFromFont( hdc_window, hdc, PM_WG );
\r
3045 CreatePieceMaskFromFont( hdc_window, hdc, PM_WM );
\r
3046 CreatePieceMaskFromFont( hdc_window, hdc, PM_WSG );
\r
3047 CreatePieceMaskFromFont( hdc_window, hdc, PM_WV );
\r
3048 CreatePieceMaskFromFont( hdc_window, hdc, PM_WAB );
\r
3049 CreatePieceMaskFromFont( hdc_window, hdc, PM_WD );
\r
3050 CreatePieceMaskFromFont( hdc_window, hdc, PM_WL );
\r
3051 CreatePieceMaskFromFont( hdc_window, hdc, PM_WS );
\r
3052 CreatePieceMaskFromFont( hdc_window, hdc, PM_BA );
\r
3053 CreatePieceMaskFromFont( hdc_window, hdc, PM_BC );
\r
3054 CreatePieceMaskFromFont( hdc_window, hdc, PM_BF );
\r
3055 CreatePieceMaskFromFont( hdc_window, hdc, PM_BH );
\r
3056 CreatePieceMaskFromFont( hdc_window, hdc, PM_BE );
\r
3057 CreatePieceMaskFromFont( hdc_window, hdc, PM_BW );
\r
3058 CreatePieceMaskFromFont( hdc_window, hdc, PM_BU );
\r
3059 CreatePieceMaskFromFont( hdc_window, hdc, PM_BO );
\r
3060 CreatePieceMaskFromFont( hdc_window, hdc, PM_BG );
\r
3061 CreatePieceMaskFromFont( hdc_window, hdc, PM_BM );
\r
3062 CreatePieceMaskFromFont( hdc_window, hdc, PM_BSG );
\r
3063 CreatePieceMaskFromFont( hdc_window, hdc, PM_BV );
\r
3064 CreatePieceMaskFromFont( hdc_window, hdc, PM_BAB );
\r
3065 CreatePieceMaskFromFont( hdc_window, hdc, PM_BD );
\r
3066 CreatePieceMaskFromFont( hdc_window, hdc, PM_BL );
\r
3067 CreatePieceMaskFromFont( hdc_window, hdc, PM_BS );
\r
3069 for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */
\r
3070 if(PieceToChar((ChessSquare)i) != '.') /* skip unused pieces */
\r
3071 CreatePieceMaskFromFont( hdc_window, hdc, i );
\r
3073 SelectObject( hdc, hfont_old );
\r
3075 fontBitmapSquareSize = squareSize;
\r
3079 if( hdc != NULL ) {
\r
3083 if( hdc_window != NULL ) {
\r
3084 ReleaseDC( hwndMain, hdc_window );
\r
3089 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)
\r
3093 sprintf(name, "%s%d%s", piece, squareSize, suffix);
\r
3094 if (gameInfo.event &&
\r
3095 strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&
\r
3096 strcmp(name, "k80s") == 0) {
\r
3097 strcpy(name, "tim");
\r
3099 return LoadBitmap(hinst, name);
\r
3103 /* Insert a color into the program's logical palette
\r
3104 structure. This code assumes the given color is
\r
3105 the result of the RGB or PALETTERGB macro, and it
\r
3106 knows how those macros work (which is documented).
\r
3109 InsertInPalette(COLORREF color)
\r
3111 LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);
\r
3113 if (pLogPal->palNumEntries++ >= PALETTESIZE) {
\r
3114 DisplayFatalError("Too many colors", 0, 1);
\r
3115 pLogPal->palNumEntries--;
\r
3119 pe->peFlags = (char) 0;
\r
3120 pe->peRed = (char) (0xFF & color);
\r
3121 pe->peGreen = (char) (0xFF & (color >> 8));
\r
3122 pe->peBlue = (char) (0xFF & (color >> 16));
\r
3128 InitDrawingColors()
\r
3130 if (pLogPal == NULL) {
\r
3131 /* Allocate enough memory for a logical palette with
\r
3132 * PALETTESIZE entries and set the size and version fields
\r
3133 * of the logical palette structure.
\r
3135 pLogPal = (NPLOGPALETTE)
\r
3136 LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +
\r
3137 (sizeof(PALETTEENTRY) * (PALETTESIZE))));
\r
3138 pLogPal->palVersion = 0x300;
\r
3140 pLogPal->palNumEntries = 0;
\r
3142 InsertInPalette(lightSquareColor);
\r
3143 InsertInPalette(darkSquareColor);
\r
3144 InsertInPalette(whitePieceColor);
\r
3145 InsertInPalette(blackPieceColor);
\r
3146 InsertInPalette(highlightSquareColor);
\r
3147 InsertInPalette(premoveHighlightColor);
\r
3149 /* create a logical color palette according the information
\r
3150 * in the LOGPALETTE structure.
\r
3152 hPal = CreatePalette((LPLOGPALETTE) pLogPal);
\r
3154 lightSquareBrush = CreateSolidBrush(lightSquareColor);
\r
3155 blackSquareBrush = CreateSolidBrush(blackPieceColor);
\r
3156 darkSquareBrush = CreateSolidBrush(darkSquareColor);
\r
3157 whitePieceBrush = CreateSolidBrush(whitePieceColor);
\r
3158 blackPieceBrush = CreateSolidBrush(blackPieceColor);
\r
3159 iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
\r
3160 explodeBrush = CreateSolidBrush(highlightSquareColor); // [HGM] atomic
\r
3161 /* [AS] Force rendering of the font-based pieces */
\r
3162 if( fontBitmapSquareSize > 0 ) {
\r
3163 fontBitmapSquareSize = 0;
\r
3169 BoardWidth(int boardSize, int n)
\r
3170 { /* [HGM] argument n added to allow different width and height */
\r
3171 int lineGap = sizeInfo[boardSize].lineGap;
\r
3173 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3174 lineGap = appData.overrideLineGap;
\r
3177 return (n + 1) * lineGap +
\r
3178 n * sizeInfo[boardSize].squareSize;
\r
3181 /* Respond to board resize by dragging edge */
\r
3183 ResizeBoard(int newSizeX, int newSizeY, int flags)
\r
3185 BoardSize newSize = NUM_SIZES - 1;
\r
3186 static int recurse = 0;
\r
3187 if (IsIconic(hwndMain)) return;
\r
3188 if (recurse > 0) return;
\r
3190 while (newSize > 0) {
\r
3191 InitDrawingSizes(newSize+1000, 0); // [HGM] kludge to update sizeInfo without visible effects
\r
3192 if(newSizeX >= sizeInfo[newSize].cliWidth &&
\r
3193 newSizeY >= sizeInfo[newSize].cliHeight) break;
\r
3196 boardSize = newSize;
\r
3197 InitDrawingSizes(boardSize, flags);
\r
3204 InitDrawingSizes(BoardSize boardSize, int flags)
\r
3206 int i, boardWidth, boardHeight; /* [HGM] height treated separately */
\r
3207 ChessSquare piece;
\r
3208 static int oldBoardSize = -1, oldTinyLayout = 0;
\r
3210 SIZE clockSize, messageSize;
\r
3212 char buf[MSG_SIZ];
\r
3214 HMENU hmenu = GetMenu(hwndMain);
\r
3215 RECT crect, wrect, oldRect;
\r
3217 LOGBRUSH logbrush;
\r
3219 int suppressVisibleEffects = 0; // [HGM] kludge to request updating sizeInfo only
\r
3220 if((int)boardSize >= 1000 ) { boardSize -= 1000; suppressVisibleEffects = 1; }
\r
3222 /* [HGM] call with -2 uses old size (for if nr of files, ranks changes) */
\r
3223 if(boardSize == (BoardSize)(-2) ) boardSize = oldBoardSize;
\r
3225 oldRect.left = boardX; //[HGM] placement: remember previous window params
\r
3226 oldRect.top = boardY;
\r
3227 oldRect.right = boardX + winWidth;
\r
3228 oldRect.bottom = boardY + winHeight;
\r
3230 tinyLayout = sizeInfo[boardSize].tinyLayout;
\r
3231 smallLayout = sizeInfo[boardSize].smallLayout;
\r
3232 squareSize = sizeInfo[boardSize].squareSize;
\r
3233 lineGap = sizeInfo[boardSize].lineGap;
\r
3234 minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted */
\r
3236 if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {
\r
3237 lineGap = appData.overrideLineGap;
\r
3240 if (tinyLayout != oldTinyLayout) {
\r
3241 long style = GetWindowLong(hwndMain, GWL_STYLE);
\r
3243 style &= ~WS_SYSMENU;
\r
3244 InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize,
\r
3245 "&Minimize\tCtrl+F4");
\r
3247 style |= WS_SYSMENU;
\r
3248 RemoveMenu(hmenu, IDM_Minimize, MF_BYCOMMAND);
\r
3250 SetWindowLong(hwndMain, GWL_STYLE, style);
\r
3252 for (i=0; menuBarText[tinyLayout][i]; i++) {
\r
3253 ModifyMenu(hmenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP,
\r
3254 (UINT)GetSubMenu(hmenu, i), menuBarText[tinyLayout][i]);
\r
3256 DrawMenuBar(hwndMain);
\r
3259 boardWidth = BoardWidth(boardSize, BOARD_WIDTH);
\r
3260 boardHeight = BoardWidth(boardSize, BOARD_HEIGHT);
\r
3262 /* Get text area sizes */
\r
3263 hdc = GetDC(hwndMain);
\r
3264 if (appData.clockMode) {
\r
3265 sprintf(buf, "White: %s", TimeString(23*60*60*1000L));
\r
3267 sprintf(buf, "White");
\r
3269 oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);
\r
3270 GetTextExtentPoint(hdc, buf, strlen(buf), &clockSize);
\r
3271 SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);
\r
3272 str = "We only care about the height here";
\r
3273 GetTextExtentPoint(hdc, str, strlen(str), &messageSize);
\r
3274 SelectObject(hdc, oldFont);
\r
3275 ReleaseDC(hwndMain, hdc);
\r
3277 /* Compute where everything goes */
\r
3278 if((first.programLogo || second.programLogo) && !tinyLayout) {
\r
3279 /* [HGM] logo: if either logo is on, reserve space for it */
\r
3280 logoHeight = 2*clockSize.cy;
\r
3281 leftLogoRect.left = OUTER_MARGIN;
\r
3282 leftLogoRect.right = leftLogoRect.left + 4*clockSize.cy;
\r
3283 leftLogoRect.top = OUTER_MARGIN;
\r
3284 leftLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3286 rightLogoRect.right = OUTER_MARGIN + boardWidth;
\r
3287 rightLogoRect.left = rightLogoRect.right - 4*clockSize.cy;
\r
3288 rightLogoRect.top = OUTER_MARGIN;
\r
3289 rightLogoRect.bottom = OUTER_MARGIN + logoHeight;
\r
3292 whiteRect.left = leftLogoRect.right;
\r
3293 whiteRect.right = OUTER_MARGIN + boardWidth/2 - INNER_MARGIN/2;
\r
3294 whiteRect.top = OUTER_MARGIN;
\r
3295 whiteRect.bottom = whiteRect.top + logoHeight;
\r
3297 blackRect.right = rightLogoRect.left;
\r
3298 blackRect.left = whiteRect.right + INNER_MARGIN;
\r
3299 blackRect.top = whiteRect.top;
\r
3300 blackRect.bottom = whiteRect.bottom;
\r
3302 whiteRect.left = OUTER_MARGIN;
\r
3303 whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2;
\r
3304 whiteRect.top = OUTER_MARGIN;
\r
3305 whiteRect.bottom = whiteRect.top + clockSize.cy;
\r
3307 blackRect.left = whiteRect.right + INNER_MARGIN;
\r
3308 blackRect.right = blackRect.left + boardWidth/2 - 1;
\r
3309 blackRect.top = whiteRect.top;
\r
3310 blackRect.bottom = whiteRect.bottom;
\r
3313 messageRect.left = OUTER_MARGIN + MESSAGE_LINE_LEFTMARGIN;
\r
3314 if (appData.showButtonBar) {
\r
3315 messageRect.right = OUTER_MARGIN + boardWidth // [HGM] logo: expressed independent of clock placement
\r
3316 - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN;
\r
3318 messageRect.right = OUTER_MARGIN + boardWidth;
\r
3320 messageRect.top = whiteRect.bottom + INNER_MARGIN;
\r
3321 messageRect.bottom = messageRect.top + messageSize.cy;
\r
3323 boardRect.left = OUTER_MARGIN;
\r
3324 boardRect.right = boardRect.left + boardWidth;
\r
3325 boardRect.top = messageRect.bottom + INNER_MARGIN;
\r
3326 boardRect.bottom = boardRect.top + boardHeight;
\r
3328 sizeInfo[boardSize].cliWidth = boardRect.right + OUTER_MARGIN;
\r
3329 sizeInfo[boardSize].cliHeight = boardRect.bottom + OUTER_MARGIN;
\r
3330 oldBoardSize = boardSize;
\r
3331 oldTinyLayout = tinyLayout;
\r
3332 winW = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN;
\r
3333 winH = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) +
\r
3334 GetSystemMetrics(SM_CYCAPTION) + boardRect.bottom + OUTER_MARGIN;
\r
3335 if(suppressVisibleEffects) return; // [HGM] when called for filling sizeInfo only
\r
3336 winWidth = winW; // [HGM] placement: set through temporary which can used by initial sizing choice
\r
3337 winHeight = winH; // without disturbing window attachments
\r
3338 GetWindowRect(hwndMain, &wrect);
\r
3339 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3340 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3342 // [HGM] placement: let attached windows follow size change.
\r
3343 ReattachAfterSize( &oldRect, winWidth, winHeight, moveHistoryDialog, &wpMoveHistory );
\r
3344 ReattachAfterSize( &oldRect, winWidth, winHeight, evalGraphDialog, &wpEvalGraph );
\r
3345 ReattachAfterSize( &oldRect, winWidth, winHeight, engineOutputDialog, &wpEngineOutput );
\r
3346 ReattachAfterSize( &oldRect, winWidth, winHeight, gameListDialog, &wpGameList );
\r
3347 ReattachAfterSize( &oldRect, winWidth, winHeight, hwndConsole, &wpConsole );
\r
3349 /* compensate if menu bar wrapped */
\r
3350 GetClientRect(hwndMain, &crect);
\r
3351 offby = boardRect.bottom + OUTER_MARGIN - crect.bottom;
\r
3352 winHeight += offby;
\r
3354 case WMSZ_TOPLEFT:
\r
3355 SetWindowPos(hwndMain, NULL,
\r
3356 wrect.right - winWidth, wrect.bottom - winHeight,
\r
3357 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3360 case WMSZ_TOPRIGHT:
\r
3362 SetWindowPos(hwndMain, NULL,
\r
3363 wrect.left, wrect.bottom - winHeight,
\r
3364 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3367 case WMSZ_BOTTOMLEFT:
\r
3369 SetWindowPos(hwndMain, NULL,
\r
3370 wrect.right - winWidth, wrect.top,
\r
3371 winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);
\r
3374 case WMSZ_BOTTOMRIGHT:
\r
3378 SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,
\r
3379 SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);
\r
3384 for (i = 0; i < N_BUTTONS; i++) {
\r
3385 if (buttonDesc[i].hwnd != NULL) {
\r
3386 DestroyWindow(buttonDesc[i].hwnd);
\r
3387 buttonDesc[i].hwnd = NULL;
\r
3389 if (appData.showButtonBar) {
\r
3390 buttonDesc[i].hwnd =
\r
3391 CreateWindow("BUTTON", buttonDesc[i].label,
\r
3392 WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
\r
3393 boardRect.right - BUTTON_WIDTH*(N_BUTTONS-i),
\r
3394 messageRect.top, BUTTON_WIDTH, messageSize.cy, hwndMain,
\r
3395 (HMENU) buttonDesc[i].id,
\r
3396 (HINSTANCE) GetWindowLong(hwndMain, GWL_HINSTANCE), NULL);
\r
3398 SendMessage(buttonDesc[i].hwnd, WM_SETFONT,
\r
3399 (WPARAM)font[boardSize][MESSAGE_FONT]->hf,
\r
3400 MAKELPARAM(FALSE, 0));
\r
3402 if (buttonDesc[i].id == IDM_Pause)
\r
3403 hwndPause = buttonDesc[i].hwnd;
\r
3404 buttonDesc[i].wndproc = (WNDPROC)
\r
3405 SetWindowLong(buttonDesc[i].hwnd, GWL_WNDPROC, (LONG) ButtonProc);
\r
3408 if (gridPen != NULL) DeleteObject(gridPen);
\r
3409 if (highlightPen != NULL) DeleteObject(highlightPen);
\r
3410 if (premovePen != NULL) DeleteObject(premovePen);
\r
3411 if (lineGap != 0) {
\r
3412 logbrush.lbStyle = BS_SOLID;
\r
3413 logbrush.lbColor = RGB(0, 0, 0); /* grid pen color = black */
\r
3415 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3416 lineGap, &logbrush, 0, NULL);
\r
3417 logbrush.lbColor = highlightSquareColor;
\r
3419 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3420 lineGap, &logbrush, 0, NULL);
\r
3422 logbrush.lbColor = premoveHighlightColor;
\r
3424 ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
\r
3425 lineGap, &logbrush, 0, NULL);
\r
3427 /* [HGM] Loop had to be split in part for vert. and hor. lines */
\r
3428 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
\r
3429 gridEndpoints[i*2].x = boardRect.left + lineGap / 2;
\r
3430 gridEndpoints[i*2].y = gridEndpoints[i*2 + 1].y =
\r
3431 boardRect.top + lineGap / 2 + (i * (squareSize + lineGap));
\r
3432 gridEndpoints[i*2 + 1].x = boardRect.left + lineGap / 2 +
\r
3433 BOARD_WIDTH * (squareSize + lineGap);
\r
3434 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3436 for (i = 0; i < BOARD_WIDTH + 1; i++) {
\r
3437 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].y = boardRect.top + lineGap / 2;
\r
3438 gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].x =
\r
3439 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].x = boardRect.left +
\r
3440 lineGap / 2 + (i * (squareSize + lineGap));
\r
3441 gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].y =
\r
3442 boardRect.top + BOARD_HEIGHT * (squareSize + lineGap);
\r
3443 gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;
\r
3447 /* [HGM] Licensing requirement */
\r
3449 if(gameInfo.variant == VariantGothic) GothicPopUp( GOTHIC, VariantGothic); else
\r
3452 if(gameInfo.variant == VariantFalcon) GothicPopUp( FALCON, VariantFalcon); else
\r
3454 GothicPopUp( "", VariantNormal);
\r
3457 /* if (boardSize == oldBoardSize) return; [HGM] variant might have changed */
\r
3459 /* Load piece bitmaps for this board size */
\r
3460 for (i=0; i<=2; i++) {
\r
3461 for (piece = WhitePawn;
\r
3462 (int) piece < (int) BlackPawn;
\r
3463 piece = (ChessSquare) ((int) piece + 1)) {
\r
3464 if (pieceBitmap[i][piece] != NULL)
\r
3465 DeleteObject(pieceBitmap[i][piece]);
\r
3469 fontBitmapSquareSize = 0; /* [HGM] render: make sure pieces will be recreated, as we might need others now */
\r
3470 // Orthodox Chess pieces
\r
3471 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s");
\r
3472 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s");
\r
3473 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "s");
\r
3474 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "s");
\r
3475 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "s");
\r
3476 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "o");
\r
3477 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "o");
\r
3478 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "o");
\r
3479 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "o");
\r
3480 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "o");
\r
3481 pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "w");
\r
3482 pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "w");
\r
3483 pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "w");
\r
3484 pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w");
\r
3485 pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w");
\r
3486 if( !strcmp(appData.variant, "shogi") && (squareSize==72 || squareSize==49)) {
\r
3487 // in Shogi, Hijack the unused Queen for Lance
\r
3488 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3489 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3490 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3492 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s");
\r
3493 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o");
\r
3494 pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w");
\r
3497 if(squareSize <= 72 && squareSize >= 33) {
\r
3498 /* A & C are available in most sizes now */
\r
3499 if(squareSize != 49 && squareSize != 72 && squareSize != 33) { // Vortex-like
\r
3500 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3501 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3502 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3503 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3504 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3505 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3506 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3507 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3508 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3509 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3510 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3511 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3512 } else { // Smirf-like
\r
3513 pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "s");
\r
3514 pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "o");
\r
3515 pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "w");
\r
3517 if(gameInfo.variant == VariantGothic) { // Vortex-like
\r
3518 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3519 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3520 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3521 } else { // WinBoard standard
\r
3522 pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s");
\r
3523 pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o");
\r
3524 pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "w");
\r
3529 if(squareSize==72 || squareSize==49 || squareSize==33) { /* experiment with some home-made bitmaps */
\r
3530 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "s");
\r
3531 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "o");
\r
3532 pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "w");
\r
3533 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "s");
\r
3534 pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "o");
\r
3535 pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3536 pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "s");
\r
3537 pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "o");
\r
3538 pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "w");
\r
3539 pieceBitmap[0][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "s");
\r
3540 pieceBitmap[1][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "o");
\r
3541 pieceBitmap[2][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "w");
\r
3542 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "s");
\r
3543 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "o");
\r
3544 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "w");
\r
3545 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "s");
\r
3546 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "o");
\r
3547 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "w");
\r
3548 pieceBitmap[0][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "s");
\r
3549 pieceBitmap[1][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "o");
\r
3550 pieceBitmap[2][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "w");
\r
3551 pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "s");
\r
3552 pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "o");
\r
3553 pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "w");
\r
3554 pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");
\r
3555 pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");
\r
3556 pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");
\r
3557 pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s");
\r
3558 pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o");
\r
3559 pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w");
\r
3561 if(gameInfo.variant == VariantShogi) { /* promoted Gold represemtations */
\r
3562 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s");
\r
3563 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "o");
\r
3564 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3565 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "s");
\r
3566 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "o");
\r
3567 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3568 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "s");
\r
3569 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "o");
\r
3570 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3571 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "s");
\r
3572 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "o");
\r
3573 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "w", squareSize, "w");
\r
3575 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "s");
\r
3576 pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "o");
\r
3577 pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "w");
\r
3578 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "s");
\r
3579 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "o");
\r
3580 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "w");
\r
3581 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");
\r
3582 pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");
\r
3583 pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");
\r
3584 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "s");
\r
3585 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "o");
\r
3586 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "w");
\r
3589 } else { /* other size, no special bitmaps available. Use smaller symbols */
\r
3590 if((int)boardSize < 2) minorSize = sizeInfo[0].squareSize;
\r
3591 else minorSize = sizeInfo[(int)boardSize - 2].squareSize;
\r
3592 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "s");
\r
3593 pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "o");
\r
3594 pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "w");
\r
3595 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "s");
\r
3596 pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "o");
\r
3597 pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "w");
\r
3598 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "s");
\r
3599 pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "o");
\r
3600 pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "r", minorSize, "w");
\r
3601 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "s");
\r
3602 pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "o");
\r
3603 pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "w");
\r
3607 if(gameInfo.variant == VariantShogi && squareSize == 58)
\r
3608 /* special Shogi support in this size */
\r
3609 { for (i=0; i<=2; i++) { /* replace all bitmaps */
\r
3610 for (piece = WhitePawn;
\r
3611 (int) piece < (int) BlackPawn;
\r
3612 piece = (ChessSquare) ((int) piece + 1)) {
\r
3613 if (pieceBitmap[i][piece] != NULL)
\r
3614 DeleteObject(pieceBitmap[i][piece]);
\r
3617 pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3618 pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3619 pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3620 pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3621 pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3622 pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3623 pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r
3624 pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");
\r
3625 pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");
\r
3626 pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");
\r
3627 pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");
\r
3628 pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");
\r
3629 pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");
\r
3630 pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");
\r
3631 pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");
\r
3632 pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");
\r
3633 pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");
\r
3634 pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");
\r
3635 pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");
\r
3636 pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");
\r
3637 pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");
\r