several small fixes
[xboard.git] / winboard / winboard.c
1 /*\r
2  * WinBoard.c -- Windows NT front end to XBoard\r
3  * $Id: winboard.c,v 2.3 2003/11/25 05:25:20 mann Exp $\r
4  *\r
5  * Copyright 1991 by Digital Equipment Corporation, Maynard,\r
6  * Massachusetts.  Enhancements Copyright\r
7  * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software\r
8  * Foundation, Inc.\r
9  *\r
10  * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,\r
11  * which was written and is copyrighted by Wayne Christopher.\r
12  *\r
13  * The following terms apply to Digital Equipment Corporation's copyright\r
14  * interest in XBoard:\r
15  * ------------------------------------------------------------------------\r
16  * All Rights Reserved\r
17  *\r
18  * Permission to use, copy, modify, and distribute this software and its\r
19  * documentation for any purpose and without fee is hereby granted,\r
20  * provided that the above copyright notice appear in all copies and that\r
21  * both that copyright notice and this permission notice appear in\r
22  * supporting documentation, and that the name of Digital not be\r
23  * used in advertising or publicity pertaining to distribution of the\r
24  * software without specific, written prior permission.\r
25  *\r
26  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\r
27  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\r
28  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\r
29  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\r
30  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\r
31  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\r
32  * SOFTWARE.\r
33  * ------------------------------------------------------------------------\r
34  *\r
35  * The following terms apply to the enhanced version of XBoard\r
36  * distributed by the Free Software Foundation:\r
37  * ------------------------------------------------------------------------\r
38  *\r
39  * GNU XBoard is free software: you can redistribute it and/or modify\r
40  * it under the terms of the GNU General Public License as published by\r
41  * the Free Software Foundation, either version 3 of the License, or (at\r
42  * your option) any later version.\r
43  *\r
44  * GNU XBoard is distributed in the hope that it will be useful, but\r
45  * WITHOUT ANY WARRANTY; without even the implied warranty of\r
46  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
47  * General Public License for more details.\r
48  *\r
49  * You should have received a copy of the GNU General Public License\r
50  * along with this program. If not, see http://www.gnu.org/licenses/.  *\r
51  *\r
52  *------------------------------------------------------------------------\r
53  ** See the file ChangeLog for a revision history.  */\r
54 \r
55 #include "config.h"\r
56 \r
57 #include <windows.h>\r
58 #include <winuser.h>\r
59 #include <winsock.h>\r
60 #include <commctrl.h>\r
61 \r
62 #include <stdio.h>\r
63 #include <stdlib.h>\r
64 #include <time.h>\r
65 #include <malloc.h>\r
66 #include <sys/stat.h>\r
67 #include <fcntl.h>\r
68 #include <math.h>\r
69 #include <commdlg.h>\r
70 #include <dlgs.h>\r
71 #include <richedit.h>\r
72 #include <mmsystem.h>\r
73 #include <ctype.h>\r
74 \r
75 #if __GNUC__\r
76 #include <errno.h>\r
77 #include <string.h>\r
78 #endif\r
79 \r
80 #include "common.h"\r
81 #include "winboard.h"\r
82 #include "frontend.h"\r
83 #include "backend.h"\r
84 #include "moves.h"\r
85 #include "wclipbrd.h"\r
86 #include "wgamelist.h"\r
87 #include "wedittags.h"\r
88 #include "woptions.h"\r
89 #include "wsockerr.h"\r
90 #include "defaults.h"\r
91 \r
92 #include "wsnap.h"\r
93 \r
94 //void InitEngineUCI( const char * iniDir, ChessProgramState * cps );\r
95 \r
96   int myrandom(void);\r
97   void mysrandom(unsigned int seed);\r
98 \r
99 extern int whiteFlag, blackFlag;\r
100 Boolean flipClock = FALSE;\r
101 \r
102 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);\r
103 VOID NewVariantPopup(HWND hwnd);\r
104 int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,\r
105                    /*char*/int promoChar));\r
106 void AnimateAtomicCapture(int fromX, int fromY, int toX, int toY, int nFrames);\r
107 void DisplayMove P((int moveNumber));\r
108 Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen));\r
109 int HtmlHelp( HWND hwnd, LPCSTR helpFile, UINT action, DWORD data );\r
110 \r
111 typedef struct {\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
117 } AnimInfo;\r
118 \r
119 static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };\r
120 \r
121 typedef struct {\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
126 } DragInfo;\r
127 \r
128 static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} };\r
129 \r
130 typedef struct {\r
131   POINT sq[2];    /* board coordinates of from, to squares */\r
132 } HighlightInfo;\r
133 \r
134 static HighlightInfo highlightInfo        = { {{-1, -1}, {-1, -1}} };\r
135 static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };\r
136 \r
137 typedef struct { // [HGM] atomic\r
138   int fromX, fromY, toX, toY, radius;\r
139 } ExplodeInfo;\r
140 \r
141 static ExplodeInfo explodeInfo;\r
142 \r
143 /* Window class names */\r
144 char szAppName[] = "WinBoard";\r
145 char szConsoleName[] = "WBConsole";\r
146 \r
147 /* Title bar text */\r
148 char szTitle[] = "WinBoard";\r
149 char szConsoleTitle[] = "I C S Interaction";\r
150 \r
151 char *programName;\r
152 char *settingsFileName;\r
153 BOOLEAN saveSettingsOnExit;\r
154 char installDir[MSG_SIZ];\r
155 \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
172 char *icsNames;\r
173 char *firstChessProgramNames;\r
174 char *secondChessProgramNames;\r
175 \r
176 #define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */\r
177 \r
178 #define PALETTESIZE 256\r
179 \r
180 HINSTANCE hInst;          /* current instance */\r
181 HWND hwndMain = NULL;        /* root window*/\r
182 HWND hwndConsole = NULL;\r
183 BOOLEAN alwaysOnTop = FALSE;\r
184 RECT boardRect;\r
185 COLORREF lightSquareColor, darkSquareColor, whitePieceColor, \r
186   blackPieceColor, highlightSquareColor, premoveHighlightColor;\r
187 HPALETTE hPal;\r
188 ColorClass currentColorClass;\r
189 \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
209 \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
214 \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
221 \r
222 #if __GNUC__ && !defined(_winmajor)\r
223 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */\r
224 #else\r
225 #define oldDialog (_winmajor < 4)\r
226 #endif\r
227 \r
228 char *defaultTextAttribs[] = \r
229 {\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
232   COLOR_NONE\r
233 };\r
234 \r
235 typedef struct {\r
236   char *name;\r
237   int squareSize;\r
238   int lineGap;\r
239   int smallLayout;\r
240   int tinyLayout;\r
241   int cliWidth, cliHeight;\r
242 } SizeInfo;\r
243 \r
244 SizeInfo sizeInfo[] = \r
245 {\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
265 };\r
266 \r
267 #define MF(x) {x, {{0,}, 0. }, {0, }, 0}\r
268 MyFont fontRec[NUM_SIZES][NUM_FONTS] =\r
269 {\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
288 };\r
289 \r
290 MyFont *font[NUM_SIZES][NUM_FONTS];\r
291 \r
292 typedef struct {\r
293   char *label;\r
294   int id;\r
295   HWND hwnd;\r
296   WNDPROC wndproc;\r
297 } MyButtonDesc;\r
298 \r
299 #define BUTTON_WIDTH (tinyLayout ? 16 : 32)\r
300 #define N_BUTTONS 5\r
301 \r
302 MyButtonDesc buttonDesc[N_BUTTONS] =\r
303 {\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
309 };\r
310 \r
311 int tinyLayout = 0, smallLayout = 0;\r
312 #define MENU_BAR_ITEMS 6\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
316 };\r
317 \r
318 \r
319 MySound sounds[(int)NSoundClasses];\r
320 MyTextAttribs textAttribs[(int)NColorClasses];\r
321 \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
334 };\r
335 \r
336 \r
337 \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
345 \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
351 \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
359 \r
360 char *programVersion;\r
361 \r
362 #define CPReal 1\r
363 #define CPComm 2\r
364 #define CPSock 3\r
365 #define CPRcmd 4\r
366 typedef int CPKind;\r
367 \r
368 typedef struct {\r
369   CPKind kind;\r
370   HANDLE hProcess;\r
371   DWORD pid;\r
372   HANDLE hTo;\r
373   HANDLE hFrom;\r
374   SOCKET sock;\r
375   SOCKET sock2;  /* stderr socket for OpenRcmd */\r
376 } ChildProc;\r
377 \r
378 #define INPUT_SOURCE_BUF_SIZE 4096\r
379 \r
380 typedef struct _InputSource {\r
381   CPKind kind;\r
382   HANDLE hFile;\r
383   SOCKET sock;\r
384   int lineByLine;\r
385   HANDLE hThread;\r
386   DWORD id;\r
387   char buf[INPUT_SOURCE_BUF_SIZE];\r
388   char *next;\r
389   DWORD count;\r
390   int error;\r
391   InputCallback func;\r
392   struct _InputSource *second;  /* for stderr thread on CPRcmd */\r
393   VOIDSTAR closure;\r
394 } InputSource;\r
395 \r
396 InputSource *consoleInputSource;\r
397 \r
398 DCB dcb;\r
399 \r
400 /* forward */\r
401 VOID ConsoleOutput(char* data, int length, int forceVisible);\r
402 VOID ConsoleCreate();\r
403 LRESULT CALLBACK\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
408 LRESULT CALLBACK\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
415 \r
416 /* [AS] */\r
417 int NewGameFRC();\r
418 int GameListOptions();\r
419 \r
420 HWND moveHistoryDialog = NULL;\r
421 BOOLEAN moveHistoryDialogUp = FALSE;\r
422 \r
423 WindowPlacement wpMoveHistory;\r
424 \r
425 HWND evalGraphDialog = NULL;\r
426 BOOLEAN evalGraphDialogUp = FALSE;\r
427 \r
428 WindowPlacement wpEvalGraph;\r
429 \r
430 HWND engineOutputDialog = NULL;\r
431 BOOLEAN engineOutputDialogUp = FALSE;\r
432 \r
433 WindowPlacement wpEngineOutput;\r
434 WindowPlacement wpGameList;\r
435 WindowPlacement wpConsole;\r
436 \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
441 \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
446 \r
447 VOID EngineOutputPopUp();\r
448 VOID EngineOutputPopDown();\r
449 BOOL EngineOutputIsUp();\r
450 VOID EngineOutputUpdate( FrontEndProgramStats * stats );\r
451 \r
452 VOID GothicPopUp(char *title, VariantClass variant);\r
453 /*\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
456  */\r
457 static int frozen = 0;\r
458 static int oldMenuItemState[MENU_BAR_ITEMS];\r
459 void FreezeUI()\r
460 {\r
461   HMENU hmenu;\r
462   int i;\r
463 \r
464   if (frozen) return;\r
465   frozen = 1;\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
469   }\r
470   DrawMenuBar(hwndMain);\r
471 }\r
472 \r
473 /* Undo a FreezeUI */\r
474 void ThawUI()\r
475 {\r
476   HMENU hmenu;\r
477   int i;\r
478 \r
479   if (!frozen) return;\r
480   frozen = 0;\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
484   }\r
485   DrawMenuBar(hwndMain);\r
486 }\r
487 \r
488 static int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them\r
489 \r
490 /* JAWS preparation patch (WinBoard for the sight impaired). Define required insertions as empty */\r
491 #ifdef JAWS\r
492 #include "jaws.c"\r
493 #else\r
494 #define JAWS_INIT\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
500 #define JAWS_DELETE(X) X\r
501 #define SAYMACHINEMOVE()\r
502 #define SAY(X)\r
503 #endif\r
504 \r
505 /*---------------------------------------------------------------------------*\\r
506  *\r
507  * WinMain\r
508  *\r
509 \*---------------------------------------------------------------------------*/\r
510 \r
511 int APIENTRY\r
512 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,\r
513         LPSTR lpCmdLine, int nCmdShow)\r
514 {\r
515   MSG msg;\r
516   HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;\r
517 //  INITCOMMONCONTROLSEX ex;\r
518 \r
519   debugFP = stderr;\r
520 \r
521   LoadLibrary("RICHED32.DLL");\r
522   consoleCF.cbSize = sizeof(CHARFORMAT);\r
523 \r
524   if (!InitApplication(hInstance)) {\r
525     return (FALSE);\r
526   }\r
527   if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {\r
528     return (FALSE);\r
529   }\r
530 \r
531   JAWS_INIT\r
532 \r
533 //  InitCommonControlsEx(&ex);\r
534   InitCommonControls();\r
535 \r
536   hAccelMain = LoadAccelerators (hInstance, szAppName);\r
537   hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");\r
538   hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */\r
539 \r
540   /* Acquire and dispatch messages until a WM_QUIT message is received. */\r
541 \r
542   while (GetMessage(&msg, /* message structure */\r
543                     NULL, /* handle of window receiving the message */\r
544                     0,    /* lowest message to examine */\r
545                     0))   /* highest message to examine */\r
546     {\r
547 \r
548       if(msg.message == WM_CHAR && msg.wParam == '\t') {\r
549         // [HGM] navigate: switch between all windows with tab\r
550         HWND e1 = NULL, e2 = NULL, mh = NULL, hInput = NULL, hText = NULL;\r
551         int i, currentElement = 0;\r
552 \r
553         // first determine what element of the chain we come from (if any)\r
554         if(appData.icsActive) {\r
555             hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
556             hText  = GetDlgItem(hwndConsole, OPT_ConsoleText);\r
557         }\r
558         if(engineOutputDialog && EngineOutputIsUp()) {\r
559             e1 = GetDlgItem(engineOutputDialog, IDC_EngineMemo1);\r
560             e2 = GetDlgItem(engineOutputDialog, IDC_EngineMemo2);\r
561         }\r
562         if(moveHistoryDialog && MoveHistoryIsUp()) {\r
563             mh = GetDlgItem(moveHistoryDialog, IDC_MoveHistory);\r
564         }\r
565         if(msg.hwnd == hwndMain) currentElement = 7 ; else\r
566         if(msg.hwnd == engineOutputDialog) currentElement = 2; else\r
567         if(msg.hwnd == e1)                 currentElement = 2; else\r
568         if(msg.hwnd == e2)                 currentElement = 3; else\r
569         if(msg.hwnd == moveHistoryDialog) currentElement = 4; else\r
570         if(msg.hwnd == mh)                currentElement = 4; else\r
571         if(msg.hwnd == evalGraphDialog)    currentElement = 7; else\r
572         if(msg.hwnd == hText)  currentElement = 5; else\r
573         if(msg.hwnd == hInput) currentElement = 6; else\r
574         for (i = 0; i < N_BUTTONS; i++) {\r
575             if (buttonDesc[i].hwnd == msg.hwnd) { currentElement = 1; break; }\r
576         }\r
577 \r
578         // determine where to go to\r
579         if(currentElement) { HWND h = NULL; int direction = GetKeyState(VK_SHIFT) < 0 ? -1 : 1;\r
580           do {\r
581             currentElement = (currentElement + direction) % 7;\r
582             switch(currentElement) {\r
583                 case 0:\r
584                   h = hwndMain; break; // passing this case always makes the loop exit\r
585                 case 1:\r
586                   h = buttonDesc[0].hwnd; break; // could be NULL\r
587                 case 2:\r
588                   if(!EngineOutputIsUp()) continue; // skip closed auxiliary windows\r
589                   h = e1; break;\r
590                 case 3:\r
591                   if(!EngineOutputIsUp()) continue;\r
592                   h = e2; break;\r
593                 case 4:\r
594                   if(!MoveHistoryIsUp()) continue;\r
595                   h = mh; break;\r
596 //              case 5: // input to eval graph does not seem to get here!\r
597 //                if(!EvalGraphIsUp()) continue;\r
598 //                h = evalGraphDialog; break;\r
599                 case 5:\r
600                   if(!appData.icsActive) continue;\r
601                   SAY("display");\r
602                   h = hText; break;\r
603                 case 6:\r
604                   if(!appData.icsActive) continue;\r
605                   SAY("input");\r
606                   h = hInput; break;\r
607             }\r
608           } while(h == 0);\r
609 \r
610           if(currentElement > 4 && IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
611           if(currentElement < 5 && IsIconic(hwndMain))    ShowWindow(hwndMain, SW_RESTORE); // all open together\r
612           SetFocus(h);\r
613 \r
614           continue; // this message now has been processed\r
615         }\r
616       }\r
617 \r
618       if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&\r
619           !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&\r
620           !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&\r
621           !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&\r
622           !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&\r
623           !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&\r
624           !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&\r
625           !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) &&\r
626           !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&\r
627           !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {\r
628         TranslateMessage(&msg); /* Translates virtual key codes */\r
629         DispatchMessage(&msg);  /* Dispatches message to window */\r
630       }\r
631     }\r
632 \r
633 \r
634   return (msg.wParam);  /* Returns the value from PostQuitMessage */\r
635 }\r
636 \r
637 /*---------------------------------------------------------------------------*\\r
638  *\r
639  * Initialization functions\r
640  *\r
641 \*---------------------------------------------------------------------------*/\r
642 \r
643 void\r
644 SetUserLogo()\r
645 {   // update user logo if necessary\r
646     static char oldUserName[MSG_SIZ], *curName;\r
647 \r
648     if(appData.autoLogo) {\r
649           curName = UserName();\r
650           if(strcmp(curName, oldUserName)) {\r
651                 sprintf(oldUserName, "logos\\%s.bmp", curName);\r
652                 userLogo = LoadImage( 0, oldUserName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );    \r
653                 strcpy(oldUserName, curName);\r
654           }\r
655     }\r
656 }\r
657 \r
658 BOOL\r
659 InitApplication(HINSTANCE hInstance)\r
660 {\r
661   WNDCLASS wc;\r
662 \r
663   /* Fill in window class structure with parameters that describe the */\r
664   /* main window. */\r
665 \r
666   wc.style         = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */\r
667   wc.lpfnWndProc   = (WNDPROC)WndProc;  /* Window Procedure */\r
668   wc.cbClsExtra    = 0;                 /* No per-class extra data. */\r
669   wc.cbWndExtra    = 0;                 /* No per-window extra data. */\r
670   wc.hInstance     = hInstance;         /* Owner of this class */\r
671   wc.hIcon         = LoadIcon(hInstance, "icon_white");\r
672   wc.hCursor       = LoadCursor(NULL, IDC_ARROW);       /* Cursor */\r
673   wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);  /* Default color */\r
674   wc.lpszMenuName  = szAppName;                 /* Menu name from .RC */\r
675   wc.lpszClassName = szAppName;                 /* Name to register as */\r
676 \r
677   /* Register the window class and return success/failure code. */\r
678   if (!RegisterClass(&wc)) return FALSE;\r
679 \r
680   wc.style         = CS_HREDRAW | CS_VREDRAW;\r
681   wc.lpfnWndProc   = (WNDPROC)ConsoleWndProc;\r
682   wc.cbClsExtra    = 0;\r
683   wc.cbWndExtra    = DLGWINDOWEXTRA;\r
684   wc.hInstance     = hInstance;\r
685   wc.hIcon         = LoadIcon(hInstance, "icon_white");\r
686   wc.hCursor       = LoadCursor(NULL, IDC_ARROW);\r
687   wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);\r
688   wc.lpszMenuName  = NULL;\r
689   wc.lpszClassName = szConsoleName;\r
690 \r
691   if (!RegisterClass(&wc)) return FALSE;\r
692   return TRUE;\r
693 }\r
694 \r
695 \r
696 /* Set by InitInstance, used by EnsureOnScreen */\r
697 int screenHeight, screenWidth;\r
698 \r
699 void\r
700 EnsureOnScreen(int *x, int *y, int minX, int minY)\r
701 {\r
702 //  int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);\r
703   /* Be sure window at (x,y) is not off screen (or even mostly off screen) */\r
704   if (*x > screenWidth - 32) *x = 0;\r
705   if (*y > screenHeight - 32) *y = 0;\r
706   if (*x < minX) *x = minX;\r
707   if (*y < minY) *y = minY;\r
708 }\r
709 \r
710 BOOL\r
711 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)\r
712 {\r
713   HWND hwnd; /* Main window handle. */\r
714   int ibs;\r
715   WINDOWPLACEMENT wp;\r
716   char *filepart;\r
717 \r
718   hInst = hInstance;    /* Store instance handle in our global variable */\r
719 \r
720   if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {\r
721     *filepart = NULLCHAR;\r
722   } else {\r
723     GetCurrentDirectory(MSG_SIZ, installDir);\r
724   }\r
725   gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise\r
726   screenWidth = screenHeight = 1000; // [HGM] placement: kludge to allow calling EnsureOnScreen from InitAppData\r
727   InitAppData(lpCmdLine);      /* Get run-time parameters */\r
728   if (appData.debugMode) {\r
729     debugFP = fopen(appData.nameOfDebugFile, "w");\r
730     setbuf(debugFP, NULL);\r
731   }\r
732 \r
733   InitBackEnd1();\r
734 \r
735 //  InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()\r
736 //  InitEngineUCI( installDir, &second );\r
737 \r
738   /* Create a main window for this application instance. */\r
739   hwnd = CreateWindow(szAppName, szTitle,\r
740                       (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),\r
741                       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,\r
742                       NULL, NULL, hInstance, NULL);\r
743   hwndMain = hwnd;\r
744 \r
745   /* If window could not be created, return "failure" */\r
746   if (!hwnd) {\r
747     return (FALSE);\r
748   }\r
749 \r
750   /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */\r
751   if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {\r
752       first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
753 \r
754       if (first.programLogo == NULL && appData.debugMode) {\r
755           fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );\r
756       }\r
757   } else if(appData.autoLogo) {\r
758       if(appData.firstDirectory && appData.firstDirectory[0]) {\r
759         char buf[MSG_SIZ];\r
760         sprintf(buf, "%s/logo.bmp", appData.firstDirectory);\r
761         first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );   \r
762       }\r
763   }\r
764 \r
765   if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {\r
766       second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
767 \r
768       if (second.programLogo == NULL && appData.debugMode) {\r
769           fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );\r
770       }\r
771   } else if(appData.autoLogo) {\r
772       char buf[MSG_SIZ];\r
773       if(appData.icsActive) { // [HGM] logo: in ICS mode second can be used for ICS\r
774         sprintf(buf, "logos\\%s.bmp", appData.icsHost);\r
775         second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
776       } else\r
777       if(appData.secondDirectory && appData.secondDirectory[0]) {\r
778         sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);\r
779         second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );  \r
780       }\r
781   }\r
782 \r
783   SetUserLogo();\r
784 \r
785   iconWhite = LoadIcon(hInstance, "icon_white");\r
786   iconBlack = LoadIcon(hInstance, "icon_black");\r
787   iconCurrent = iconWhite;\r
788   InitDrawingColors();\r
789   screenHeight = GetSystemMetrics(SM_CYSCREEN);\r
790   screenWidth = GetSystemMetrics(SM_CXSCREEN);\r
791   for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {\r
792     /* Compute window size for each board size, and use the largest\r
793        size that fits on this screen as the default. */\r
794     InitDrawingSizes((BoardSize)(ibs+1000), 0);\r
795     if (boardSize == (BoardSize)-1 &&\r
796         winH <= screenHeight\r
797            - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 10\r
798         && winW <= screenWidth) {\r
799       boardSize = (BoardSize)ibs;\r
800     }\r
801   }\r
802 \r
803   InitDrawingSizes(boardSize, 0);\r
804   InitMenuChecks();\r
805   buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);\r
806 \r
807   /* [AS] Load textures if specified */\r
808   ZeroMemory( &backTextureSquareInfo, sizeof(backTextureSquareInfo) );\r
809   \r
810   if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {\r
811       liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
812       liteBackTextureMode = appData.liteBackTextureMode;\r
813 \r
814       if (liteBackTexture == NULL && appData.debugMode) {\r
815           fprintf( debugFP, "Unable to load lite texture bitmap '%s'\n", appData.liteBackTextureFile );\r
816       }\r
817   }\r
818   \r
819   if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {\r
820       darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
821       darkBackTextureMode = appData.darkBackTextureMode;\r
822 \r
823       if (darkBackTexture == NULL && appData.debugMode) {\r
824           fprintf( debugFP, "Unable to load dark texture bitmap '%s'\n", appData.darkBackTextureFile );\r
825       }\r
826   }\r
827 \r
828   mysrandom( (unsigned) time(NULL) );\r
829 \r
830   /* [AS] Restore layout */\r
831   if( wpMoveHistory.visible ) {\r
832       MoveHistoryPopUp();\r
833   }\r
834 \r
835   if( wpEvalGraph.visible ) {\r
836       EvalGraphPopUp();\r
837   }\r
838 \r
839   if( wpEngineOutput.visible ) {\r
840       EngineOutputPopUp();\r
841   }\r
842 \r
843   InitBackEnd2();\r
844 \r
845   /* Make the window visible; update its client area; and return "success" */\r
846   EnsureOnScreen(&boardX, &boardY, minX, minY);\r
847   wp.length = sizeof(WINDOWPLACEMENT);\r
848   wp.flags = 0;\r
849   wp.showCmd = nCmdShow;\r
850   wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;\r
851   wp.rcNormalPosition.left = boardX;\r
852   wp.rcNormalPosition.right = boardX + winWidth;\r
853   wp.rcNormalPosition.top = boardY;\r
854   wp.rcNormalPosition.bottom = boardY + winHeight;\r
855   SetWindowPlacement(hwndMain, &wp);\r
856 \r
857   SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
858                0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);\r
859 \r
860   if (hwndConsole) {\r
861 #if AOT_CONSOLE\r
862     SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
863                  0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);\r
864 #endif\r
865     ShowWindow(hwndConsole, nCmdShow);\r
866   }\r
867   UpdateWindow(hwnd);\r
868 \r
869   return TRUE;\r
870 \r
871 }\r
872 \r
873 \r
874 typedef enum {\r
875   ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone, \r
876   ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,\r
877   ArgSettingsFilename,\r
878   ArgX, ArgY, ArgZ // [HGM] placement: for window-placement options stored relative to main window\r
879 } ArgType;\r
880 \r
881 typedef struct {\r
882   char *argName;\r
883   ArgType argType;\r
884   /***\r
885   union {\r
886     String *pString;       // ArgString\r
887     int *pInt;             // ArgInt\r
888     float *pFloat;         // ArgFloat\r
889     Boolean *pBoolean;     // ArgBoolean\r
890     COLORREF *pColor;      // ArgColor\r
891     ColorClass cc;         // ArgAttribs\r
892     String *pFilename;     // ArgFilename\r
893     BoardSize *pBoardSize; // ArgBoardSize\r
894     int whichFont;         // ArgFont\r
895     DCB *pDCB;             // ArgCommSettings\r
896     String *pFilename;     // ArgSettingsFilename\r
897   } argLoc;\r
898   ***/\r
899   LPVOID argLoc;\r
900   BOOL save;\r
901 } ArgDescriptor;\r
902 \r
903 int junk;\r
904 ArgDescriptor argDescriptors[] = {\r
905   /* positional arguments */\r
906   { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },\r
907   { "", ArgNone, NULL },\r
908   /* keyword arguments */\r
909   { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },\r
910   { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },\r
911   { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },\r
912   { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },\r
913   { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },\r
914   { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },\r
915   { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },\r
916   { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },\r
917   { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },\r
918   { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },\r
919   { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },\r
920   { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },\r
921   { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },\r
922   { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },\r
923   { "initString", ArgString, (LPVOID) &appData.initString, FALSE },\r
924   { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },\r
925   { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },\r
926   { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,\r
927     FALSE },\r
928   { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,\r
929     FALSE },\r
930   { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,\r
931     FALSE },\r
932   { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },\r
933   { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,\r
934     FALSE },\r
935   { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },\r
936   { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },\r
937   { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },\r
938   { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },\r
939   { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },\r
940   { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },\r
941   { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },\r
942   { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },\r
943   { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },\r
944   { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },\r
945   { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },\r
946   { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },\r
947   { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },\r
948   { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },\r
949   { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },\r
950   { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },\r
951   { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },\r
952   /*!!bitmapDirectory?*/\r
953   { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },\r
954   { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },\r
955   { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },\r
956   { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },\r
957   { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },\r
958   { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },\r
959   { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },\r
960   { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },\r
961   { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },\r
962   { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },\r
963   { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },\r
964   { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },\r
965   { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },\r
966   { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },\r
967   { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },\r
968   { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },\r
969   { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },\r
970   { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },\r
971   { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },\r
972   { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },\r
973   { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },\r
974   { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },\r
975   { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },\r
976   { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },\r
977   { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },\r
978   { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },\r
979   { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },\r
980   { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },\r
981   { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },\r
982   { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },\r
983   { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },\r
984   { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },\r
985   { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },\r
986   { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },\r
987   { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },\r
988   { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },\r
989   { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },\r
990   { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },\r
991   { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },\r
992   { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },\r
993   { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },\r
994   { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },\r
995   { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },\r
996   { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },\r
997   { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },\r
998   { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },\r
999   { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },\r
1000   { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },\r
1001   { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },\r
1002   { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },\r
1003   { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },\r
1004   { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },\r
1005   { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },\r
1006   { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },\r
1007   { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },\r
1008   { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },\r
1009   { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },\r
1010   { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },\r
1011   { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },\r
1012   { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },\r
1013   { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },\r
1014   { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },\r
1015   { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },\r
1016   { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },\r
1017   { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },\r
1018   { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },\r
1019   { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },\r
1020   { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },\r
1021   { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },\r
1022   { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },\r
1023   { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },\r
1024   { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },\r
1025   { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },\r
1026   { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },\r
1027   { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },\r
1028   { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },\r
1029   { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },\r
1030   { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },\r
1031   { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },\r
1032   { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },\r
1033   { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },\r
1034   { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },\r
1035   { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },\r
1036   { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },\r
1037   { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },\r
1038   { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },\r
1039   { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },\r
1040   { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },\r
1041   { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },\r
1042   { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },\r
1043   { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },\r
1044   { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },\r
1045   { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },\r
1046   { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, \r
1047     FALSE }, /* only so that old WinBoard.ini files from betas can be read */\r
1048   { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },\r
1049   { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },\r
1050   { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },\r
1051   { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },\r
1052   { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },\r
1053   { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },\r
1054   { "moveHistoryFont", ArgFont, (LPVOID) MOVEHISTORY_FONT, TRUE }, /* [AS] */\r
1055   { "boardSize", ArgBoardSize, (LPVOID) &boardSize,\r
1056     TRUE }, /* must come after all fonts */\r
1057   { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },\r
1058   { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,\r
1059     FALSE }, /* historical; kept only so old winboard.ini files will parse */\r
1060   { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },\r
1061   { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },\r
1062   { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },\r
1063   { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },\r
1064   { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },\r
1065   { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },\r
1066   { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },\r
1067   { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },\r
1068   { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },\r
1069   { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },\r
1070   { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },\r
1071   { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },\r
1072   { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },\r
1073   { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },\r
1074   { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },\r
1075   { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },\r
1076   { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },\r
1077   { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },\r
1078   { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },\r
1079   { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },\r
1080   { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },\r
1081   { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },\r
1082   { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },\r
1083   { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },\r
1084   { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },\r
1085   { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },\r
1086   { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },\r
1087   { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },\r
1088 #if 0\r
1089   { "cmailGameName", ArgString, (LPVOID) &appData.cmailGameName, FALSE },\r
1090   { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE },\r
1091 #endif\r
1092   { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },\r
1093   { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },\r
1094   { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },\r
1095   { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },\r
1096   { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },\r
1097   { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },\r
1098   { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },\r
1099   { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },\r
1100   { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },\r
1101   { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },\r
1102   { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },\r
1103   { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },\r
1104   { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },\r
1105   { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },\r
1106   { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },\r
1107   { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },\r
1108   { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },\r
1109   { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },\r
1110   { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },\r
1111   { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },\r
1112   { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },\r
1113   { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },\r
1114   { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },\r
1115   { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },\r
1116   { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },\r
1117   { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },\r
1118   { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },\r
1119   { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },\r
1120   { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },\r
1121   { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },\r
1122   { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },\r
1123   { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },\r
1124   { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },\r
1125   { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },\r
1126   { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},\r
1127   { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},\r
1128   { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},\r
1129   { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},\r
1130   { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},\r
1131   { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},\r
1132   { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},\r
1133   { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },\r
1134   { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },\r
1135   { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },\r
1136   { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },\r
1137   { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },\r
1138   { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },\r
1139   { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },\r
1140   { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },\r
1141   { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },\r
1142   { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },\r
1143   { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },\r
1144   { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },\r
1145   { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },\r
1146   { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },\r
1147   { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },\r
1148   { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },\r
1149   { "highlightLastMove", ArgBoolean,\r
1150     (LPVOID) &appData.highlightLastMove, TRUE },\r
1151   { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },\r
1152   { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },\r
1153   { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },\r
1154   { "highlightDragging", ArgBoolean,\r
1155     (LPVOID) &appData.highlightDragging, TRUE },\r
1156   { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },\r
1157   { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },\r
1158   { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },\r
1159   { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },\r
1160   { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },\r
1161   { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },\r
1162   { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },\r
1163   { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },\r
1164   { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },\r
1165   { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },\r
1166   { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },\r
1167   { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },\r
1168   { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },\r
1169   { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },\r
1170   { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },\r
1171   { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },\r
1172   { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },\r
1173   { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },\r
1174   { "soundShout", ArgFilename,\r
1175     (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },\r
1176   { "soundSShout", ArgFilename,\r
1177     (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },\r
1178   { "soundChannel1", ArgFilename,\r
1179     (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },\r
1180   { "soundChannel", ArgFilename,\r
1181     (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },\r
1182   { "soundKibitz", ArgFilename,\r
1183     (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },\r
1184   { "soundTell", ArgFilename,\r
1185     (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },\r
1186   { "soundChallenge", ArgFilename,\r
1187     (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },\r
1188   { "soundRequest", ArgFilename,\r
1189     (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },\r
1190   { "soundSeek", ArgFilename,\r
1191     (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },\r
1192   { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },\r
1193   { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },\r
1194   { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },\r
1195   { "soundIcsLoss", ArgFilename, \r
1196     (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },\r
1197   { "soundIcsDraw", ArgFilename, \r
1198     (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },\r
1199   { "soundIcsUnfinished", ArgFilename, \r
1200     (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},\r
1201   { "soundIcsAlarm", ArgFilename, \r
1202     (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },\r
1203   { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },\r
1204   { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },\r
1205   { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },\r
1206   { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },\r
1207   { "reuseChessPrograms", ArgBoolean,\r
1208     (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */\r
1209   { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },\r
1210   { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },\r
1211   { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },\r
1212   { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },\r
1213   { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },\r
1214   { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },\r
1215   { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },\r
1216   { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },\r
1217   { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },\r
1218   { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },\r
1219   { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },\r
1220   { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },\r
1221   { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },\r
1222   { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },\r
1223   { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,\r
1224     TRUE },\r
1225   { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,\r
1226     TRUE },\r
1227   { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },\r
1228   { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },\r
1229   { "variant", ArgString, (LPVOID) &appData.variant, FALSE },\r
1230   { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion, FALSE },\r
1231   { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,FALSE },\r
1232   { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },\r
1233   { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },\r
1234   { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },\r
1235   { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },\r
1236   /* [AS] New features */\r
1237   { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE },\r
1238   { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE },\r
1239   { "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE },\r
1240   { "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE },\r
1241   { "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE },\r
1242   { "darkBackTextureFile", ArgString, (LPVOID) &appData.darkBackTextureFile, TRUE },\r
1243   { "liteBackTextureMode", ArgInt, (LPVOID) &appData.liteBackTextureMode, TRUE },\r
1244   { "darkBackTextureMode", ArgInt, (LPVOID) &appData.darkBackTextureMode, TRUE },\r
1245   { "renderPiecesWithFont", ArgString, (LPVOID) &appData.renderPiecesWithFont, TRUE },\r
1246   { "fontPieceToCharTable", ArgString, (LPVOID) &appData.fontToPieceTable, TRUE },\r
1247   { "fontPieceBackColorWhite", ArgColor, (LPVOID) &appData.fontBackColorWhite, TRUE },\r
1248   { "fontPieceForeColorWhite", ArgColor, (LPVOID) &appData.fontForeColorWhite, TRUE },\r
1249   { "fontPieceBackColorBlack", ArgColor, (LPVOID) &appData.fontBackColorBlack, TRUE },\r
1250   { "fontPieceForeColorBlack", ArgColor, (LPVOID) &appData.fontForeColorBlack, TRUE },\r
1251   { "fontPieceSize", ArgInt, (LPVOID) &appData.fontPieceSize, TRUE },\r
1252   { "overrideLineGap", ArgInt, (LPVOID) &appData.overrideLineGap, TRUE },\r
1253   { "adjudicateLossThreshold", ArgInt, (LPVOID) &appData.adjudicateLossThreshold, TRUE },\r
1254   { "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE },\r
1255   { "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE },\r
1256   { "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },\r
1257   { "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },\r
1258   { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },\r
1259   { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE },\r
1260   { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE },\r
1261   { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE },\r
1262   { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE },\r
1263   { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE },\r
1264   { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE },\r
1265   { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE },\r
1266   { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE },\r
1267   { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE },\r
1268   { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE },\r
1269   { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE },\r
1270   { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE },\r
1271   { "firstIsUCI", ArgBoolean, (LPVOID) &appData.firstIsUCI, FALSE },\r
1272   { "fUCI", ArgTrue, (LPVOID) &appData.firstIsUCI, FALSE },\r
1273   { "secondIsUCI", ArgBoolean, (LPVOID) &appData.secondIsUCI, FALSE },\r
1274   { "sUCI", ArgTrue, (LPVOID) &appData.secondIsUCI, FALSE },\r
1275   { "firstHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },\r
1276   { "fNoOwnBookUCI", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },\r
1277   { "firstXBook", ArgFalse, (LPVOID) &appData.firstHasOwnBookUCI, FALSE },\r
1278   { "secondHasOwnBookUCI", ArgBoolean, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },\r
1279   { "sNoOwnBookUCI", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },\r
1280   { "secondXBook", ArgFalse, (LPVOID) &appData.secondHasOwnBookUCI, FALSE },\r
1281   { "polyglotDir", ArgFilename, (LPVOID) &appData.polyglotDir, TRUE },\r
1282   { "usePolyglotBook", ArgBoolean, (LPVOID) &appData.usePolyglotBook, TRUE },\r
1283   { "polyglotBook", ArgFilename, (LPVOID) &appData.polyglotBook, TRUE },\r
1284   { "defaultHashSize", ArgInt, (LPVOID) &appData.defaultHashSize, TRUE }, \r
1285   { "defaultCacheSizeEGTB", ArgInt, (LPVOID) &appData.defaultCacheSizeEGTB, TRUE },\r
1286   { "defaultPathEGTB", ArgFilename, (LPVOID) &appData.defaultPathEGTB, TRUE },\r
1287 \r
1288   /* [HGM] board-size, adjudication and misc. options */\r
1289   { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE },\r
1290   { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE },\r
1291   { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE },\r
1292   { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE },\r
1293   { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE },\r
1294   { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE },\r
1295   { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE },\r
1296   { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE },\r
1297   { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE },\r
1298   { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE },\r
1299   { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE },\r
1300   { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE },\r
1301   { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE },\r
1302   { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE },\r
1303   { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE },\r
1304   { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE },\r
1305   { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE },\r
1306   { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE },\r
1307   { "userName", ArgString, (LPVOID) &appData.userName, FALSE },\r
1308   { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE },\r
1309   { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE },\r
1310   { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE },\r
1311   { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE },\r
1312   { "niceEngines", ArgInt, (LPVOID) &appData.niceEngines, TRUE },\r
1313   { "firstLogo", ArgFilename, (LPVOID) &appData.firstLogo, FALSE },\r
1314   { "secondLogo", ArgFilename, (LPVOID) &appData.secondLogo, FALSE },\r
1315   { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE },\r
1316   { "firstOptions", ArgString, (LPVOID) &appData.firstOptions, FALSE },\r
1317   { "secondOptions", ArgString, (LPVOID) &appData.secondOptions, FALSE },\r
1318   { "firstNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride1, FALSE },\r
1319   { "secondNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride2, FALSE },\r
1320 \r
1321 #ifdef ZIPPY\r
1322   { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },\r
1323   { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },\r
1324   { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },\r
1325   { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },\r
1326   { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },\r
1327   { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },\r
1328   { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },\r
1329   { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },\r
1330   { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },\r
1331   { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },\r
1332   { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },\r
1333   { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE },\r
1334   { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,\r
1335     FALSE },\r
1336   { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE },\r
1337   { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE },\r
1338   { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE },\r
1339   { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },\r
1340   { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },\r
1341   { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE },\r
1342   { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,\r
1343     FALSE },\r
1344   { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE },\r
1345   { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },\r
1346   { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },\r
1347   { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE },\r
1348   { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE },\r
1349   { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE },\r
1350   { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE },\r
1351   { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },\r
1352   { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },\r
1353   { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE },\r
1354   { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE },\r
1355   { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },\r
1356   { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },\r
1357   { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },\r
1358   { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },\r
1359   { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },\r
1360   { "zippyShortGame", ArgInt, (LPVOID)&appData.zippyShortGame, FALSE },\r
1361   /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */\r
1362   { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },\r
1363 #endif\r
1364   /* [HGM] options for broadcasting and time odds */\r
1365   { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },\r
1366   { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },\r
1367   { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },\r
1368   { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },\r
1369   { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },\r
1370   { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },\r
1371   { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },\r
1372   { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },\r
1373   { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },\r
1374   { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },\r
1375   { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE },\r
1376 \r
1377   // [HGM] placement: put all window layouts last in ini file, but man X,Y before all others\r
1378   { "minX", ArgZ, (LPVOID) &minX, FALSE }, // [HGM] placement: to make suer auxialary windows can be placed\r
1379   { "minY", ArgZ, (LPVOID) &minY, FALSE },\r
1380   { "winWidth",  ArgInt, (LPVOID) &winWidth,  TRUE }, // [HGM] placement: dummies to remember right & bottom\r
1381   { "winHeight", ArgInt, (LPVOID) &winHeight, TRUE }, //       for attaching auxiliary windows to them\r
1382   { "x", ArgInt, (LPVOID) &boardX, TRUE },\r
1383   { "y", ArgInt, (LPVOID) &boardY, TRUE },\r
1384   { "icsX", ArgX,   (LPVOID) &wpConsole.x, TRUE },\r
1385   { "icsY", ArgY,   (LPVOID) &wpConsole.y, TRUE },\r
1386   { "icsW", ArgInt, (LPVOID) &wpConsole.width, TRUE },\r
1387   { "icsH", ArgInt, (LPVOID) &wpConsole.height, TRUE },\r
1388   { "analysisX", ArgX,   (LPVOID) &analysisX, FALSE }, // [HGM] placement: analysis window no longer exists\r
1389   { "analysisY", ArgY,   (LPVOID) &analysisY, FALSE }, //       provided for compatibility with old ini files\r
1390   { "analysisW", ArgInt, (LPVOID) &analysisW, FALSE },\r
1391   { "analysisH", ArgInt, (LPVOID) &analysisH, FALSE },\r
1392   { "commentX", ArgX,   (LPVOID) &commentX, TRUE },\r
1393   { "commentY", ArgY,   (LPVOID) &commentY, TRUE },\r
1394   { "commentW", ArgInt, (LPVOID) &commentW, TRUE },\r
1395   { "commentH", ArgInt, (LPVOID) &commentH, TRUE },\r
1396   { "tagsX", ArgX,   (LPVOID) &editTagsX, TRUE },\r
1397   { "tagsY", ArgY,   (LPVOID) &editTagsY, TRUE },\r
1398   { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },\r
1399   { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },\r
1400   { "gameListX", ArgX,   (LPVOID) &wpGameList.x, TRUE },\r
1401   { "gameListY", ArgY,   (LPVOID) &wpGameList.y, TRUE },\r
1402   { "gameListW", ArgInt, (LPVOID) &wpGameList.width, TRUE },\r
1403   { "gameListH", ArgInt, (LPVOID) &wpGameList.height, TRUE },\r
1404   /* [AS] Layout stuff */\r
1405   { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },\r
1406   { "moveHistoryX", ArgX,   (LPVOID) &wpMoveHistory.x, TRUE },\r
1407   { "moveHistoryY", ArgY,   (LPVOID) &wpMoveHistory.y, TRUE },\r
1408   { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },\r
1409   { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },\r
1410 \r
1411   { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },\r
1412   { "evalGraphX", ArgX,   (LPVOID) &wpEvalGraph.x, TRUE },\r
1413   { "evalGraphY", ArgY,   (LPVOID) &wpEvalGraph.y, TRUE },\r
1414   { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },\r
1415   { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },\r
1416 \r
1417   { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },\r
1418   { "engineOutputX", ArgX,   (LPVOID) &wpEngineOutput.x, TRUE },\r
1419   { "engineOutputY", ArgY,   (LPVOID) &wpEngineOutput.y, TRUE },\r
1420   { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },\r
1421   { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },\r
1422 \r
1423   { NULL, ArgNone, NULL, FALSE }\r
1424 };\r
1425 \r
1426 \r
1427 /* Kludge for indirection files on command line */\r
1428 char* lastIndirectionFilename;\r
1429 ArgDescriptor argDescriptorIndirection =\r
1430 { "", ArgSettingsFilename, (LPVOID) NULL, FALSE };\r
1431 \r
1432 \r
1433 VOID\r
1434 ExitArgError(char *msg, char *badArg)\r
1435 {\r
1436   char buf[MSG_SIZ];\r
1437 \r
1438   sprintf(buf, "%s %s", msg, badArg);\r
1439   DisplayFatalError(buf, 0, 2);\r
1440   exit(2);\r
1441 }\r
1442 \r
1443 /* Command line font name parser.  NULL name means do nothing.\r
1444    Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"\r
1445    For backward compatibility, syntax without the colon is also\r
1446    accepted, but font names with digits in them won't work in that case.\r
1447 */\r
1448 VOID\r
1449 ParseFontName(char *name, MyFontParams *mfp)\r
1450 {\r
1451   char *p, *q;\r
1452   if (name == NULL) return;\r
1453   p = name;\r
1454   q = strchr(p, ':');\r
1455   if (q) {\r
1456     if (q - p >= sizeof(mfp->faceName))\r
1457       ExitArgError("Font name too long:", name);\r
1458     memcpy(mfp->faceName, p, q - p);\r
1459     mfp->faceName[q - p] = NULLCHAR;\r
1460     p = q + 1;\r
1461   } else {\r
1462     q = mfp->faceName;\r
1463     while (*p && !isdigit(*p)) {\r
1464       *q++ = *p++;\r
1465       if (q - mfp->faceName >= sizeof(mfp->faceName))\r
1466         ExitArgError("Font name too long:", name);\r
1467     }\r
1468     while (q > mfp->faceName && q[-1] == ' ') q--;\r
1469     *q = NULLCHAR;\r
1470   }\r
1471   if (!*p) ExitArgError("Font point size missing:", name);\r
1472   mfp->pointSize = (float) atof(p);\r
1473   mfp->bold = (strchr(p, 'b') != NULL);\r
1474   mfp->italic = (strchr(p, 'i') != NULL);\r
1475   mfp->underline = (strchr(p, 'u') != NULL);\r
1476   mfp->strikeout = (strchr(p, 's') != NULL);\r
1477 }\r
1478 \r
1479 /* Color name parser.\r
1480    X version accepts X color names, but this one\r
1481    handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */\r
1482 COLORREF\r
1483 ParseColorName(char *name)\r
1484 {\r
1485   int red, green, blue, count;\r
1486   char buf[MSG_SIZ];\r
1487 \r
1488   count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);\r
1489   if (count != 3) {\r
1490     count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d", \r
1491       &red, &green, &blue);\r
1492   }\r
1493   if (count != 3) {\r
1494     sprintf(buf, "Can't parse color name %s", name);\r
1495     DisplayError(buf, 0);\r
1496     return RGB(0, 0, 0);\r
1497   }\r
1498   return PALETTERGB(red, green, blue);\r
1499 }\r
1500 \r
1501 \r
1502 void ParseAttribs(COLORREF *color, int *effects, char* argValue)\r
1503 {\r
1504   char *e = argValue;\r
1505   int eff = 0;\r
1506 \r
1507   while (*e) {\r
1508     if (*e == 'b')      eff |= CFE_BOLD;\r
1509     else if (*e == 'i') eff |= CFE_ITALIC;\r
1510     else if (*e == 'u') eff |= CFE_UNDERLINE;\r
1511     else if (*e == 's') eff |= CFE_STRIKEOUT;\r
1512     else if (*e == '#' || isdigit(*e)) break;\r
1513     e++;\r
1514   }\r
1515   *effects = eff;\r
1516   *color   = ParseColorName(e);\r
1517 }\r
1518 \r
1519 \r
1520 BoardSize\r
1521 ParseBoardSize(char *name)\r
1522 {\r
1523   BoardSize bs = SizeTiny;\r
1524   while (sizeInfo[bs].name != NULL) {\r
1525     if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;\r
1526     bs++;\r
1527   }\r
1528   ExitArgError("Unrecognized board size value", name);\r
1529   return bs; /* not reached */\r
1530 }\r
1531 \r
1532 \r
1533 char\r
1534 StringGet(void *getClosure)\r
1535 {\r
1536   char **p = (char **) getClosure;\r
1537   return *((*p)++);\r
1538 }\r
1539 \r
1540 char\r
1541 FileGet(void *getClosure)\r
1542 {\r
1543   int c;\r
1544   FILE* f = (FILE*) getClosure;\r
1545 \r
1546   c = getc(f);\r
1547   if (c == '\r') c = getc(f); // work around DOS format files by bypassing the '\r' completely\r
1548   if (c == EOF)\r
1549     return NULLCHAR;\r
1550   else\r
1551     return (char) c;\r
1552 }\r
1553 \r
1554 /* Parse settings file named "name". If file found, return the\r
1555    full name in fullname and return TRUE; else return FALSE */\r
1556 BOOLEAN\r
1557 ParseSettingsFile(char *name, char fullname[MSG_SIZ])\r
1558 {\r
1559   char *dummy;\r
1560   FILE *f;\r
1561   int ok; char buf[MSG_SIZ];\r
1562 \r
1563   ok = SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy);\r
1564   if(!ok && strchr(name, '.') == NULL) { // [HGM] append default file-name extension '.ini' when needed\r
1565     sprintf(buf, "%s.ini", name);\r
1566     ok = SearchPath(installDir, buf, NULL, MSG_SIZ, fullname, &dummy);\r
1567   }\r
1568   if (ok) {\r
1569     f = fopen(fullname, "r");\r
1570     if (f != NULL) {\r
1571       ParseArgs(FileGet, f);\r
1572       fclose(f);\r
1573       return TRUE;\r
1574     }\r
1575   }\r
1576   return FALSE;\r
1577 }\r
1578 \r
1579 VOID\r
1580 ParseArgs(GetFunc get, void *cl)\r
1581 {\r
1582   char argName[ARG_MAX];\r
1583   char argValue[ARG_MAX];\r
1584   ArgDescriptor *ad;\r
1585   char start;\r
1586   char *q;\r
1587   int i, octval;\r
1588   char ch;\r
1589   int posarg = 0;\r
1590 \r
1591   ch = get(cl);\r
1592   for (;;) {\r
1593     while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);\r
1594     if (ch == NULLCHAR) break;\r
1595     if (ch == ';') {\r
1596       /* Comment to end of line */\r
1597       ch = get(cl);\r
1598       while (ch != '\n' && ch != NULLCHAR) ch = get(cl);\r
1599       continue;\r
1600     } else if (ch == '/' || ch == '-') {\r
1601       /* Switch */\r
1602       q = argName;\r
1603       while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&\r
1604              ch != '\n' && ch != '\t') {\r
1605         *q++ = ch;\r
1606         ch = get(cl);\r
1607       }\r
1608       *q = NULLCHAR;\r
1609 \r
1610       for (ad = argDescriptors; ad->argName != NULL; ad++)\r
1611         if (strcmp(ad->argName, argName + 1) == 0) break;\r
1612 \r
1613       if (ad->argName == NULL)\r
1614         ExitArgError("Unrecognized argument", argName);\r
1615 \r
1616     } else if (ch == '@') {\r
1617       /* Indirection file */\r
1618       ad = &argDescriptorIndirection;\r
1619       ch = get(cl);\r
1620     } else {\r
1621       /* Positional argument */\r
1622       ad = &argDescriptors[posarg++];\r
1623       strcpy(argName, ad->argName);\r
1624     }\r
1625 \r
1626     if (ad->argType == ArgTrue) {\r
1627       *(Boolean *) ad->argLoc = TRUE;\r
1628       continue;\r
1629     }\r
1630     if (ad->argType == ArgFalse) {\r
1631       *(Boolean *) ad->argLoc = FALSE;\r
1632       continue;\r
1633     }\r
1634 \r
1635     while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);\r
1636     if (ch == NULLCHAR || ch == '\n') {\r
1637       ExitArgError("No value provided for argument", argName);\r
1638     }\r
1639     q = argValue;\r
1640     if (ch == '{') {\r
1641       // Quoting with { }.  No characters have to (or can) be escaped.\r
1642       // Thus the string cannot contain a '}' character.\r
1643       start = ch;\r
1644       ch = get(cl);\r
1645       while (start) {\r
1646         switch (ch) {\r
1647         case NULLCHAR:\r
1648           start = NULLCHAR;\r
1649           break;\r
1650           \r
1651         case '}':\r
1652           ch = get(cl);\r
1653           start = NULLCHAR;\r
1654           break;\r
1655 \r
1656         default:\r
1657           *q++ = ch;\r
1658           ch = get(cl);\r
1659           break;\r
1660         }\r
1661       }   \r
1662     } else if (ch == '\'' || ch == '"') {\r
1663       // Quoting with ' ' or " ", with \ as escape character.\r
1664       // Inconvenient for long strings that may contain Windows filenames.\r
1665       start = ch;\r
1666       ch = get(cl);\r
1667       while (start) {\r
1668         switch (ch) {\r
1669         case NULLCHAR:\r
1670           start = NULLCHAR;\r
1671           break;\r
1672 \r
1673         default:\r
1674         not_special:\r
1675           *q++ = ch;\r
1676           ch = get(cl);\r
1677           break;\r
1678 \r
1679         case '\'':\r
1680         case '\"':\r
1681           if (ch == start) {\r
1682             ch = get(cl);\r
1683             start = NULLCHAR;\r
1684             break;\r
1685           } else {\r
1686             goto not_special;\r
1687           }\r
1688 \r
1689         case '\\':\r
1690           if (ad->argType == ArgFilename\r
1691               || ad->argType == ArgSettingsFilename) {\r
1692               goto not_special;\r
1693           }\r
1694           ch = get(cl);\r
1695           switch (ch) {\r
1696           case NULLCHAR:\r
1697             ExitArgError("Incomplete \\ escape in value for", argName);\r
1698             break;\r
1699           case 'n':\r
1700             *q++ = '\n';\r
1701             ch = get(cl);\r
1702             break;\r
1703           case 'r':\r
1704             *q++ = '\r';\r
1705             ch = get(cl);\r
1706             break;\r
1707           case 't':\r
1708             *q++ = '\t';\r
1709             ch = get(cl);\r
1710             break;\r
1711           case 'b':\r
1712             *q++ = '\b';\r
1713             ch = get(cl);\r
1714             break;\r
1715           case 'f':\r
1716             *q++ = '\f';\r
1717             ch = get(cl);\r
1718             break;\r
1719           default:\r
1720             octval = 0;\r
1721             for (i = 0; i < 3; i++) {\r
1722               if (ch >= '0' && ch <= '7') {\r
1723                 octval = octval*8 + (ch - '0');\r
1724                 ch = get(cl);\r
1725               } else {\r
1726                 break;\r
1727               }\r
1728             }\r
1729             if (i > 0) {\r
1730               *q++ = (char) octval;\r
1731             } else {\r
1732               *q++ = ch;\r
1733               ch = get(cl);\r
1734             }\r
1735             break;\r
1736           }\r
1737           break;\r
1738         }\r
1739       }\r
1740     } else {\r
1741       while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {\r
1742         *q++ = ch;\r
1743         ch = get(cl);\r
1744       }\r
1745     }\r
1746     *q = NULLCHAR;\r
1747 \r
1748     switch (ad->argType) {\r
1749     case ArgInt:\r
1750       *(int *) ad->argLoc = atoi(argValue);\r
1751       break;\r
1752 \r
1753     case ArgX:\r
1754       *(int *) ad->argLoc = atoi(argValue) + boardX; // [HGM] placement: translate stored relative to absolute \r
1755       break;\r
1756 \r
1757     case ArgY:\r
1758       *(int *) ad->argLoc = atoi(argValue) + boardY; // (this is really kludgey, it should be done where used...)\r
1759       break;\r
1760 \r
1761     case ArgZ:\r
1762       *(int *) ad->argLoc = atoi(argValue);\r
1763       EnsureOnScreen(&boardX, &boardY, minX, minY); \r
1764       break;\r
1765 \r
1766     case ArgFloat:\r
1767       *(float *) ad->argLoc = (float) atof(argValue);\r
1768       break;\r
1769 \r
1770     case ArgString:\r
1771     case ArgFilename:\r
1772       *(char **) ad->argLoc = strdup(argValue);\r
1773       break;\r
1774 \r
1775     case ArgSettingsFilename:\r
1776       {\r
1777         char fullname[MSG_SIZ];\r
1778         if (ParseSettingsFile(argValue, fullname)) {\r
1779           if (ad->argLoc != NULL) {\r
1780             *(char **) ad->argLoc = strdup(fullname);\r
1781           }\r
1782         } else {\r
1783           if (ad->argLoc != NULL) {\r
1784           } else {\r
1785             ExitArgError("Failed to open indirection file", argValue);\r
1786           }\r
1787         }\r
1788       }\r
1789       break;\r
1790 \r
1791     case ArgBoolean:\r
1792       switch (argValue[0]) {\r
1793       case 't':\r
1794       case 'T':\r
1795         *(Boolean *) ad->argLoc = TRUE;\r
1796         break;\r
1797       case 'f':\r
1798       case 'F':\r
1799         *(Boolean *) ad->argLoc = FALSE;\r
1800         break;\r
1801       default:\r
1802         ExitArgError("Unrecognized boolean argument value", argValue);\r
1803         break;\r
1804       }\r
1805       break;\r
1806 \r
1807     case ArgColor:\r
1808       *(COLORREF *)ad->argLoc = ParseColorName(argValue);\r
1809       break;\r
1810 \r
1811     case ArgAttribs: {\r
1812       ColorClass cc = (ColorClass)ad->argLoc;\r
1813       ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);\r
1814       }\r
1815       break;\r
1816       \r
1817     case ArgBoardSize:\r
1818       *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);\r
1819       break;\r
1820 \r
1821     case ArgFont:\r
1822       ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);\r
1823       break;\r
1824 \r
1825     case ArgCommSettings:\r
1826       ParseCommSettings(argValue, &dcb);\r
1827       break;\r
1828 \r
1829     case ArgNone:\r
1830       ExitArgError("Unrecognized argument", argValue);\r
1831       break;\r
1832     case ArgTrue:\r
1833     case ArgFalse: ;\r
1834     }\r
1835   }\r
1836 }\r
1837 \r
1838 VOID\r
1839 LFfromMFP(LOGFONT* lf, MyFontParams *mfp)\r
1840 {\r
1841   HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);\r
1842   lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);\r
1843   DeleteDC(hdc);\r
1844   lf->lfWidth = 0;\r
1845   lf->lfEscapement = 0;\r
1846   lf->lfOrientation = 0;\r
1847   lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;\r
1848   lf->lfItalic = mfp->italic;\r
1849   lf->lfUnderline = mfp->underline;\r
1850   lf->lfStrikeOut = mfp->strikeout;\r
1851   lf->lfCharSet = DEFAULT_CHARSET;\r
1852   lf->lfOutPrecision = OUT_DEFAULT_PRECIS;\r
1853   lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;\r
1854   lf->lfQuality = DEFAULT_QUALITY;\r
1855   lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;\r
1856   strcpy(lf->lfFaceName, mfp->faceName);\r
1857 }\r
1858 \r
1859 VOID\r
1860 CreateFontInMF(MyFont *mf)\r
1861 {\r
1862   LFfromMFP(&mf->lf, &mf->mfp);\r
1863   if (mf->hf) DeleteObject(mf->hf);\r
1864   mf->hf = CreateFontIndirect(&mf->lf);\r
1865 }\r
1866 \r
1867 VOID\r
1868 SetDefaultTextAttribs()\r
1869 {\r
1870   ColorClass cc;\r
1871   for (cc = (ColorClass)0; cc < NColorClasses; cc++) {\r
1872     ParseAttribs(&textAttribs[cc].color, \r
1873                  &textAttribs[cc].effects, \r
1874                  defaultTextAttribs[cc]);\r
1875   }\r
1876 }\r
1877 \r
1878 VOID\r
1879 SetDefaultSounds()\r
1880 {\r
1881   ColorClass cc;\r
1882   SoundClass sc;\r
1883   for (cc = (ColorClass)0; cc < NColorClasses; cc++) {\r
1884     textAttribs[cc].sound.name = strdup("");\r
1885     textAttribs[cc].sound.data = NULL;\r
1886   }\r
1887   for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {\r
1888     sounds[sc].name = strdup("");\r
1889     sounds[sc].data = NULL;\r
1890   }\r
1891   sounds[(int)SoundBell].name = strdup(SOUND_BELL);\r
1892 }\r
1893 \r
1894 VOID\r
1895 LoadAllSounds()\r
1896 {\r
1897   ColorClass cc;\r
1898   SoundClass sc;\r
1899   for (cc = (ColorClass)0; cc < NColorClasses; cc++) {\r
1900     MyLoadSound(&textAttribs[cc].sound);\r
1901   }\r
1902   for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {\r
1903     MyLoadSound(&sounds[sc]);\r
1904   }\r
1905 }\r
1906 \r
1907 VOID\r
1908 InitAppData(LPSTR lpCmdLine)\r
1909 {\r
1910   int i, j;\r
1911   char buf[ARG_MAX], currDir[MSG_SIZ];\r
1912   char *dummy, *p;\r
1913 \r
1914   programName = szAppName;\r
1915 \r
1916   /* Initialize to defaults */\r
1917   lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);\r
1918   darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);\r
1919   whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);\r
1920   blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);\r
1921   highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);\r
1922   premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);\r
1923   consoleBackgroundColor = ParseColorName(COLOR_BKGD);\r
1924   SetDefaultTextAttribs();\r
1925   SetDefaultSounds();\r
1926   appData.movesPerSession = MOVES_PER_SESSION;\r
1927   appData.initString = INIT_STRING;\r
1928   appData.secondInitString = INIT_STRING;\r
1929   appData.firstComputerString = COMPUTER_STRING;\r
1930   appData.secondComputerString = COMPUTER_STRING;\r
1931   appData.firstChessProgram = FIRST_CHESS_PROGRAM;\r
1932   appData.secondChessProgram = SECOND_CHESS_PROGRAM;\r
1933   appData.firstPlaysBlack = FALSE;\r
1934   appData.noChessProgram = FALSE;\r
1935   chessProgram = FALSE;\r
1936   appData.firstHost = FIRST_HOST;\r
1937   appData.secondHost = SECOND_HOST;\r
1938   appData.firstDirectory = FIRST_DIRECTORY;\r
1939   appData.secondDirectory = SECOND_DIRECTORY;\r
1940   appData.bitmapDirectory = "";\r
1941   appData.remoteShell = REMOTE_SHELL;\r
1942   appData.remoteUser = "";\r
1943   appData.timeDelay = TIME_DELAY;\r
1944   appData.timeControl = TIME_CONTROL;\r
1945   appData.timeIncrement = TIME_INCREMENT;\r
1946   appData.icsActive = FALSE;\r
1947   appData.icsHost = "";\r
1948   appData.icsPort = ICS_PORT;\r
1949   appData.icsCommPort = ICS_COMM_PORT;\r
1950   appData.icsLogon = ICS_LOGON;\r
1951   appData.icsHelper = "";\r
1952   appData.useTelnet = FALSE;\r
1953   appData.telnetProgram = TELNET_PROGRAM;\r
1954   appData.gateway = "";\r
1955   appData.loadGameFile = "";\r
1956   appData.loadGameIndex = 0;\r
1957   appData.saveGameFile = "";\r
1958   appData.autoSaveGames = FALSE;\r
1959   appData.loadPositionFile = "";\r
1960   appData.loadPositionIndex = 1;\r
1961   appData.savePositionFile = "";\r
1962   appData.matchMode = FALSE;\r
1963   appData.matchGames = 0;\r
1964   appData.monoMode = FALSE;\r
1965   appData.debugMode = FALSE;\r
1966   appData.clockMode = TRUE;\r
1967   boardSize = (BoardSize) -1; /* determine by screen size */\r
1968   appData.Iconic = FALSE; /*unused*/\r
1969   appData.searchTime = "";\r
1970   appData.searchDepth = 0;\r
1971   appData.showCoords = FALSE;\r
1972   appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/\r
1973   appData.autoCallFlag = FALSE;\r
1974   appData.flipView = FALSE;\r
1975   appData.autoFlipView = TRUE;\r
1976   appData.cmailGameName = "";\r
1977   appData.alwaysPromoteToQueen = FALSE;\r
1978   appData.oldSaveStyle = FALSE;\r
1979   appData.quietPlay = FALSE;\r
1980   appData.showThinking = FALSE;\r
1981   appData.ponderNextMove = TRUE;\r
1982   appData.periodicUpdates = TRUE;\r
1983   appData.popupExitMessage = TRUE;\r
1984   appData.popupMoveErrors = FALSE;\r
1985   appData.autoObserve = FALSE;\r
1986   appData.autoComment = FALSE;\r
1987   appData.animate = TRUE;\r
1988   appData.animSpeed = 10;\r
1989   appData.animateDragging = TRUE;\r
1990   appData.highlightLastMove = TRUE;\r
1991   appData.getMoveList = TRUE;\r
1992   appData.testLegality = TRUE;\r
1993   appData.premove = TRUE;\r
1994   appData.premoveWhite = FALSE;\r
1995   appData.premoveWhiteText = "";\r
1996   appData.premoveBlack = FALSE;\r
1997   appData.premoveBlackText = "";\r
1998   appData.icsAlarm = TRUE;\r
1999   appData.icsAlarmTime = 5000;\r
2000   appData.autoRaiseBoard = TRUE;\r
2001   appData.localLineEditing = TRUE;\r
2002   appData.colorize = TRUE;\r
2003   appData.reuseFirst = TRUE;\r
2004   appData.reuseSecond = TRUE;\r
2005   appData.blindfold = FALSE;\r
2006   appData.icsEngineAnalyze = FALSE;\r
2007   memset(&dcb, 0, sizeof(DCB)); // required by VS 2002 +\r
2008   dcb.DCBlength = sizeof(DCB);\r
2009   dcb.BaudRate = 9600;\r
2010   dcb.fBinary = TRUE;\r
2011   dcb.fParity = FALSE;\r
2012   dcb.fOutxCtsFlow = FALSE;\r
2013   dcb.fOutxDsrFlow = FALSE;\r
2014   dcb.fDtrControl = DTR_CONTROL_ENABLE;\r
2015   dcb.fDsrSensitivity = FALSE;\r
2016   dcb.fTXContinueOnXoff = TRUE;\r
2017   dcb.fOutX = FALSE;\r
2018   dcb.fInX = FALSE;\r
2019   dcb.fNull = FALSE;\r
2020   dcb.fRtsControl = RTS_CONTROL_ENABLE;\r
2021   dcb.fAbortOnError = FALSE;\r
2022   dcb.ByteSize = 7;\r
2023   dcb.Parity = SPACEPARITY;\r
2024   dcb.StopBits = ONESTOPBIT;\r
2025   settingsFileName = SETTINGS_FILE;\r
2026   saveSettingsOnExit = TRUE;\r
2027   boardX = CW_USEDEFAULT;\r
2028   boardY = CW_USEDEFAULT;\r
2029   analysisX = CW_USEDEFAULT; \r
2030   analysisY = CW_USEDEFAULT; \r
2031   analysisW = CW_USEDEFAULT;\r
2032   analysisH = CW_USEDEFAULT;\r
2033   commentX = CW_USEDEFAULT; \r
2034   commentY = CW_USEDEFAULT; \r
2035   commentW = CW_USEDEFAULT;\r
2036   commentH = CW_USEDEFAULT;\r
2037   editTagsX = CW_USEDEFAULT; \r
2038   editTagsY = CW_USEDEFAULT; \r
2039   editTagsW = CW_USEDEFAULT;\r
2040   editTagsH = CW_USEDEFAULT;\r
2041   icsTextMenuString = ICS_TEXT_MENU_DEFAULT;\r
2042   icsNames = ICS_NAMES;\r
2043   firstChessProgramNames = FCP_NAMES;\r
2044   secondChessProgramNames = SCP_NAMES;\r
2045   appData.initialMode = "";\r
2046   appData.variant = "normal";\r
2047   appData.firstProtocolVersion = PROTOVER;\r
2048   appData.secondProtocolVersion = PROTOVER;\r
2049   appData.showButtonBar = TRUE;\r
2050 \r
2051    /* [AS] New properties (see comments in header file) */\r
2052   appData.firstScoreIsAbsolute = FALSE;\r
2053   appData.secondScoreIsAbsolute = FALSE;\r
2054   appData.saveExtendedInfoInPGN = FALSE;\r
2055   appData.hideThinkingFromHuman = FALSE;\r
2056   appData.liteBackTextureFile = "";\r
2057   appData.liteBackTextureMode = BACK_TEXTURE_MODE_PLAIN;\r
2058   appData.darkBackTextureFile = "";\r
2059   appData.darkBackTextureMode = BACK_TEXTURE_MODE_PLAIN;\r
2060   appData.renderPiecesWithFont = "";\r
2061   appData.fontToPieceTable = "";\r
2062   appData.fontBackColorWhite = 0;\r
2063   appData.fontForeColorWhite = 0;\r
2064   appData.fontBackColorBlack = 0;\r
2065   appData.fontForeColorBlack = 0;\r
2066   appData.fontPieceSize = 80;\r
2067   appData.overrideLineGap = 1;\r
2068   appData.adjudicateLossThreshold = 0;\r
2069   appData.delayBeforeQuit = 0;\r
2070   appData.delayAfterQuit = 0;\r
2071   appData.nameOfDebugFile = "winboard.debug";\r
2072   appData.pgnEventHeader = "Computer Chess Game";\r
2073   appData.defaultFrcPosition = -1;\r
2074   appData.gameListTags = GLT_DEFAULT_TAGS;\r
2075   appData.saveOutOfBookInfo = TRUE;\r
2076   appData.showEvalInMoveHistory = TRUE;\r
2077   appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );\r
2078   appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );\r
2079   appData.highlightMoveWithArrow = FALSE;\r
2080   appData.highlightArrowColor = ParseColorName( "#FFFF80" );\r
2081   appData.useStickyWindows = TRUE;\r
2082   appData.adjudicateDrawMoves = 0;\r
2083   appData.autoDisplayComment = TRUE;\r
2084   appData.autoDisplayTags = TRUE;\r
2085   appData.firstIsUCI = FALSE;\r
2086   appData.secondIsUCI = FALSE;\r
2087   appData.firstHasOwnBookUCI = TRUE;\r
2088   appData.secondHasOwnBookUCI = TRUE;\r
2089   appData.polyglotDir = "";\r
2090   appData.usePolyglotBook = FALSE;\r
2091   appData.polyglotBook = "";\r
2092   appData.defaultHashSize = 64;\r
2093   appData.defaultCacheSizeEGTB = 4;\r
2094   appData.defaultPathEGTB = "c:\\egtb";\r
2095   appData.firstOptions = "";\r
2096   appData.secondOptions = "";\r
2097 \r
2098   InitWindowPlacement( &wpGameList );\r
2099   InitWindowPlacement( &wpMoveHistory );\r
2100   InitWindowPlacement( &wpEvalGraph );\r
2101   InitWindowPlacement( &wpEngineOutput );\r
2102   InitWindowPlacement( &wpConsole );\r
2103 \r
2104   /* [HGM] User-selectable board size, adjudication control, miscellaneous */\r
2105   appData.NrFiles      = -1;\r
2106   appData.NrRanks      = -1;\r
2107   appData.holdingsSize = -1;\r
2108   appData.testClaims   = FALSE;\r
2109   appData.checkMates   = FALSE;\r
2110   appData.materialDraws= FALSE;\r
2111   appData.trivialDraws = FALSE;\r
2112   appData.ruleMoves    = 51;\r
2113   appData.drawRepeats  = 6;\r
2114   appData.matchPause   = 10000;\r
2115   appData.alphaRank    = FALSE;\r
2116   appData.allWhite     = FALSE;\r
2117   appData.upsideDown   = FALSE;\r
2118   appData.serverPause  = 15;\r
2119   appData.serverMovesName   = NULL;\r
2120   appData.suppressLoadMoves = FALSE;\r
2121   appData.firstTimeOdds  = 1;\r
2122   appData.secondTimeOdds = 1;\r
2123   appData.firstAccumulateTC  = 1; // combine previous and current sessions\r
2124   appData.secondAccumulateTC = 1;\r
2125   appData.firstNPS  = -1; // [HGM] nps: use wall-clock time\r
2126   appData.secondNPS = -1;\r
2127   appData.engineComments = 1;\r
2128   appData.smpCores = 1; // [HGM] SMP: max nr of cores\r
2129   appData.egtFormats = "";\r
2130 \r
2131 #ifdef ZIPPY\r
2132   appData.zippyTalk = ZIPPY_TALK;\r
2133   appData.zippyPlay = ZIPPY_PLAY;\r
2134   appData.zippyLines = ZIPPY_LINES;\r
2135   appData.zippyPinhead = ZIPPY_PINHEAD;\r
2136   appData.zippyPassword = ZIPPY_PASSWORD;\r
2137   appData.zippyPassword2 = ZIPPY_PASSWORD2;\r
2138   appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;\r
2139   appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;\r
2140   appData.zippyUseI = ZIPPY_USE_I;\r
2141   appData.zippyBughouse = ZIPPY_BUGHOUSE;\r
2142   appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;\r
2143   appData.zippyGameEnd = ZIPPY_GAME_END;\r
2144   appData.zippyGameStart = ZIPPY_GAME_START;\r
2145   appData.zippyAdjourn = ZIPPY_ADJOURN;\r
2146   appData.zippyAbort = ZIPPY_ABORT;\r
2147   appData.zippyVariants = ZIPPY_VARIANTS;\r
2148   appData.zippyMaxGames = ZIPPY_MAX_GAMES;\r
2149   appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;\r
2150 #endif\r
2151 \r
2152   /* Point font array elements to structures and\r
2153      parse default font names */\r
2154   for (i=0; i<NUM_FONTS; i++) {\r
2155     for (j=0; j<NUM_SIZES; j++) {\r
2156       font[j][i] = &fontRec[j][i];\r
2157       ParseFontName(font[j][i]->def, &font[j][i]->mfp);\r
2158     }\r
2159   }\r
2160   \r
2161   /* Parse default settings file if any */\r
2162   if (ParseSettingsFile(settingsFileName, buf)) {\r
2163     settingsFileName = strdup(buf);\r
2164   }\r
2165 \r
2166   /* Parse command line */\r
2167   ParseArgs(StringGet, &lpCmdLine);\r
2168 \r
2169   /* [HGM] make sure board size is acceptable */\r
2170   if(appData.NrFiles > BOARD_SIZE ||\r
2171      appData.NrRanks > BOARD_SIZE   )\r
2172       DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);\r
2173 \r
2174   /* [HGM] After parsing the options from the .ini file, and overruling them\r
2175    * with options from the command line, we now make an even higher priority\r
2176    * overrule by WB options attached to the engine command line. This so that\r
2177    * tournament managers can use WB options (such as /timeOdds) that follow\r
2178    * the engines.\r
2179    */\r
2180   if(appData.firstChessProgram != NULL) {\r
2181       char *p = StrStr(appData.firstChessProgram, "WBopt");\r
2182       static char *f = "first";\r
2183       char buf[MSG_SIZ], *q = buf;\r
2184       if(p != NULL) { // engine command line contains WinBoard options\r
2185           sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"\r
2186           ParseArgs(StringGet, &q);\r
2187           p[-1] = 0; // cut them offengine command line\r
2188       }\r
2189   }\r
2190   // now do same for second chess program\r
2191   if(appData.secondChessProgram != NULL) {\r
2192       char *p = StrStr(appData.secondChessProgram, "WBopt");\r
2193       static char *s = "second";\r
2194       char buf[MSG_SIZ], *q = buf;\r
2195       if(p != NULL) { // engine command line contains WinBoard options\r
2196           sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"\r
2197           ParseArgs(StringGet, &q);\r
2198           p[-1] = 0; // cut them offengine command line\r
2199       }\r
2200   }\r
2201 \r
2202 \r
2203   /* Propagate options that affect others */\r
2204   if (appData.matchMode || appData.matchGames) chessProgram = TRUE;\r
2205   if (appData.icsActive || appData.noChessProgram) {\r
2206      chessProgram = FALSE;  /* not local chess program mode */\r
2207   }\r
2208 \r
2209   /* Open startup dialog if needed */\r
2210   if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||\r
2211       (appData.icsActive && *appData.icsHost == NULLCHAR) ||\r
2212       (chessProgram && (*appData.firstChessProgram == NULLCHAR ||\r
2213                         *appData.secondChessProgram == NULLCHAR))) {\r
2214     FARPROC lpProc;\r
2215     \r
2216     lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);\r
2217     DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);\r
2218     FreeProcInstance(lpProc);\r
2219   }\r
2220 \r
2221   /* Make sure save files land in the right (?) directory */\r
2222   if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {\r
2223     appData.saveGameFile = strdup(buf);\r
2224   }\r
2225   if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {\r
2226     appData.savePositionFile = strdup(buf);\r
2227   }\r
2228 \r
2229   /* Finish initialization for fonts and sounds */\r
2230   for (i=0; i<NUM_FONTS; i++) {\r
2231     for (j=0; j<NUM_SIZES; j++) {\r
2232       CreateFontInMF(font[j][i]);\r
2233     }\r
2234   }\r
2235   /* xboard, and older WinBoards, controlled the move sound with the\r
2236      appData.ringBellAfterMoves option.  In the current WinBoard, we\r
2237      always turn the option on (so that the backend will call us),\r
2238      then let the user turn the sound off by setting it to silence if\r
2239      desired.  To accommodate old winboard.ini files saved by old\r
2240      versions of WinBoard, we also turn off the sound if the option\r
2241      was initially set to false. */\r
2242   if (!appData.ringBellAfterMoves) {\r
2243     sounds[(int)SoundMove].name = strdup("");\r
2244     appData.ringBellAfterMoves = TRUE;\r
2245   }\r
2246   GetCurrentDirectory(MSG_SIZ, currDir);\r
2247   SetCurrentDirectory(installDir);\r
2248   LoadAllSounds();\r
2249   SetCurrentDirectory(currDir);\r
2250 \r
2251   p = icsTextMenuString;\r
2252   if (p[0] == '@') {\r
2253     FILE* f = fopen(p + 1, "r");\r
2254     if (f == NULL) {\r
2255       DisplayFatalError(p + 1, errno, 2);\r
2256       return;\r
2257     }\r
2258     i = fread(buf, 1, sizeof(buf)-1, f);\r
2259     fclose(f);\r
2260     buf[i] = NULLCHAR;\r
2261     p = buf;\r
2262   }\r
2263   ParseIcsTextMenu(strdup(p));\r
2264 }\r
2265 \r
2266 \r
2267 VOID\r
2268 InitMenuChecks()\r
2269 {\r
2270   HMENU hmenu = GetMenu(hwndMain);\r
2271 \r
2272   (void) EnableMenuItem(hmenu, IDM_CommPort,\r
2273                         MF_BYCOMMAND|((appData.icsActive &&\r
2274                                        *appData.icsCommPort != NULLCHAR) ?\r
2275                                       MF_ENABLED : MF_GRAYED));\r
2276   (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,\r
2277                        MF_BYCOMMAND|(saveSettingsOnExit ?\r
2278                                      MF_CHECKED : MF_UNCHECKED));\r
2279 }\r
2280 \r
2281 \r
2282 VOID\r
2283 SaveSettings(char* name)\r
2284 {\r
2285   FILE *f;\r
2286   ArgDescriptor *ad;\r
2287   WINDOWPLACEMENT wp;\r
2288   char dir[MSG_SIZ];\r
2289 \r
2290   if (!hwndMain) return;\r
2291 \r
2292   GetCurrentDirectory(MSG_SIZ, dir);\r
2293   SetCurrentDirectory(installDir);\r
2294   f = fopen(name, "w");\r
2295   SetCurrentDirectory(dir);\r
2296   if (f == NULL) {\r
2297     DisplayError(name, errno);\r
2298     return;\r
2299   }\r
2300   fprintf(f, ";\n");\r
2301   fprintf(f, "; %s %s.%s Save Settings file\n", PRODUCT, VERSION, PATCHLEVEL);\r
2302   fprintf(f, ";\n");\r
2303   fprintf(f, "; You can edit the values of options that are already set in this file,\n");\r
2304   fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");\r
2305   fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");\r
2306   fprintf(f, ";\n");\r
2307 \r
2308   wp.length = sizeof(WINDOWPLACEMENT);\r
2309   GetWindowPlacement(hwndMain, &wp);\r
2310   boardX = wp.rcNormalPosition.left;\r
2311   boardY = wp.rcNormalPosition.top;\r
2312 \r
2313   if (hwndConsole) {\r
2314     GetWindowPlacement(hwndConsole, &wp);\r
2315     wpConsole.x = wp.rcNormalPosition.left;\r
2316     wpConsole.y = wp.rcNormalPosition.top;\r
2317     wpConsole.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
2318     wpConsole.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
2319   }\r
2320 \r
2321   if (analysisDialog) {\r
2322     GetWindowPlacement(analysisDialog, &wp);\r
2323     analysisX = wp.rcNormalPosition.left;\r
2324     analysisY = wp.rcNormalPosition.top;\r
2325     analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
2326     analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
2327   }\r
2328 \r
2329   if (commentDialog) {\r
2330     GetWindowPlacement(commentDialog, &wp);\r
2331     commentX = wp.rcNormalPosition.left;\r
2332     commentY = wp.rcNormalPosition.top;\r
2333     commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
2334     commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
2335   }\r
2336 \r
2337   if (editTagsDialog) {\r
2338     GetWindowPlacement(editTagsDialog, &wp);\r
2339     editTagsX = wp.rcNormalPosition.left;\r
2340     editTagsY = wp.rcNormalPosition.top;\r
2341     editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
2342     editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
2343   }\r
2344 \r
2345   if (gameListDialog) {\r
2346     GetWindowPlacement(gameListDialog, &wp);\r
2347     wpGameList.x = wp.rcNormalPosition.left;\r
2348     wpGameList.y = wp.rcNormalPosition.top;\r
2349     wpGameList.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
2350     wpGameList.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
2351   }\r
2352 \r
2353   /* [AS] Move history */\r
2354   wpMoveHistory.visible = MoveHistoryIsUp();\r
2355   \r
2356   if( moveHistoryDialog ) {\r
2357     GetWindowPlacement(moveHistoryDialog, &wp);\r
2358     wpMoveHistory.x = wp.rcNormalPosition.left;\r
2359     wpMoveHistory.y = wp.rcNormalPosition.top;\r
2360     wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
2361     wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
2362   }\r
2363 \r
2364   /* [AS] Eval graph */\r
2365   wpEvalGraph.visible = EvalGraphIsUp();\r
2366 \r
2367   if( evalGraphDialog ) {\r
2368     GetWindowPlacement(evalGraphDialog, &wp);\r
2369     wpEvalGraph.x = wp.rcNormalPosition.left;\r
2370     wpEvalGraph.y = wp.rcNormalPosition.top;\r
2371     wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
2372     wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
2373   }\r
2374 \r
2375   /* [AS] Engine output */\r
2376   wpEngineOutput.visible = EngineOutputIsUp();\r
2377 \r
2378   if( engineOutputDialog ) {\r
2379     GetWindowPlacement(engineOutputDialog, &wp);\r
2380     wpEngineOutput.x = wp.rcNormalPosition.left;\r
2381     wpEngineOutput.y = wp.rcNormalPosition.top;\r
2382     wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
2383     wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
2384   }\r
2385 \r
2386   for (ad = argDescriptors; ad->argName != NULL; ad++) {\r
2387     if (!ad->save) continue;\r
2388     switch (ad->argType) {\r
2389     case ArgString:\r
2390       {\r
2391         char *p = *(char **)ad->argLoc;\r
2392         if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {\r
2393           /* Quote multiline values or \-containing values\r
2394              with { } if possible */\r
2395           fprintf(f, "/%s={%s}\n", ad->argName, p);\r
2396         } else {\r
2397           /* Else quote with " " */\r
2398           fprintf(f, "/%s=\"", ad->argName);\r
2399           while (*p) {\r
2400             if (*p == '\n') fprintf(f, "\n");\r
2401             else if (*p == '\r') fprintf(f, "\\r");\r
2402             else if (*p == '\t') fprintf(f, "\\t");\r
2403             else if (*p == '\b') fprintf(f, "\\b");\r
2404             else if (*p == '\f') fprintf(f, "\\f");\r
2405             else if (*p < ' ') fprintf(f, "\\%03o", *p);\r
2406             else if (*p == '\"') fprintf(f, "\\\"");\r
2407             else if (*p == '\\') fprintf(f, "\\\\");\r
2408             else putc(*p, f);\r
2409             p++;\r
2410           }\r
2411           fprintf(f, "\"\n");\r
2412         }\r
2413       }\r
2414       break;\r
2415     case ArgInt:\r
2416     case ArgZ:\r
2417       fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);\r
2418       break;\r
2419     case ArgX:\r
2420       fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardX); // [HGM] placement: stor relative value\r
2421       break;\r
2422     case ArgY:\r
2423       fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc - boardY);\r
2424       break;\r
2425     case ArgFloat:\r
2426       fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);\r
2427       break;\r
2428     case ArgBoolean:\r
2429       fprintf(f, "/%s=%s\n", ad->argName, \r
2430         (*(Boolean *)ad->argLoc) ? "true" : "false");\r
2431       break;\r
2432     case ArgTrue:\r
2433       if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);\r
2434       break;\r
2435     case ArgFalse:\r
2436       if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);\r
2437       break;\r
2438     case ArgColor:\r
2439       {\r
2440         COLORREF color = *(COLORREF *)ad->argLoc;\r
2441         fprintf(f, "/%s=#%02lx%02lx%02lx\n", ad->argName, \r
2442           color&0xff, (color>>8)&0xff, (color>>16)&0xff);\r
2443       }\r
2444       break;\r
2445     case ArgAttribs:\r
2446       {\r
2447         MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];\r
2448         fprintf(f, "/%s=\"%s%s%s%s%s#%02lx%02lx%02lx\"\n", ad->argName,\r
2449           (ta->effects & CFE_BOLD) ? "b" : "",\r
2450           (ta->effects & CFE_ITALIC) ? "i" : "",\r
2451           (ta->effects & CFE_UNDERLINE) ? "u" : "",\r
2452           (ta->effects & CFE_STRIKEOUT) ? "s" : "",\r
2453           (ta->effects) ? " " : "",\r
2454           ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);\r
2455       }\r
2456       break;\r
2457     case ArgFilename:\r
2458       if (strchr(*(char **)ad->argLoc, '\"')) {\r
2459         fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);\r
2460       } else {\r
2461         fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);\r
2462       }\r
2463       break;\r
2464     case ArgBoardSize:\r
2465       fprintf(f, "/%s=%s\n", ad->argName,\r
2466               sizeInfo[*(BoardSize *)ad->argLoc].name);\r
2467       break;\r
2468     case ArgFont:\r
2469       {\r
2470         int bs;\r
2471         for (bs=0; bs<NUM_SIZES; bs++) {\r
2472           MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;\r
2473           fprintf(f, "/size=%s ", sizeInfo[bs].name);\r
2474           fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n",\r
2475             ad->argName, mfp->faceName, mfp->pointSize,\r
2476             mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",\r
2477             mfp->bold ? "b" : "",\r
2478             mfp->italic ? "i" : "",\r
2479             mfp->underline ? "u" : "",\r
2480             mfp->strikeout ? "s" : "");\r
2481         }\r
2482       }\r
2483       break;\r
2484     case ArgCommSettings:\r
2485       PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);\r
2486     case ArgNone:\r
2487     case ArgSettingsFilename: ;\r
2488     }\r
2489   }\r
2490   fclose(f);\r
2491 }\r
2492 \r
2493 \r
2494 \r
2495 /*---------------------------------------------------------------------------*\\r
2496  *\r
2497  * GDI board drawing routines\r
2498  *\r
2499 \*---------------------------------------------------------------------------*/\r
2500 \r
2501 /* [AS] Draw square using background texture */\r
2502 static void DrawTile( int dx, int dy, int dw, int dh, HDC dst, HDC src, int mode, int sx, int sy )\r
2503 {\r
2504     XFORM   x;\r
2505 \r
2506     if( mode == 0 ) {\r
2507         return; /* Should never happen! */\r
2508     }\r
2509 \r
2510     SetGraphicsMode( dst, GM_ADVANCED );\r
2511 \r
2512     switch( mode ) {\r
2513     case 1:\r
2514         /* Identity */\r
2515         break;\r
2516     case 2:\r
2517         /* X reflection */\r
2518         x.eM11 = -1.0;\r
2519         x.eM12 = 0;\r
2520         x.eM21 = 0;\r
2521         x.eM22 = 1.0;\r
2522         x.eDx = (FLOAT) dw + dx - 1;\r
2523         x.eDy = 0;\r
2524         dx = 0;\r
2525         SetWorldTransform( dst, &x );\r
2526         break;\r
2527     case 3:\r
2528         /* Y reflection */\r
2529         x.eM11 = 1.0;\r
2530         x.eM12 = 0;\r
2531         x.eM21 = 0;\r
2532         x.eM22 = -1.0;\r
2533         x.eDx = 0;\r
2534         x.eDy = (FLOAT) dh + dy - 1;\r
2535         dy = 0;\r
2536         SetWorldTransform( dst, &x );\r
2537         break;\r
2538     case 4:\r
2539         /* X/Y flip */\r
2540         x.eM11 = 0;\r
2541         x.eM12 = 1.0;\r
2542         x.eM21 = 1.0;\r
2543         x.eM22 = 0;\r
2544         x.eDx = (FLOAT) dx;\r
2545         x.eDy = (FLOAT) dy;\r
2546         dx = 0;\r
2547         dy = 0;\r
2548         SetWorldTransform( dst, &x );\r
2549         break;\r
2550     }\r
2551 \r
2552     BitBlt( dst, dx, dy, dw, dh, src, sx, sy, SRCCOPY );\r
2553 \r
2554     x.eM11 = 1.0;\r
2555     x.eM12 = 0;\r
2556     x.eM21 = 0;\r
2557     x.eM22 = 1.0;\r
2558     x.eDx = 0;\r
2559     x.eDy = 0;\r
2560     SetWorldTransform( dst, &x );\r
2561 \r
2562     ModifyWorldTransform( dst, 0, MWT_IDENTITY );\r
2563 }\r
2564 \r
2565 /* [AS] [HGM] Make room for more piece types, so all pieces can be different */\r
2566 enum {\r
2567     PM_WP = (int) WhitePawn, \r
2568     PM_WN = (int) WhiteKnight, \r
2569     PM_WB = (int) WhiteBishop, \r
2570     PM_WR = (int) WhiteRook, \r
2571     PM_WQ = (int) WhiteQueen, \r
2572     PM_WF = (int) WhiteFerz, \r
2573     PM_WW = (int) WhiteWazir, \r
2574     PM_WE = (int) WhiteAlfil, \r
2575     PM_WM = (int) WhiteMan, \r
2576     PM_WO = (int) WhiteCannon, \r
2577     PM_WU = (int) WhiteUnicorn, \r
2578     PM_WH = (int) WhiteNightrider, \r
2579     PM_WA = (int) WhiteAngel, \r
2580     PM_WC = (int) WhiteMarshall, \r
2581     PM_WAB = (int) WhiteCardinal, \r
2582     PM_WD = (int) WhiteDragon, \r
2583     PM_WL = (int) WhiteLance, \r
2584     PM_WS = (int) WhiteCobra, \r
2585     PM_WV = (int) WhiteFalcon, \r
2586     PM_WSG = (int) WhiteSilver, \r
2587     PM_WG = (int) WhiteGrasshopper, \r
2588     PM_WK = (int) WhiteKing,\r
2589     PM_BP = (int) BlackPawn, \r
2590     PM_BN = (int) BlackKnight, \r
2591     PM_BB = (int) BlackBishop, \r
2592     PM_BR = (int) BlackRook, \r
2593     PM_BQ = (int) BlackQueen, \r
2594     PM_BF = (int) BlackFerz, \r
2595     PM_BW = (int) BlackWazir, \r
2596     PM_BE = (int) BlackAlfil, \r
2597     PM_BM = (int) BlackMan,\r
2598     PM_BO = (int) BlackCannon, \r
2599     PM_BU = (int) BlackUnicorn, \r
2600     PM_BH = (int) BlackNightrider, \r
2601     PM_BA = (int) BlackAngel, \r
2602     PM_BC = (int) BlackMarshall, \r
2603     PM_BG = (int) BlackGrasshopper, \r
2604     PM_BAB = (int) BlackCardinal,\r
2605     PM_BD = (int) BlackDragon,\r
2606     PM_BL = (int) BlackLance,\r
2607     PM_BS = (int) BlackCobra,\r
2608     PM_BV = (int) BlackFalcon,\r
2609     PM_BSG = (int) BlackSilver,\r
2610     PM_BK = (int) BlackKing\r
2611 };\r
2612 \r
2613 static HFONT hPieceFont = NULL;\r
2614 static HBITMAP hPieceMask[(int) EmptySquare];\r
2615 static HBITMAP hPieceFace[(int) EmptySquare];\r
2616 static int fontBitmapSquareSize = 0;\r
2617 static char pieceToFontChar[(int) EmptySquare] =\r
2618                               { 'p', 'n', 'b', 'r', 'q', \r
2619                       'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',\r
2620                       'k', 'o', 'm', 'v', 't', 'w', \r
2621                       'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',\r
2622                                                               'l' };\r
2623 \r
2624 extern BOOL SetCharTable( char *table, const char * map );\r
2625 /* [HGM] moved to backend.c */\r
2626 \r
2627 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )\r
2628 {\r
2629     HBRUSH hbrush;\r
2630     BYTE r1 = GetRValue( color );\r
2631     BYTE g1 = GetGValue( color );\r
2632     BYTE b1 = GetBValue( color );\r
2633     BYTE r2 = r1 / 2;\r
2634     BYTE g2 = g1 / 2;\r
2635     BYTE b2 = b1 / 2;\r
2636     RECT rc;\r
2637 \r
2638     /* Create a uniform background first */\r
2639     hbrush = CreateSolidBrush( color );\r
2640     SetRect( &rc, 0, 0, squareSize, squareSize );\r
2641     FillRect( hdc, &rc, hbrush );\r
2642     DeleteObject( hbrush );\r
2643     \r
2644     if( mode == 1 ) {\r
2645         /* Vertical gradient, good for pawn, knight and rook, less for queen and king */\r
2646         int steps = squareSize / 2;\r
2647         int i;\r
2648 \r
2649         for( i=0; i<steps; i++ ) {\r
2650             BYTE r = r1 - (r1-r2) * i / steps;\r
2651             BYTE g = g1 - (g1-g2) * i / steps;\r
2652             BYTE b = b1 - (b1-b2) * i / steps;\r
2653 \r
2654             hbrush = CreateSolidBrush( RGB(r,g,b) );\r
2655             SetRect( &rc, i + squareSize - steps, 0, i + squareSize - steps + 1, squareSize );\r
2656             FillRect( hdc, &rc, hbrush );\r
2657             DeleteObject(hbrush);\r
2658         }\r
2659     }\r
2660     else if( mode == 2 ) {\r
2661         /* Diagonal gradient, good more or less for every piece */\r
2662         POINT triangle[3];\r
2663         HPEN hpen = SelectObject( hdc, GetStockObject(NULL_PEN) );\r
2664         HBRUSH hbrush_old;\r
2665         int steps = squareSize;\r
2666         int i;\r
2667 \r
2668         triangle[0].x = squareSize - steps;\r
2669         triangle[0].y = squareSize;\r
2670         triangle[1].x = squareSize;\r
2671         triangle[1].y = squareSize;\r
2672         triangle[2].x = squareSize;\r
2673         triangle[2].y = squareSize - steps;\r
2674 \r
2675         for( i=0; i<steps; i++ ) {\r
2676             BYTE r = r1 - (r1-r2) * i / steps;\r
2677             BYTE g = g1 - (g1-g2) * i / steps;\r
2678             BYTE b = b1 - (b1-b2) * i / steps;\r
2679 \r
2680             hbrush = CreateSolidBrush( RGB(r,g,b) );\r
2681             hbrush_old = SelectObject( hdc, hbrush );\r
2682             Polygon( hdc, triangle, 3 );\r
2683             SelectObject( hdc, hbrush_old );\r
2684             DeleteObject(hbrush);\r
2685             triangle[0].x++;\r
2686             triangle[2].y++;\r
2687         }\r
2688 \r
2689         SelectObject( hdc, hpen );\r
2690     }\r
2691 }\r
2692 \r
2693 /*\r
2694     [AS] The method I use to create the bitmaps it a bit tricky, but it\r
2695     seems to work ok. The main problem here is to find the "inside" of a chess\r
2696     piece: follow the steps as explained below.\r
2697 */\r
2698 static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )\r
2699 {\r
2700     HBITMAP hbm;\r
2701     HBITMAP hbm_old;\r
2702     COLORREF chroma = RGB(0xFF,0x00,0xFF);\r
2703     RECT rc;\r
2704     SIZE sz;\r
2705     POINT pt;\r
2706     int backColor = whitePieceColor; \r
2707     int foreColor = blackPieceColor;\r
2708     \r
2709     if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {\r
2710         backColor = appData.fontBackColorWhite;\r
2711         foreColor = appData.fontForeColorWhite;\r
2712     }\r
2713     else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {\r
2714         backColor = appData.fontBackColorBlack;\r
2715         foreColor = appData.fontForeColorBlack;\r
2716     }\r
2717 \r
2718     /* Mask */\r
2719     hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );\r
2720 \r
2721     hbm_old = SelectObject( hdc, hbm );\r
2722 \r
2723     rc.left = 0;\r
2724     rc.top = 0;\r
2725     rc.right = squareSize;\r
2726     rc.bottom = squareSize;\r
2727 \r
2728     /* Step 1: background is now black */\r
2729     FillRect( hdc, &rc, GetStockObject(BLACK_BRUSH) );\r
2730 \r
2731     GetTextExtentPoint32( hdc, &pieceToFontChar[index], 1, &sz );\r
2732 \r
2733     pt.x = (squareSize - sz.cx) / 2;\r
2734     pt.y = (squareSize - sz.cy) / 2;\r
2735 \r
2736     SetBkMode( hdc, TRANSPARENT );\r
2737     SetTextColor( hdc, chroma );\r
2738     /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */\r
2739     TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );\r
2740 \r
2741     SelectObject( hdc, GetStockObject(WHITE_BRUSH) );\r
2742     /* Step 3: the area outside the piece is filled with white */\r
2743 //    FloodFill( hdc, 0, 0, chroma );\r
2744     ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );\r
2745     ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big\r
2746     ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );\r
2747     ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );\r
2748     SelectObject( hdc, GetStockObject(BLACK_BRUSH) );\r
2749     /* \r
2750         Step 4: this is the tricky part, the area inside the piece is filled with black,\r
2751         but if the start point is not inside the piece we're lost!\r
2752         There should be a better way to do this... if we could create a region or path\r
2753         from the fill operation we would be fine for example.\r
2754     */\r
2755 //    FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );\r
2756     ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );\r
2757 \r
2758     {   /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */\r
2759         HDC dc2 = CreateCompatibleDC( hdc_window );\r
2760         HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );\r
2761 \r
2762         SelectObject( dc2, bm2 );\r
2763         BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy\r
2764         BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );\r
2765         BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );\r
2766         BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );\r
2767         BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );\r
2768 \r
2769         DeleteDC( dc2 );\r
2770         DeleteObject( bm2 );\r
2771     }\r
2772 \r
2773     SetTextColor( hdc, 0 );\r
2774     /* \r
2775         Step 5: some fonts have "disconnected" areas that are skipped by the fill:\r
2776         draw the piece again in black for safety.\r
2777     */\r
2778     TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );\r
2779 \r
2780     SelectObject( hdc, hbm_old );\r
2781 \r
2782     if( hPieceMask[index] != NULL ) {\r
2783         DeleteObject( hPieceMask[index] );\r
2784     }\r
2785 \r
2786     hPieceMask[index] = hbm;\r
2787 \r
2788     /* Face */\r
2789     hbm = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );\r
2790 \r
2791     SelectObject( hdc, hbm );\r
2792 \r
2793     {\r
2794         HDC dc1 = CreateCompatibleDC( hdc_window );\r
2795         HDC dc2 = CreateCompatibleDC( hdc_window );\r
2796         HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );\r
2797 \r
2798         SelectObject( dc1, hPieceMask[index] );\r
2799         SelectObject( dc2, bm2 );\r
2800         FillRect( dc2, &rc, GetStockObject(WHITE_BRUSH) );\r
2801         BitBlt( dc2, 0, 0, squareSize, squareSize, dc1, 0, 0, SRCINVERT );\r
2802         \r
2803         /* \r
2804             Now dc2 contains the inverse of the piece mask, i.e. a mask that preserves\r
2805             the piece background and deletes (makes transparent) the rest.\r
2806             Thanks to that mask, we are free to paint the background with the greates\r
2807             freedom, as we'll be able to mask off the unwanted parts when finished.\r
2808             We use this, to make gradients and give the pieces a "roundish" look.\r
2809         */\r
2810         SetPieceBackground( hdc, backColor, 2 );\r
2811         BitBlt( hdc, 0, 0, squareSize, squareSize, dc2, 0, 0, SRCAND );\r
2812 \r
2813         DeleteDC( dc2 );\r
2814         DeleteDC( dc1 );\r
2815         DeleteObject( bm2 );\r
2816     }\r
2817 \r
2818     SetTextColor( hdc, foreColor );\r
2819     TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );\r
2820 \r
2821     SelectObject( hdc, hbm_old );\r
2822 \r
2823     if( hPieceFace[index] != NULL ) {\r
2824         DeleteObject( hPieceFace[index] );\r
2825     }\r
2826 \r
2827     hPieceFace[index] = hbm;\r
2828 }\r
2829 \r
2830 static int TranslatePieceToFontPiece( int piece )\r
2831 {\r
2832     switch( piece ) {\r
2833     case BlackPawn:\r
2834         return PM_BP;\r
2835     case BlackKnight:\r
2836         return PM_BN;\r
2837     case BlackBishop:\r
2838         return PM_BB;\r
2839     case BlackRook:\r
2840         return PM_BR;\r
2841     case BlackQueen:\r
2842         return PM_BQ;\r
2843     case BlackKing:\r
2844         return PM_BK;\r
2845     case WhitePawn:\r
2846         return PM_WP;\r
2847     case WhiteKnight:\r
2848         return PM_WN;\r
2849     case WhiteBishop:\r
2850         return PM_WB;\r
2851     case WhiteRook:\r
2852         return PM_WR;\r
2853     case WhiteQueen:\r
2854         return PM_WQ;\r
2855     case WhiteKing:\r
2856         return PM_WK;\r
2857 \r
2858     case BlackAngel:\r
2859         return PM_BA;\r
2860     case BlackMarshall:\r
2861         return PM_BC;\r
2862     case BlackFerz:\r
2863         return PM_BF;\r
2864     case BlackNightrider:\r
2865         return PM_BH;\r
2866     case BlackAlfil:\r
2867         return PM_BE;\r
2868     case BlackWazir:\r
2869         return PM_BW;\r
2870     case BlackUnicorn:\r
2871         return PM_BU;\r
2872     case BlackCannon:\r
2873         return PM_BO;\r
2874     case BlackGrasshopper:\r
2875         return PM_BG;\r
2876     case BlackMan:\r
2877         return PM_BM;\r
2878     case BlackSilver:\r
2879         return PM_BSG;\r
2880     case BlackLance:\r
2881         return PM_BL;\r
2882     case BlackFalcon:\r
2883         return PM_BV;\r
2884     case BlackCobra:\r
2885         return PM_BS;\r
2886     case BlackCardinal:\r
2887         return PM_BAB;\r
2888     case BlackDragon:\r
2889         return PM_BD;\r
2890 \r
2891     case WhiteAngel:\r
2892         return PM_WA;\r
2893     case WhiteMarshall:\r
2894         return PM_WC;\r
2895     case WhiteFerz:\r
2896         return PM_WF;\r
2897     case WhiteNightrider:\r
2898         return PM_WH;\r
2899     case WhiteAlfil:\r
2900         return PM_WE;\r
2901     case WhiteWazir:\r
2902         return PM_WW;\r
2903     case WhiteUnicorn:\r
2904         return PM_WU;\r
2905     case WhiteCannon:\r
2906         return PM_WO;\r
2907     case WhiteGrasshopper:\r
2908         return PM_WG;\r
2909     case WhiteMan:\r
2910         return PM_WM;\r
2911     case WhiteSilver:\r
2912         return PM_WSG;\r
2913     case WhiteLance:\r
2914         return PM_WL;\r
2915     case WhiteFalcon:\r
2916         return PM_WV;\r
2917     case WhiteCobra:\r
2918         return PM_WS;\r
2919     case WhiteCardinal:\r
2920         return PM_WAB;\r
2921     case WhiteDragon:\r
2922         return PM_WD;\r
2923     }\r
2924 \r
2925     return 0;\r
2926 }\r
2927 \r
2928 void CreatePiecesFromFont()\r
2929 {\r
2930     LOGFONT lf;\r
2931     HDC hdc_window = NULL;\r
2932     HDC hdc = NULL;\r
2933     HFONT hfont_old;\r
2934     int fontHeight;\r
2935     int i;\r
2936 \r
2937     if( fontBitmapSquareSize < 0 ) {\r
2938         /* Something went seriously wrong in the past: do not try to recreate fonts! */\r
2939         return;\r
2940     }\r
2941 \r
2942     if( appData.renderPiecesWithFont == NULL || appData.renderPiecesWithFont[0] == NULLCHAR || appData.renderPiecesWithFont[0] == '*' ) {\r
2943         fontBitmapSquareSize = -1;\r
2944         return;\r
2945     }\r
2946 \r
2947     if( fontBitmapSquareSize != squareSize ) {\r
2948         hdc_window = GetDC( hwndMain );\r
2949         hdc = CreateCompatibleDC( hdc_window );\r
2950 \r
2951         if( hPieceFont != NULL ) {\r
2952             DeleteObject( hPieceFont );\r
2953         }\r
2954         else {\r
2955             for( i=0; i<=(int)BlackKing; i++ ) {\r
2956                 hPieceMask[i] = NULL;\r
2957                 hPieceFace[i] = NULL;\r
2958             }\r
2959         }\r
2960 \r
2961         fontHeight = 75;\r
2962 \r
2963         if( appData.fontPieceSize >= 50 && appData.fontPieceSize <= 150 ) {\r
2964             fontHeight = appData.fontPieceSize;\r
2965         }\r
2966 \r
2967         fontHeight = (fontHeight * squareSize) / 100;\r
2968 \r
2969         lf.lfHeight = -MulDiv( fontHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72 );\r
2970         lf.lfWidth = 0;\r
2971         lf.lfEscapement = 0;\r
2972         lf.lfOrientation = 0;\r
2973         lf.lfWeight = FW_NORMAL;\r
2974         lf.lfItalic = 0;\r
2975         lf.lfUnderline = 0;\r
2976         lf.lfStrikeOut = 0;\r
2977         lf.lfCharSet = DEFAULT_CHARSET;\r
2978         lf.lfOutPrecision = OUT_DEFAULT_PRECIS;\r
2979         lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;\r
2980         lf.lfQuality = PROOF_QUALITY;\r
2981         lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;\r
2982         strncpy( lf.lfFaceName, appData.renderPiecesWithFont, sizeof(lf.lfFaceName) );\r
2983         lf.lfFaceName[ sizeof(lf.lfFaceName) - 1 ] = '\0';\r
2984 \r
2985         hPieceFont = CreateFontIndirect( &lf );\r
2986 \r
2987         if( hPieceFont == NULL ) {\r
2988             fontBitmapSquareSize = -2;\r
2989         }\r
2990         else {\r
2991             /* Setup font-to-piece character table */\r
2992             if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {\r
2993                 /* No (or wrong) global settings, try to detect the font */\r
2994                 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {\r
2995                     /* Alpha */\r
2996                     SetCharTable(pieceToFontChar, "phbrqkojntwl");\r
2997                 }\r
2998                 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {\r
2999                     /* DiagramTT* family */\r
3000                     SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");\r
3001                 }\r
3002                 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {\r
3003                     /* Fairy symbols */\r
3004                      SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");\r
3005                 }\r
3006                 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {\r
3007                     /* Good Companion (Some characters get warped as literal :-( */\r
3008                     char s[] = "1cmWG0ñueOS¯®oYI23wgQU";\r
3009                     s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;\r
3010                     SetCharTable(pieceToFontChar, s);\r
3011                 }\r
3012                 else {\r
3013                     /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */\r
3014                     SetCharTable(pieceToFontChar, "pnbrqkomvtwl");\r
3015                 }\r
3016             }\r
3017 \r
3018             /* Create bitmaps */\r
3019             hfont_old = SelectObject( hdc, hPieceFont );\r
3020 #if 0\r
3021             CreatePieceMaskFromFont( hdc_window, hdc, PM_WP );\r
3022             CreatePieceMaskFromFont( hdc_window, hdc, PM_WN );\r
3023             CreatePieceMaskFromFont( hdc_window, hdc, PM_WB );\r
3024             CreatePieceMaskFromFont( hdc_window, hdc, PM_WR );\r
3025             CreatePieceMaskFromFont( hdc_window, hdc, PM_WQ );\r
3026             CreatePieceMaskFromFont( hdc_window, hdc, PM_WK );\r
3027             CreatePieceMaskFromFont( hdc_window, hdc, PM_BP );\r
3028             CreatePieceMaskFromFont( hdc_window, hdc, PM_BN );\r
3029             CreatePieceMaskFromFont( hdc_window, hdc, PM_BB );\r
3030             CreatePieceMaskFromFont( hdc_window, hdc, PM_BR );\r
3031             CreatePieceMaskFromFont( hdc_window, hdc, PM_BQ );\r
3032             CreatePieceMaskFromFont( hdc_window, hdc, PM_BK );\r
3033 \r
3034             CreatePieceMaskFromFont( hdc_window, hdc, PM_WA );\r
3035             CreatePieceMaskFromFont( hdc_window, hdc, PM_WC );\r
3036             CreatePieceMaskFromFont( hdc_window, hdc, PM_WF );\r
3037             CreatePieceMaskFromFont( hdc_window, hdc, PM_WH );\r
3038             CreatePieceMaskFromFont( hdc_window, hdc, PM_WE );\r
3039             CreatePieceMaskFromFont( hdc_window, hdc, PM_WW );\r
3040             CreatePieceMaskFromFont( hdc_window, hdc, PM_WU );\r
3041             CreatePieceMaskFromFont( hdc_window, hdc, PM_WO );\r
3042             CreatePieceMaskFromFont( hdc_window, hdc, PM_WG );\r
3043             CreatePieceMaskFromFont( hdc_window, hdc, PM_WM );\r
3044             CreatePieceMaskFromFont( hdc_window, hdc, PM_WSG );\r
3045             CreatePieceMaskFromFont( hdc_window, hdc, PM_WV );\r
3046             CreatePieceMaskFromFont( hdc_window, hdc, PM_WAB );\r
3047             CreatePieceMaskFromFont( hdc_window, hdc, PM_WD );\r
3048             CreatePieceMaskFromFont( hdc_window, hdc, PM_WL );\r
3049             CreatePieceMaskFromFont( hdc_window, hdc, PM_WS );\r
3050             CreatePieceMaskFromFont( hdc_window, hdc, PM_BA );\r
3051             CreatePieceMaskFromFont( hdc_window, hdc, PM_BC );\r
3052             CreatePieceMaskFromFont( hdc_window, hdc, PM_BF );\r
3053             CreatePieceMaskFromFont( hdc_window, hdc, PM_BH );\r
3054             CreatePieceMaskFromFont( hdc_window, hdc, PM_BE );\r
3055             CreatePieceMaskFromFont( hdc_window, hdc, PM_BW );\r
3056             CreatePieceMaskFromFont( hdc_window, hdc, PM_BU );\r
3057             CreatePieceMaskFromFont( hdc_window, hdc, PM_BO );\r
3058             CreatePieceMaskFromFont( hdc_window, hdc, PM_BG );\r
3059             CreatePieceMaskFromFont( hdc_window, hdc, PM_BM );\r
3060             CreatePieceMaskFromFont( hdc_window, hdc, PM_BSG );\r
3061             CreatePieceMaskFromFont( hdc_window, hdc, PM_BV );\r
3062             CreatePieceMaskFromFont( hdc_window, hdc, PM_BAB );\r
3063             CreatePieceMaskFromFont( hdc_window, hdc, PM_BD );\r
3064             CreatePieceMaskFromFont( hdc_window, hdc, PM_BL );\r
3065             CreatePieceMaskFromFont( hdc_window, hdc, PM_BS );\r
3066 #else\r
3067             for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */\r
3068                 if(PieceToChar((ChessSquare)i) != '.')     /* skip unused pieces         */\r
3069                     CreatePieceMaskFromFont( hdc_window, hdc, i );\r
3070 #endif\r
3071             SelectObject( hdc, hfont_old );\r
3072 \r
3073             fontBitmapSquareSize = squareSize;\r
3074         }\r
3075     }\r
3076 \r
3077     if( hdc != NULL ) {\r
3078         DeleteDC( hdc );\r
3079     }\r
3080 \r
3081     if( hdc_window != NULL ) {\r
3082         ReleaseDC( hwndMain, hdc_window );\r
3083     }\r
3084 }\r
3085 \r
3086 HBITMAP\r
3087 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)\r
3088 {\r
3089   char name[128];\r
3090 \r
3091   sprintf(name, "%s%d%s", piece, squareSize, suffix);\r
3092   if (gameInfo.event &&\r
3093       strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&\r
3094       strcmp(name, "k80s") == 0) {\r
3095     strcpy(name, "tim");\r
3096   }\r
3097   return LoadBitmap(hinst, name);\r
3098 }\r
3099 \r
3100 \r
3101 /* Insert a color into the program's logical palette\r
3102    structure.  This code assumes the given color is\r
3103    the result of the RGB or PALETTERGB macro, and it\r
3104    knows how those macros work (which is documented).\r
3105 */\r
3106 VOID\r
3107 InsertInPalette(COLORREF color)\r
3108 {\r
3109   LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);\r
3110 \r
3111   if (pLogPal->palNumEntries++ >= PALETTESIZE) {\r
3112     DisplayFatalError("Too many colors", 0, 1);\r
3113     pLogPal->palNumEntries--;\r
3114     return;\r
3115   }\r
3116 \r
3117   pe->peFlags = (char) 0;\r
3118   pe->peRed = (char) (0xFF & color);\r
3119   pe->peGreen = (char) (0xFF & (color >> 8));\r
3120   pe->peBlue = (char) (0xFF & (color >> 16));\r
3121   return;\r
3122 }\r
3123 \r
3124 \r
3125 VOID\r
3126 InitDrawingColors()\r
3127 {\r
3128   if (pLogPal == NULL) {\r
3129     /* Allocate enough memory for a logical palette with\r
3130      * PALETTESIZE entries and set the size and version fields\r
3131      * of the logical palette structure.\r
3132      */\r
3133     pLogPal = (NPLOGPALETTE)\r
3134       LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +\r
3135                               (sizeof(PALETTEENTRY) * (PALETTESIZE))));\r
3136     pLogPal->palVersion    = 0x300;\r
3137   }\r
3138   pLogPal->palNumEntries = 0;\r
3139 \r
3140   InsertInPalette(lightSquareColor);\r
3141   InsertInPalette(darkSquareColor);\r
3142   InsertInPalette(whitePieceColor);\r
3143   InsertInPalette(blackPieceColor);\r
3144   InsertInPalette(highlightSquareColor);\r
3145   InsertInPalette(premoveHighlightColor);\r
3146 \r
3147   /*  create a logical color palette according the information\r
3148    *  in the LOGPALETTE structure.\r
3149    */\r
3150   hPal = CreatePalette((LPLOGPALETTE) pLogPal);\r
3151 \r
3152   lightSquareBrush = CreateSolidBrush(lightSquareColor);\r
3153   blackSquareBrush = CreateSolidBrush(blackPieceColor);\r
3154   darkSquareBrush = CreateSolidBrush(darkSquareColor);\r
3155   whitePieceBrush = CreateSolidBrush(whitePieceColor);\r
3156   blackPieceBrush = CreateSolidBrush(blackPieceColor);\r
3157   iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));\r
3158   explodeBrush = CreateSolidBrush(highlightSquareColor); // [HGM] atomic\r
3159   /* [AS] Force rendering of the font-based pieces */\r
3160   if( fontBitmapSquareSize > 0 ) {\r
3161     fontBitmapSquareSize = 0;\r
3162   }\r
3163 }\r
3164 \r
3165 \r
3166 int\r
3167 BoardWidth(int boardSize, int n)\r
3168 { /* [HGM] argument n added to allow different width and height */\r
3169   int lineGap = sizeInfo[boardSize].lineGap;\r
3170 \r
3171   if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {\r
3172       lineGap = appData.overrideLineGap;\r
3173   }\r
3174 \r
3175   return (n + 1) * lineGap +\r
3176           n * sizeInfo[boardSize].squareSize;\r
3177 }\r
3178 \r
3179 /* Respond to board resize by dragging edge */\r
3180 VOID\r
3181 ResizeBoard(int newSizeX, int newSizeY, int flags)\r
3182 {\r
3183   BoardSize newSize = NUM_SIZES - 1;\r
3184   static int recurse = 0;\r
3185   if (IsIconic(hwndMain)) return;\r