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