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