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