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