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