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