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