Fix loading of engine-defined PGN games
[xboard.git] / winboard / woptions.c
1 /*\r
2  * woptions.c -- Options dialog box routines for WinBoard\r
3  *\r
4  * Copyright 2000, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.\r
5  *\r
6  * Enhancements Copyright 2005 Alessandro Scotti\r
7  *\r
8  * ------------------------------------------------------------------------\r
9  *\r
10  * GNU XBoard is free software: you can redistribute it and/or modify\r
11  * it under the terms of the GNU General Public License as published by\r
12  * the Free Software Foundation, either version 3 of the License, or (at\r
13  * your option) any later version.\r
14  *\r
15  * GNU XBoard is distributed in the hope that it will be useful, but\r
16  * WITHOUT ANY WARRANTY; without even the implied warranty of\r
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
18  * General Public License for more details.\r
19  *\r
20  * You should have received a copy of the GNU General Public License\r
21  * along with this program. If not, see http://www.gnu.org/licenses/.  *\r
22  *\r
23  *------------------------------------------------------------------------\r
24  ** See the file ChangeLog for a revision history.  */\r
25 \r
26 #include "config.h"\r
27 \r
28 #include <windows.h>   /* required for all Windows applications */\r
29 #include <stdio.h>\r
30 #include <stdlib.h>\r
31 #include <shlobj.h>    /* [AS] Requires NT 4.0 or Win95 */\r
32 #include <ctype.h>\r
33 \r
34 #include "common.h"\r
35 #include "frontend.h"\r
36 #include "winboard.h"\r
37 #include "backend.h"\r
38 #include "woptions.h"\r
39 #include "defaults.h"\r
40 #include <richedit.h>\r
41 \r
42 #if __GNUC__\r
43 #include <errno.h>\r
44 #include <string.h>\r
45 #endif\r
46 \r
47 #define _(s) T_(s)\r
48 #define N_(s) s\r
49 \r
50 /* Imports from winboard.c */\r
51 \r
52 extern MyFont *font[NUM_SIZES][NUM_FONTS];\r
53 extern HINSTANCE hInst;          /* current instance */\r
54 extern HWND hwndMain;            /* root window*/\r
55 extern BOOLEAN alwaysOnTop;\r
56 extern RECT boardRect;\r
57 extern COLORREF lightSquareColor, darkSquareColor, whitePieceColor,\r
58   blackPieceColor, highlightSquareColor, premoveHighlightColor;\r
59 extern HPALETTE hPal;\r
60 extern BoardSize boardSize;\r
61 extern COLORREF consoleBackgroundColor;\r
62 extern MyColorizeAttribs colorizeAttribs[]; /* do I need the size? */\r
63 extern MyTextAttribs textAttribs[];\r
64 extern MySound sounds[];\r
65 extern ColorClass currentColorClass;\r
66 extern HWND hwndConsole;\r
67 extern char *defaultTextAttribs[];\r
68 extern HWND commentDialog;\r
69 extern HWND moveHistoryDialog;\r
70 extern HWND engineOutputDialog;\r
71 extern char installDir[];\r
72 extern HWND hCommPort;    /* currently open comm port */\r
73 extern DCB dcb;\r
74 extern BOOLEAN chessProgram;\r
75 extern int startedFromPositionFile; /* [HGM] loadPos */\r
76 extern int searchTime;\r
77 \r
78 /* types */\r
79 \r
80 typedef struct {\r
81   char *label;\r
82   unsigned value;\r
83 } ComboData;\r
84 \r
85 typedef struct {\r
86   char *label;\r
87   char *name;\r
88 } SoundComboData;\r
89 \r
90 /* module prototypes */\r
91 \r
92 LRESULT CALLBACK GeneralOptions(HWND, UINT, WPARAM, LPARAM);\r
93 LRESULT CALLBACK BoardOptions(HWND, UINT, WPARAM, LPARAM);\r
94 LRESULT CALLBACK NewVariant(HWND, UINT, WPARAM, LPARAM);\r
95 LRESULT CALLBACK IcsOptions(HWND, UINT, WPARAM, LPARAM);\r
96 LRESULT CALLBACK FontOptions(HWND, UINT, WPARAM, LPARAM);\r
97 LRESULT CALLBACK CommPortOptions(HWND, UINT, WPARAM, LPARAM);\r
98 LRESULT CALLBACK LoadOptions(HWND, UINT, WPARAM, LPARAM);\r
99 LRESULT CALLBACK SaveOptions(HWND, UINT, WPARAM, LPARAM);\r
100 LRESULT CALLBACK TimeControl(HWND, UINT, WPARAM, LPARAM);\r
101 VOID ChangeBoardSize(BoardSize newSize);\r
102 VOID PaintSampleSquare(\r
103     HWND     hwnd,\r
104     int      ctrlid,\r
105     COLORREF squareColor,\r
106     COLORREF pieceColor,\r
107     COLORREF squareOutlineColor,\r
108     COLORREF pieceDetailColor,\r
109     BOOL     isWhitePiece,\r
110     BOOL     isMono,\r
111     HBITMAP  pieces[3]\r
112     );\r
113 VOID PaintColorBlock(HWND hwnd, int ctrlid, COLORREF color);\r
114 VOID SetBoardOptionEnables(HWND hDlg);\r
115 BoardSize BoardOptionsWhichRadio(HWND hDlg);\r
116 BOOL APIENTRY MyCreateFont(HWND hwnd, MyFont *font);\r
117 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);\r
118 LRESULT CALLBACK ColorizeTextDialog(HWND , UINT, WPARAM, LPARAM);\r
119 VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);\r
120 VOID SetIcsOptionEnables(HWND hDlg);\r
121 VOID SetSampleFontText(HWND hwnd, int id, const MyFont *mf);\r
122 VOID CopyFont(MyFont *dest, const MyFont *src);\r
123 void InitSoundComboData(SoundComboData *scd);\r
124 void ResetSoundComboData(SoundComboData *scd);\r
125 void InitSoundCombo(HWND hwndCombo, SoundComboData *scd);\r
126 int SoundDialogWhichRadio(HWND hDlg);\r
127 VOID SoundDialogSetEnables(HWND hDlg, int radio);\r
128 char * SoundDialogGetName(HWND hDlg, int radio);\r
129 void DisplaySelectedSound(HWND hDlg, HWND hCombo, const char *name);\r
130 VOID ParseCommSettings(char *arg, DCB *dcb);\r
131 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);\r
132 void InitCombo(HANDLE hwndCombo, ComboData *cd);\r
133 void SelectComboValue(HANDLE hwndCombo, ComboData *cd, unsigned value);\r
134 VOID SetLoadOptionEnables(HWND hDlg);\r
135 VOID SetSaveOptionEnables(HWND hDlg);\r
136 VOID SetTimeControlEnables(HWND hDlg);\r
137 \r
138 char *\r
139 InterpretFileName(char *buf, char *homeDir)\r
140 { // [HGM] file name relative to homeDir. (Taken out of SafeOptionsDialog, because it is generally useful)\r
141   char *result = NULL;\r
142   if ((isalpha(buf[0]) && buf[1] == ':') ||\r
143     (buf[0] == '\\' && buf[1] == '\\')) {\r
144     return strdup(buf);\r
145   } else {\r
146     char buf2[MSG_SIZ], buf3[MSG_SIZ];\r
147     char *dummy;\r
148     GetCurrentDirectory(MSG_SIZ, buf3);\r
149     SetCurrentDirectory(homeDir);\r
150     if (GetFullPathName(buf, MSG_SIZ, buf2, &dummy)) {\r
151       result = strdup(buf2);\r
152     } else {\r
153       result = strdup(buf);\r
154     }\r
155     SetCurrentDirectory(buf3);\r
156   }\r
157   return result;\r
158 }\r
159 \r
160 /*---------------------------------------------------------------------------*\\r
161  *\r
162  * General Options Dialog functions\r
163  *\r
164 \*---------------------------------------------------------------------------*/\r
165 \r
166 \r
167 LRESULT CALLBACK\r
168 GeneralOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
169 {\r
170   static Boolean oldShowCoords;\r
171   static Boolean oldBlindfold;\r
172   static Boolean oldShowButtonBar;\r
173   static Boolean oldAutoLogo;\r
174 \r
175   switch (message) {\r
176   case WM_INITDIALOG: /* message: initialize dialog box */\r
177     oldShowCoords = appData.showCoords;\r
178     oldBlindfold  = appData.blindfold;\r
179     oldShowButtonBar = appData.showButtonBar;\r
180     oldAutoLogo  = appData.autoLogo;\r
181 \r
182     /* Center the dialog over the application window */\r
183     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
184     Translate(hDlg, DLG_GeneralOptions);\r
185 \r
186     /* Initialize the dialog items */\r
187 #define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y))\r
188 \r
189     CHECK_BOX(OPT_AlwaysOnTop, alwaysOnTop);\r
190     CHECK_BOX(OPT_AlwaysQueen, appData.alwaysPromoteToQueen);\r
191     CHECK_BOX(OPT_AnimateDragging, appData.animateDragging);\r
192     CHECK_BOX(OPT_AnimateMoving, appData.animate);\r
193     CHECK_BOX(OPT_AutoFlag, appData.autoCallFlag);\r
194     CHECK_BOX(OPT_AutoFlipView, appData.autoFlipView);\r
195     CHECK_BOX(OPT_AutoRaiseBoard, appData.autoRaiseBoard);\r
196     CHECK_BOX(OPT_Blindfold, appData.blindfold);\r
197     CHECK_BOX(OPT_HighlightDragging, appData.highlightDragging);\r
198     CHECK_BOX(OPT_HighlightLastMove, appData.highlightLastMove);\r
199     CHECK_BOX(OPT_PeriodicUpdates, appData.periodicUpdates);\r
200     CHECK_BOX(OPT_PonderNextMove, appData.ponderNextMove);\r
201     CHECK_BOX(OPT_PopupExitMessage, appData.popupExitMessage);\r
202     CHECK_BOX(OPT_PopupMoveErrors, appData.popupMoveErrors);\r
203     CHECK_BOX(OPT_ShowButtonBar, appData.showButtonBar);\r
204     CHECK_BOX(OPT_ShowCoordinates, appData.showCoords);\r
205     CHECK_BOX(OPT_ShowThinking, appData.showThinking);\r
206     CHECK_BOX(OPT_TestLegality, appData.testLegality);\r
207     CHECK_BOX(OPT_HideThinkFromHuman, appData.hideThinkingFromHuman);\r
208     CHECK_BOX(OPT_SaveExtPGN, appData.saveExtendedInfoInPGN);\r
209     CHECK_BOX(OPT_ExtraInfoInMoveHistory, appData.showEvalInMoveHistory);\r
210     CHECK_BOX(OPT_HighlightMoveArrow, appData.highlightMoveWithArrow);\r
211     CHECK_BOX(OPT_AutoLogo, appData.autoLogo); // [HGM] logo\r
212     CHECK_BOX(OPT_SmartMove, appData.oneClick); // [HGM] one-click\r
213     CHECK_BOX(OPT_AutoTags, appData.autoDisplayTags); // [HGM]\r
214     CHECK_BOX(OPT_AutoComment, appData.autoDisplayComment); // [HGM]\r
215     CHECK_BOX(OPT_Headers, appData.headers); // [HGM]\r
216     CHECK_BOX(OPT_Variations, appData.variations); // [HGM]\r
217     CHECK_BOX(OPT_AutoExtend, appData.autoExtend); // [HGM]\r
218 \r
219 #undef CHECK_BOX\r
220 \r
221     EnableWindow(GetDlgItem(hDlg, OPT_AutoFlag),\r
222                  appData.icsActive || !appData.noChessProgram);\r
223     EnableWindow(GetDlgItem(hDlg, OPT_AutoFlipView),\r
224                  appData.icsActive || !appData.noChessProgram);\r
225     EnableWindow(GetDlgItem(hDlg, OPT_PonderNextMove),\r
226                  !appData.noChessProgram);\r
227     EnableWindow(GetDlgItem(hDlg, OPT_PeriodicUpdates),\r
228                  !appData.noChessProgram && !appData.icsActive);\r
229     EnableWindow(GetDlgItem(hDlg, OPT_ShowThinking),\r
230                  !appData.noChessProgram);\r
231     return TRUE;\r
232 \r
233 \r
234   case WM_COMMAND: /* message: received a command */\r
235     switch (LOWORD(wParam)) {\r
236     case IDOK:\r
237       /* Read changed options from the dialog box */\r
238 \r
239 #define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x))\r
240 \r
241       alwaysOnTop                  = IS_CHECKED(OPT_AlwaysOnTop);\r
242       appData.alwaysPromoteToQueen = IS_CHECKED(OPT_AlwaysQueen);\r
243       appData.animateDragging      = IS_CHECKED(OPT_AnimateDragging);\r
244       appData.animate              = IS_CHECKED(OPT_AnimateMoving);\r
245       appData.autoCallFlag         = IS_CHECKED(OPT_AutoFlag);\r
246       appData.autoFlipView         = IS_CHECKED(OPT_AutoFlipView);\r
247       appData.autoRaiseBoard       = IS_CHECKED(OPT_AutoRaiseBoard);\r
248       appData.blindfold            = IS_CHECKED(OPT_Blindfold);\r
249       appData.highlightDragging    = IS_CHECKED(OPT_HighlightDragging);\r
250       appData.highlightLastMove    = IS_CHECKED(OPT_HighlightLastMove);\r
251       PeriodicUpdatesEvent(          IS_CHECKED(OPT_PeriodicUpdates));\r
252       PonderNextMoveEvent(           IS_CHECKED(OPT_PonderNextMove));\r
253       appData.popupExitMessage     = IS_CHECKED(OPT_PopupExitMessage);\r
254       appData.popupMoveErrors      = IS_CHECKED(OPT_PopupMoveErrors);\r
255       appData.showButtonBar        = IS_CHECKED(OPT_ShowButtonBar);\r
256       appData.showCoords           = IS_CHECKED(OPT_ShowCoordinates);\r
257       // [HGM] thinking: next three moved up\r
258       appData.saveExtendedInfoInPGN= IS_CHECKED(OPT_SaveExtPGN);\r
259       appData.hideThinkingFromHuman= IS_CHECKED(OPT_HideThinkFromHuman);\r
260       appData.showEvalInMoveHistory= IS_CHECKED(OPT_ExtraInfoInMoveHistory);\r
261       appData.showThinking         = IS_CHECKED(OPT_ShowThinking);\r
262       ShowThinkingEvent(); // [HGM] thinking: tests four options\r
263       appData.testLegality         = IS_CHECKED(OPT_TestLegality);\r
264       appData.highlightMoveWithArrow=IS_CHECKED(OPT_HighlightMoveArrow);\r
265       appData.autoLogo             =IS_CHECKED(OPT_AutoLogo); // [HGM] logo\r
266       appData.oneClick             =IS_CHECKED(OPT_SmartMove); // [HGM] one-click\r
267       appData.autoDisplayTags      =IS_CHECKED(OPT_AutoTags); // [HGM]\r
268       appData.autoDisplayComment   =IS_CHECKED(OPT_AutoComment); // [HGM]\r
269       appData.headers              =IS_CHECKED(OPT_Headers); // [HGM]\r
270       appData.variations           =IS_CHECKED(OPT_Variations); // [HGM]\r
271       appData.autoExtend           =IS_CHECKED(OPT_AutoExtend); // [HGM]\r
272 \r
273 #undef IS_CHECKED\r
274 \r
275       SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
276                    0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);\r
277 #if AOT_CONSOLE\r
278       if (hwndConsole) {\r
279         SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
280                      0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);\r
281       }\r
282 #endif\r
283       if (!appData.highlightLastMove) {\r
284         ClearHighlights();\r
285         DrawPosition(FALSE, NULL);\r
286       }\r
287       /*\r
288        * for some reason the redraw seems smoother when we invalidate\r
289        * the board rect after the call to EndDialog()\r
290        */\r
291       EndDialog(hDlg, TRUE);\r
292 \r
293       if (oldAutoLogo != appData.autoLogo) { // [HGM] logo: remove any logos when we switch autologo off\r
294         if(oldAutoLogo) first.programLogo = second.programLogo = NULL;\r
295         InitDrawingSizes(boardSize, 0);\r
296       } else if (oldShowButtonBar != appData.showButtonBar) {\r
297         InitDrawingSizes(boardSize, 0);\r
298       } else if ((oldShowCoords != appData.showCoords) ||\r
299                  (oldBlindfold != appData.blindfold)) {\r
300         InvalidateRect(hwndMain, &boardRect, FALSE);\r
301       }\r
302 \r
303       return TRUE;\r
304 \r
305     case IDCANCEL:\r
306       EndDialog(hDlg, FALSE);\r
307       return TRUE;\r
308 \r
309     }\r
310     break;\r
311   }\r
312   return FALSE;\r
313 }\r
314 \r
315 VOID\r
316 GeneralOptionsPopup(HWND hwnd)\r
317 {\r
318   FARPROC lpProc;\r
319 \r
320   lpProc = MakeProcInstance((FARPROC)GeneralOptionsDialog, hInst);\r
321   DialogBox(hInst, MAKEINTRESOURCE(DLG_GeneralOptions), hwnd,\r
322             (DLGPROC) lpProc);\r
323   FreeProcInstance(lpProc);\r
324 }\r
325 /*---------------------------------------------------------------------------*\\r
326  *\r
327  * Board Options Dialog functions\r
328  *\r
329 \*---------------------------------------------------------------------------*/\r
330 \r
331 const int SAMPLE_SQ_SIZE = 54;\r
332 \r
333 VOID\r
334 ChangeBoardSize(BoardSize newSize)\r
335 {\r
336   if (newSize != boardSize) {\r
337     boardSize = newSize;\r
338     InitDrawingSizes(boardSize, 0);\r
339   }\r
340 }\r
341 \r
342 VOID\r
343 PaintSampleSquare(\r
344     HWND     hwnd,\r
345     int      ctrlid,\r
346     COLORREF squareColor,\r
347     COLORREF pieceColor,\r
348     COLORREF squareOutlineColor,\r
349     COLORREF pieceDetailColor,\r
350     BOOL     isWhitePiece,\r
351     BOOL     isMono,\r
352     HBITMAP  pieces[3]\r
353     )\r
354 {\r
355   HBRUSH  brushSquare;\r
356   HBRUSH  brushSquareOutline;\r
357   HBRUSH  brushPiece;\r
358   HBRUSH  brushPieceDetail;\r
359   HBRUSH  oldBrushPiece = NULL;\r
360   HBRUSH  oldBrushSquare;\r
361   HBITMAP oldBitmapMem;\r
362   HBITMAP oldBitmapTemp;\r
363   HBITMAP bufferBitmap;\r
364   RECT    rect;\r
365   HDC     hdcScreen, hdcMem, hdcTemp;\r
366   HPEN    pen, oldPen;\r
367   HWND    hCtrl = GetDlgItem(hwnd, ctrlid);\r
368   int     x, y;\r
369 \r
370   const int SOLID   = 0;\r
371   const int WHITE   = 1;\r
372   const int OUTLINE = 2;\r
373   const int BORDER  = 4;\r
374 \r
375   InvalidateRect(hCtrl, NULL, TRUE);\r
376   UpdateWindow(hCtrl);\r
377   GetClientRect(hCtrl, &rect);\r
378   x = rect.left + (BORDER / 2);\r
379   y = rect.top  + (BORDER / 2);\r
380   hdcScreen = GetDC(hCtrl);\r
381   hdcMem  = CreateCompatibleDC(hdcScreen);\r
382   hdcTemp = CreateCompatibleDC(hdcScreen);\r
383 \r
384   bufferBitmap = CreateCompatibleBitmap(hdcScreen, rect.right-rect.left+1,\r
385                                         rect.bottom-rect.top+1);\r
386   oldBitmapMem = SelectObject(hdcMem, bufferBitmap);\r
387   if (!isMono) {\r
388     SelectPalette(hdcMem, hPal, FALSE);\r
389   }\r
390   brushSquare         = CreateSolidBrush(squareColor);\r
391   brushSquareOutline  = CreateSolidBrush(squareOutlineColor);\r
392   brushPiece          = CreateSolidBrush(pieceColor);\r
393   brushPieceDetail    = CreateSolidBrush(pieceDetailColor);\r
394 \r
395   /*\r
396    * first draw the rectangle\r
397    */\r
398   pen      = CreatePen(PS_SOLID, BORDER, squareOutlineColor);\r
399   oldPen   = (HPEN)  SelectObject(hdcMem, pen);\r
400   oldBrushSquare = (HBRUSH)SelectObject(hdcMem, brushSquare);\r
401   Rectangle(hdcMem, rect.left, rect.top, rect.right, rect.bottom);\r
402 \r
403   /*\r
404    * now draw the piece\r
405    */\r
406   if (isMono) {\r
407     oldBitmapTemp = SelectObject(hdcTemp, pieces[OUTLINE]);\r
408     BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, hdcTemp, 0, 0,\r
409            isWhitePiece ? SRCCOPY : NOTSRCCOPY);\r
410     SelectObject(hdcTemp, oldBitmapTemp);\r
411   } else {\r
412     if (isWhitePiece) {\r
413       oldBitmapTemp = SelectObject(hdcTemp, pieces[WHITE]);\r
414       oldBrushPiece = SelectObject(hdcMem, brushPiece);\r
415       BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE,\r
416              hdcTemp, 0, 0, 0x00B8074A);\r
417       /* Use black for outline of white pieces */\r
418       SelectObject(hdcTemp, pieces[OUTLINE]);\r
419       BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE,\r
420              hdcTemp, 0, 0, SRCAND);\r
421     } else {\r
422       /* Use square color for details of black pieces */\r
423       oldBitmapTemp = SelectObject(hdcTemp, pieces[SOLID]);\r
424       oldBrushPiece = SelectObject(hdcMem, brushPiece);\r
425       BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE,\r
426              hdcTemp, 0, 0, 0x00B8074A);\r
427     }\r
428     SelectObject(hdcMem, oldBrushPiece);\r
429     SelectObject(hdcTemp, oldBitmapTemp);\r
430   }\r
431   /*\r
432    * copy the memory dc to the screen\r
433    */\r
434   SelectObject(hdcMem, bufferBitmap);\r
435   BitBlt(hdcScreen, rect.left, rect.top,\r
436          rect.right - rect.left,\r
437          rect.bottom - rect.top,\r
438          hdcMem, rect.left, rect.top, SRCCOPY);\r
439   SelectObject(hdcMem, oldBitmapMem);\r
440   /*\r
441    * clean up\r
442    */\r
443   SelectObject(hdcMem, oldBrushSquare);\r
444   SelectObject(hdcMem, oldPen);\r
445   DeleteObject(brushPiece);\r
446   DeleteObject(brushPieceDetail);\r
447   DeleteObject(brushSquare);\r
448   DeleteObject(brushSquareOutline);\r
449   DeleteObject(pen);\r
450   DeleteDC(hdcTemp);\r
451   DeleteDC(hdcMem);\r
452   ReleaseDC(hCtrl, hdcScreen);\r
453 }\r
454 \r
455 \r
456 VOID\r
457 PaintColorBlock(HWND hwnd, int ctrlid, COLORREF color)\r
458 {\r
459   HDC    hdc;\r
460   HBRUSH brush, oldBrush;\r
461   RECT   rect;\r
462   HWND   hCtrl = GetDlgItem(hwnd, ctrlid);\r
463 \r
464   hdc = GetDC(hCtrl);\r
465   InvalidateRect(hCtrl, NULL, TRUE);\r
466   UpdateWindow(hCtrl);\r
467   GetClientRect(hCtrl, &rect);\r
468   brush = CreateSolidBrush(color);\r
469   oldBrush = (HBRUSH)SelectObject(hdc, brush);\r
470   Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);\r
471   SelectObject(hdc, oldBrush);\r
472   DeleteObject(brush);\r
473   ReleaseDC(hCtrl, hdc);\r
474 }\r
475 \r
476 \r
477 VOID\r
478 SetBoardOptionEnables(HWND hDlg)\r
479 {\r
480   if (IsDlgButtonChecked(hDlg, OPT_Monochrome)) {\r
481     ShowWindow(GetDlgItem(hDlg, OPT_LightSquareColor), SW_HIDE);\r
482     ShowWindow(GetDlgItem(hDlg, OPT_DarkSquareColor), SW_HIDE);\r
483     ShowWindow(GetDlgItem(hDlg, OPT_WhitePieceColor), SW_HIDE);\r
484     ShowWindow(GetDlgItem(hDlg, OPT_BlackPieceColor), SW_HIDE);\r
485 \r
486     EnableWindow(GetDlgItem(hDlg, OPT_ChooseLightSquareColor), FALSE);\r
487     EnableWindow(GetDlgItem(hDlg, OPT_ChooseDarkSquareColor), FALSE);\r
488     EnableWindow(GetDlgItem(hDlg, OPT_ChooseWhitePieceColor), FALSE);\r
489     EnableWindow(GetDlgItem(hDlg, OPT_ChooseBlackPieceColor), FALSE);\r
490   } else {\r
491     ShowWindow(GetDlgItem(hDlg, OPT_LightSquareColor), SW_SHOW);\r
492     ShowWindow(GetDlgItem(hDlg, OPT_DarkSquareColor), SW_SHOW);\r
493     ShowWindow(GetDlgItem(hDlg, OPT_WhitePieceColor), SW_SHOW);\r
494     ShowWindow(GetDlgItem(hDlg, OPT_BlackPieceColor), SW_SHOW);\r
495 \r
496     EnableWindow(GetDlgItem(hDlg, OPT_ChooseLightSquareColor), TRUE);\r
497     EnableWindow(GetDlgItem(hDlg, OPT_ChooseDarkSquareColor), TRUE);\r
498     EnableWindow(GetDlgItem(hDlg, OPT_ChooseWhitePieceColor), TRUE);\r
499     EnableWindow(GetDlgItem(hDlg, OPT_ChooseBlackPieceColor), TRUE);\r
500   }\r
501 }\r
502 \r
503 BoardSize\r
504 BoardOptionsWhichRadio(HWND hDlg)\r
505 {\r
506   return (IsDlgButtonChecked(hDlg, OPT_SizeTiny) ? SizeTiny :\r
507          (IsDlgButtonChecked(hDlg, OPT_SizeTeeny) ? SizeTeeny :\r
508          (IsDlgButtonChecked(hDlg, OPT_SizeDinky) ? SizeDinky :\r
509          (IsDlgButtonChecked(hDlg, OPT_SizePetite) ? SizePetite :\r
510          (IsDlgButtonChecked(hDlg, OPT_SizeSlim) ? SizeSlim :\r
511          (IsDlgButtonChecked(hDlg, OPT_SizeSmall) ? SizeSmall :\r
512          (IsDlgButtonChecked(hDlg, OPT_SizeMediocre) ? SizeMediocre :\r
513          (IsDlgButtonChecked(hDlg, OPT_SizeMiddling) ? SizeMiddling :\r
514          (IsDlgButtonChecked(hDlg, OPT_SizeAverage) ? SizeAverage :\r
515          (IsDlgButtonChecked(hDlg, OPT_SizeModerate) ? SizeModerate :\r
516          (IsDlgButtonChecked(hDlg, OPT_SizeMedium) ? SizeMedium :\r
517          (IsDlgButtonChecked(hDlg, OPT_SizeBulky) ? SizeBulky :\r
518          (IsDlgButtonChecked(hDlg, OPT_SizeLarge) ? SizeLarge :\r
519          (IsDlgButtonChecked(hDlg, OPT_SizeBig) ? SizeBig :\r
520          (IsDlgButtonChecked(hDlg, OPT_SizeHuge) ? SizeHuge :\r
521          (IsDlgButtonChecked(hDlg, OPT_SizeGiant) ? SizeGiant :\r
522          (IsDlgButtonChecked(hDlg, OPT_SizeColossal) ? SizeColossal :\r
523           SizeTitanic )))))))))))))))));\r
524 }\r
525 \r
526 LRESULT CALLBACK\r
527 BoardOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
528 {\r
529   static Boolean  mono, white, flip, fonts, bitmaps, grid;\r
530   static BoardSize size;\r
531   static COLORREF lsc, dsc, wpc, bpc, hsc, phc;\r
532   static HBITMAP pieces[3];\r
533 \r
534   switch (message) {\r
535   case WM_INITDIALOG: /* message: initialize dialog box */\r
536     /* Center the dialog over the application window */\r
537     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
538     Translate(hDlg, DLG_BoardOptions);\r
539     /* Initialize the dialog items */\r
540     switch (boardSize) {\r
541     case SizeTiny:\r
542       CheckDlgButton(hDlg, OPT_SizeTiny, TRUE);\r
543       break;\r
544     case SizeTeeny:\r
545       CheckDlgButton(hDlg, OPT_SizeTeeny, TRUE);\r
546       break;\r
547     case SizeDinky:\r
548       CheckDlgButton(hDlg, OPT_SizeDinky, TRUE);\r
549       break;\r
550     case SizePetite:\r
551       CheckDlgButton(hDlg, OPT_SizePetite, TRUE);\r
552       break;\r
553     case SizeSlim:\r
554       CheckDlgButton(hDlg, OPT_SizeSlim, TRUE);\r
555       break;\r
556     case SizeSmall:\r
557       CheckDlgButton(hDlg, OPT_SizeSmall, TRUE);\r
558       break;\r
559     case SizeMediocre:\r
560       CheckDlgButton(hDlg, OPT_SizeMediocre, TRUE);\r
561       break;\r
562     case SizeMiddling:\r
563       CheckDlgButton(hDlg, OPT_SizeMiddling, TRUE);\r
564       break;\r
565     case SizeAverage:\r
566       CheckDlgButton(hDlg, OPT_SizeAverage, TRUE);\r
567       break;\r
568     case SizeModerate:\r
569       CheckDlgButton(hDlg, OPT_SizeModerate, TRUE);\r
570       break;\r
571     case SizeMedium:\r
572       CheckDlgButton(hDlg, OPT_SizeMedium, TRUE);\r
573       break;\r
574     case SizeBulky:\r
575       CheckDlgButton(hDlg, OPT_SizeBulky, TRUE);\r
576       break;\r
577     case SizeLarge:\r
578       CheckDlgButton(hDlg, OPT_SizeLarge, TRUE);\r
579       break;\r
580     case SizeBig:\r
581       CheckDlgButton(hDlg, OPT_SizeBig, TRUE);\r
582       break;\r
583     case SizeHuge:\r
584       CheckDlgButton(hDlg, OPT_SizeHuge, TRUE);\r
585       break;\r
586     case SizeGiant:\r
587       CheckDlgButton(hDlg, OPT_SizeGiant, TRUE);\r
588       break;\r
589     case SizeColossal:\r
590       CheckDlgButton(hDlg, OPT_SizeColossal, TRUE);\r
591       break;\r
592     case SizeTitanic:\r
593       CheckDlgButton(hDlg, OPT_SizeTitanic, TRUE);\r
594     default: ; // should not happen, but suppresses warning on pedantic compilers\r
595     }\r
596 \r
597     if (appData.monoMode)\r
598       CheckDlgButton(hDlg, OPT_Monochrome, TRUE);\r
599 \r
600     if (appData.allWhite)\r
601       CheckDlgButton(hDlg, OPT_AllWhite, TRUE);\r
602 \r
603     if (appData.upsideDown)\r
604       CheckDlgButton(hDlg, OPT_UpsideDown, TRUE);\r
605 \r
606     if (appData.useBitmaps)\r
607       CheckDlgButton(hDlg, OPT_Bitmaps, TRUE);\r
608 \r
609     if (appData.useFont)\r
610       CheckDlgButton(hDlg, OPT_PieceFont, TRUE);\r
611 \r
612     if (appData.overrideLineGap >= 0)\r
613       CheckDlgButton(hDlg, OPT_Grid, TRUE);\r
614 \r
615     pieces[0] = DoLoadBitmap(hInst, "n", SAMPLE_SQ_SIZE, "s");\r
616     pieces[1] = DoLoadBitmap(hInst, "n", SAMPLE_SQ_SIZE, "w");\r
617     pieces[2] = DoLoadBitmap(hInst, "n", SAMPLE_SQ_SIZE, "o");\r
618 \r
619     lsc = lightSquareColor;\r
620     dsc = darkSquareColor;\r
621     fonts = appData.useFont;\r
622     wpc = fonts ? appData.fontBackColorWhite : whitePieceColor;\r
623     bpc = fonts ? appData.fontForeColorBlack : blackPieceColor;\r
624     hsc = highlightSquareColor;\r
625     phc = premoveHighlightColor;\r
626     mono = appData.monoMode;\r
627     white= appData.allWhite;\r
628     flip = appData.upsideDown;\r
629     size = boardSize;\r
630     bitmaps = appData.useBitmaps;\r
631     grid = appData.overrideLineGap >= 0;\r
632 \r
633     SetBoardOptionEnables(hDlg);\r
634     return TRUE;\r
635 \r
636   case WM_PAINT:\r
637     PaintColorBlock(hDlg, OPT_LightSquareColor, lsc);\r
638     PaintColorBlock(hDlg, OPT_DarkSquareColor,  dsc);\r
639     PaintColorBlock(hDlg, OPT_WhitePieceColor,  wpc);\r
640     PaintColorBlock(hDlg, OPT_BlackPieceColor,  bpc);\r
641     PaintColorBlock(hDlg, OPT_HighlightSquareColor, hsc);\r
642     PaintColorBlock(hDlg, OPT_PremoveHighlightColor, phc);\r
643     PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc,\r
644         TRUE, mono, pieces);\r
645     PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc,\r
646         FALSE, mono, pieces);\r
647 \r
648     return FALSE;\r
649 \r
650   case WM_COMMAND: /* message: received a command */\r
651     switch (LOWORD(wParam)) {\r
652     case IDOK:\r
653       /*\r
654        * if we call EndDialog() after the call to ChangeBoardSize(),\r
655        * then ChangeBoardSize() does not take effect, although the new\r
656        * boardSize is saved. Go figure...\r
657        */\r
658       EndDialog(hDlg, TRUE);\r
659 \r
660       size = BoardOptionsWhichRadio(hDlg);\r
661 \r
662       /*\r
663        * did any settings change?\r
664        */\r
665       if (size != boardSize) {\r
666         ChangeBoardSize(size);\r
667       }\r
668 \r
669       if (bitmaps && !appData.useBitmaps) InitTextures();\r
670 \r
671       if ((mono != appData.monoMode) ||\r
672           (lsc  != lightSquareColor) ||\r
673           (dsc  != darkSquareColor) ||\r
674           (wpc  != fonts ? appData.fontBackColorWhite : whitePieceColor) ||\r
675           (bpc  != fonts ? appData.fontForeColorBlack : blackPieceColor) ||\r
676           (hsc  != highlightSquareColor) ||\r
677           (flip != appData.upsideDown) ||\r
678           (white != appData.allWhite) ||\r
679           (fonts != appData.useFont) ||\r
680           (bitmaps != appData.useBitmaps) ||\r
681           (grid != appData.overrideLineGap >= 0) ||\r
682           (phc  != premoveHighlightColor)) {\r
683 \r
684           lightSquareColor = lsc;\r
685           darkSquareColor = dsc;\r
686           if(fonts) {\r
687             appData.fontBackColorWhite = wpc;\r
688             appData.fontForeColorBlack = bpc;\r
689           } else {\r
690             whitePieceColor = wpc;\r
691             blackPieceColor = bpc;\r
692           }\r
693           highlightSquareColor = hsc;\r
694           premoveHighlightColor = phc;\r
695           appData.monoMode = mono;\r
696           appData.allWhite = white;\r
697           appData.upsideDown = flip;\r
698           appData.useFont = fonts;\r
699           appData.useBitmaps = bitmaps;\r
700           if(grid != appData.overrideLineGap >= 0) appData.overrideLineGap = grid - 1;\r
701 \r
702           InitDrawingColors();\r
703           InitDrawingSizes(boardSize, 0);\r
704           InvalidateRect(hwndMain, &boardRect, FALSE);\r
705       }\r
706       DeleteObject(pieces[0]);\r
707       DeleteObject(pieces[1]);\r
708 \r
709       DeleteObject(pieces[2]);\r
710       return TRUE;\r
711 \r
712     case IDCANCEL:\r
713       DeleteObject(pieces[0]);\r
714       DeleteObject(pieces[1]);\r
715       DeleteObject(pieces[2]);\r
716       EndDialog(hDlg, FALSE);\r
717       return TRUE;\r
718 \r
719     case OPT_ChooseLightSquareColor:\r
720       if (ChangeColor(hDlg, &lsc))\r
721         PaintColorBlock(hDlg, OPT_LightSquareColor, lsc);\r
722         PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc,\r
723             TRUE, mono, pieces);\r
724       break;\r
725 \r
726     case OPT_ChooseDarkSquareColor:\r
727       if (ChangeColor(hDlg, &dsc))\r
728         PaintColorBlock(hDlg, OPT_DarkSquareColor, dsc);\r
729         PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc,\r
730             FALSE, mono, pieces);\r
731       break;\r
732 \r
733     case OPT_ChooseWhitePieceColor:\r
734       if (ChangeColor(hDlg, &wpc))\r
735         PaintColorBlock(hDlg, OPT_WhitePieceColor, wpc);\r
736         PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc,\r
737             TRUE, mono, pieces);\r
738       break;\r
739 \r
740     case OPT_ChooseBlackPieceColor:\r
741       if (ChangeColor(hDlg, &bpc))\r
742         PaintColorBlock(hDlg, OPT_BlackPieceColor, bpc);\r
743         PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc,\r
744             FALSE, mono, pieces);\r
745       break;\r
746 \r
747     case OPT_ChooseHighlightSquareColor:\r
748       if (ChangeColor(hDlg, &hsc))\r
749         PaintColorBlock(hDlg, OPT_HighlightSquareColor, hsc);\r
750         PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc,\r
751             TRUE, mono, pieces);\r
752       break;\r
753 \r
754     case OPT_ChoosePremoveHighlightColor:\r
755       if (ChangeColor(hDlg, &phc))\r
756         PaintColorBlock(hDlg, OPT_PremoveHighlightColor, phc);\r
757         PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc,\r
758             FALSE, mono, pieces);\r
759       break;\r
760 \r
761     case OPT_DefaultBoardColors:\r
762       lsc = ParseColorName(LIGHT_SQUARE_COLOR);\r
763       dsc = ParseColorName(DARK_SQUARE_COLOR);\r
764       wpc = ParseColorName(WHITE_PIECE_COLOR);\r
765       bpc = ParseColorName(BLACK_PIECE_COLOR);\r
766       hsc = ParseColorName(HIGHLIGHT_SQUARE_COLOR);\r
767       phc = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);\r
768       mono = FALSE;\r
769       white= FALSE;\r
770       flip = FALSE;\r
771       CheckDlgButton(hDlg, OPT_Monochrome, FALSE);\r
772       CheckDlgButton(hDlg, OPT_AllWhite,   FALSE);\r
773       CheckDlgButton(hDlg, OPT_UpsideDown, FALSE);\r
774       PaintColorBlock(hDlg, OPT_LightSquareColor, lsc);\r
775       PaintColorBlock(hDlg, OPT_DarkSquareColor,  dsc);\r
776       PaintColorBlock(hDlg, OPT_WhitePieceColor,  wpc);\r
777       PaintColorBlock(hDlg, OPT_BlackPieceColor,  bpc);\r
778       PaintColorBlock(hDlg, OPT_HighlightSquareColor, hsc);\r
779       PaintColorBlock(hDlg, OPT_PremoveHighlightColor, phc);\r
780       SetBoardOptionEnables(hDlg);\r
781       PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc,\r
782           TRUE, mono, pieces);\r
783       PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc,\r
784           FALSE, mono, pieces);\r
785       break;\r
786 \r
787     case OPT_Monochrome:\r
788       mono = !mono;\r
789       SetBoardOptionEnables(hDlg);\r
790       break;\r
791 \r
792     case OPT_AllWhite:\r
793       white = !white;\r
794       break;\r
795 \r
796     case OPT_UpsideDown:\r
797       flip = !flip;\r
798       break;\r
799 \r
800     case OPT_Bitmaps:\r
801       bitmaps = !bitmaps;\r
802       break;\r
803 \r
804     case OPT_PieceFont:\r
805       fonts = !fonts;\r
806       break;\r
807 \r
808     case OPT_Grid:\r
809       grid = !grid;\r
810       break;\r
811     }\r
812     break;\r
813   }\r
814   return FALSE;\r
815 }\r
816 \r
817 \r
818 VOID\r
819 BoardOptionsPopup(HWND hwnd)\r
820 {\r
821   FARPROC lpProc = MakeProcInstance((FARPROC)BoardOptionsDialog, hInst);\r
822   DialogBox(hInst, MAKEINTRESOURCE(DLG_BoardOptions), hwnd,\r
823           (DLGPROC) lpProc);\r
824   FreeProcInstance(lpProc);\r
825 }\r
826 \r
827 int radioButton[] = {\r
828     OPT_VariantNormal,\r
829     -1, // Loadable\r
830     OPT_VariantWildcastle,\r
831     OPT_VariantNocastle,\r
832     OPT_VariantFRC,\r
833     OPT_VariantBughouse,\r
834     OPT_VariantCrazyhouse,\r
835     OPT_VariantLosers,\r
836     OPT_VariantSuicide,\r
837     OPT_VariantGiveaway,\r
838     OPT_VariantTwoKings,\r
839     -1, //Kriegspiel\r
840     OPT_VariantAtomic,\r
841     OPT_Variant3Check,\r
842     OPT_VariantShatranj,\r
843     -1,\r
844     -1,\r
845     -1,\r
846     -1,\r
847     -1,\r
848     -1,\r
849     -1,\r
850     -1,\r
851     OPT_VariantShogi,\r
852     -1, // Chu\r
853     OPT_VariantCourier,\r
854     OPT_VariantGothic,\r
855     OPT_VariantCapablanca,\r
856     OPT_VariantKnightmate,\r
857     OPT_VariantFairy,        \r
858     OPT_VariantCylinder,\r
859     OPT_VariantFalcon,\r
860     OPT_VariantCRC,\r
861     OPT_VariantBerolina,\r
862     OPT_VariantJanus,\r
863     OPT_VariantSuper,\r
864     OPT_VariantGreat,\r
865     -1, // Twilight,\r
866     OPT_VariantMakruk,\r
867     OPT_VariantSChess,\r
868     OPT_VariantGrand,\r
869     OPT_VariantSpartan, // Spartan\r
870     OPT_VariantXiangqi,\r
871     OPT_VariantASEAN,\r
872     OPT_VariantLion,\r
873     -2 // sentinel\r
874 };\r
875 \r
876 VariantClass\r
877 VariantWhichRadio(HWND hDlg)\r
878 {\r
879   int i=0, j;\r
880   *engineVariant = NULLCHAR;\r
881   while((j = radioButton[i++]) != -2) {\r
882         if(j == -1) continue; // no menu button\r
883         if(IsDlgButtonChecked(hDlg, j) &&\r
884            (appData.noChessProgram || strstr(first.variants, VariantName(i-1)))) return (VariantClass) i-1;\r
885   }\r
886   for(i=0; i<9; i++) { // check for engine-defined variants\r
887     if(IsDlgButtonChecked(hDlg, OPT_EngineVariant+i) ) {\r
888         GetDlgItemText(hDlg, OPT_EngineVariant+i, engineVariant, MSG_SIZ); // remember name, so we can resolve it later\r
889         return VariantUnknown;\r
890     }\r
891   }\r
892   return gameInfo.variant; // If no button checked, keep old\r
893 }\r
894 \r
895 void\r
896 VariantShowRadio(HWND hDlg)\r
897 {\r
898   char c = *engineVariant;\r
899   int i=0, j;\r
900   CheckDlgButton(hDlg, radioButton[gameInfo.variant], TRUE);\r
901   *engineVariant = NULLCHAR; // [HGM] kludge to prevent VariantName will always return engineVariant\r
902   while((j = radioButton[i++]) != -2) {\r
903         if(j == -1) continue; // no menu button\r
904         EnableWindow(GetDlgItem(hDlg, j), appData.noChessProgram || strstr(first.variants, VariantName(i-1)));\r
905   }\r
906   *engineVariant = c;\r
907   for(i=0; i<9; i++) { // initialize engine-defined variants\r
908     char *v = EngineDefinedVariant(&first, i); // get name of #i\r
909     if(v) { // there is such a variant\r
910         EnableWindow(GetDlgItem(hDlg, OPT_EngineVariant+i), TRUE);     // and enable the button\r
911         SetDlgItemText(hDlg, OPT_EngineVariant+i, v);                  // put its name on button\r
912     } else EnableWindow(GetDlgItem(hDlg, OPT_EngineVariant+i), FALSE); // no such variant; disable button\r
913   }\r
914 }\r
915 \r
916 LRESULT CALLBACK\r
917 NewVariantDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
918 {\r
919   static VariantClass v;\r
920   static int n1_ok, n2_ok, n3_ok;\r
921 \r
922   switch (message) {\r
923   case WM_INITDIALOG: /* message: initialize dialog box */\r
924     /* Center the dialog over the application window */\r
925     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
926     Translate(hDlg, DLG_NewVariant);\r
927 \r
928     /* Initialize the dialog items */\r
929     VariantShowRadio(hDlg);\r
930 \r
931     SetDlgItemInt( hDlg, IDC_Files, -1, TRUE );\r
932     SendDlgItemMessage( hDlg, IDC_Files, EM_SETSEL, 0, -1 );\r
933 \r
934     SetDlgItemInt( hDlg, IDC_Ranks, -1, TRUE );\r
935     SendDlgItemMessage( hDlg, IDC_Ranks, EM_SETSEL, 0, -1 );\r
936 \r
937     SetDlgItemInt( hDlg, IDC_Holdings, -1, TRUE );\r
938     SendDlgItemMessage( hDlg, IDC_Ranks, EM_SETSEL, 0, -1 );\r
939 \r
940     n1_ok = n2_ok = n3_ok = FALSE;\r
941 \r
942     return TRUE;\r
943 \r
944   case WM_COMMAND: /* message: received a command */\r
945     switch (LOWORD(wParam)) {\r
946     case IDOK:\r
947       /*\r
948        * if we call EndDialog() after the call to ChangeBoardSize(),\r
949        * then ChangeBoardSize() does not take effect, although the new\r
950        * boardSize is saved. Go figure...\r
951        */\r
952       EndDialog(hDlg, TRUE);\r
953 \r
954       v = VariantWhichRadio(hDlg);\r
955       if(!appData.noChessProgram) {\r
956         char *name = VariantName(v), buf[MSG_SIZ];\r
957         if (first.protocolVersion > 1 && StrStr(first.variants, name) == NULL) {\r
958           /* [HGM] in protocol 2 we check if variant is suported by engine */\r
959           snprintf(buf, MSG_SIZ, _("Variant %s not supported by %s"), name, first.tidy);\r
960           DisplayError(buf, 0);\r
961           return TRUE; /* treat as _("Cancel") if first engine does not support it */\r
962         } else\r
963         if (second.initDone && second.protocolVersion > 1 && StrStr(second.variants, name) == NULL) {\r
964           snprintf(buf, MSG_SIZ, _("Warning: second engine (%s) does not support this!"), second.tidy);\r
965           DisplayError(buf, 0);   /* use of second engine is optional; only warn user */\r
966         }\r
967       }\r
968 \r
969       gameInfo.variant = v;\r
970       appData.variant = VariantName(v);\r
971 \r
972       appData.NrFiles = (int) GetDlgItemInt(hDlg, IDC_Files, NULL, FALSE );\r
973       appData.NrRanks = (int) GetDlgItemInt(hDlg, IDC_Ranks, NULL, FALSE );\r
974       appData.holdingsSize = (int) GetDlgItemInt(hDlg, IDC_Holdings, NULL, FALSE );\r
975 \r
976       if(!n1_ok) appData.NrFiles = -1;\r
977       if(!n2_ok) appData.NrRanks = -1;\r
978       if(!n3_ok) appData.holdingsSize = -1;\r
979 \r
980       shuffleOpenings = FALSE; /* [HGM] shuffle: possible shuffle reset when we switch */\r
981       startedFromPositionFile = FALSE; /* [HGM] loadPos: no longer valid in new variant */\r
982       appData.pieceToCharTable = NULL;\r
983       Reset(TRUE, TRUE);\r
984 \r
985       return TRUE;\r
986 \r
987     case IDCANCEL:\r
988       EndDialog(hDlg, FALSE);\r
989       return TRUE;\r
990 \r
991     case IDC_Ranks:\r
992     case IDC_Files:\r
993     case IDC_Holdings:\r
994         if( HIWORD(wParam) == EN_CHANGE ) {\r
995 \r
996             GetDlgItemInt(hDlg, IDC_Files, &n1_ok, FALSE );\r
997             GetDlgItemInt(hDlg, IDC_Ranks, &n2_ok, FALSE );\r
998             GetDlgItemInt(hDlg, IDC_Holdings, &n3_ok, FALSE );\r
999 \r
1000             /*EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok && n3_ok ? TRUE : FALSE );*/\r
1001         }\r
1002         return TRUE;\r
1003     }\r
1004     break;\r
1005   }\r
1006   return FALSE;\r
1007 }\r
1008 \r
1009 \r
1010 VOID\r
1011 NewVariantPopup(HWND hwnd)\r
1012 {\r
1013   FARPROC lpProc = MakeProcInstance((FARPROC)NewVariantDialog, hInst);\r
1014   DialogBox(hInst, MAKEINTRESOURCE(DLG_NewVariant), hwnd,\r
1015           (DLGPROC) lpProc);\r
1016   FreeProcInstance(lpProc);\r
1017 }\r
1018 \r
1019 /*---------------------------------------------------------------------------*\\r
1020  *\r
1021  * ICS Options Dialog functions\r
1022  *\r
1023 \*---------------------------------------------------------------------------*/\r
1024 \r
1025 BOOL APIENTRY\r
1026 MyCreateFont(HWND hwnd, MyFont *font)\r
1027 {\r
1028   CHOOSEFONT cf;\r
1029   HFONT hf;\r
1030 \r
1031   /* Initialize members of the CHOOSEFONT structure. */\r
1032   cf.lStructSize = sizeof(CHOOSEFONT);\r
1033   cf.hwndOwner = hwnd;\r
1034   cf.hDC = (HDC)NULL;\r
1035   cf.lpLogFont = &font->lf;\r
1036   cf.iPointSize = 0;\r
1037   cf.Flags = CF_SCREENFONTS|/*CF_ANSIONLY|*/CF_INITTOLOGFONTSTRUCT;\r
1038   cf.rgbColors = RGB(0,0,0);\r
1039   cf.lCustData = 0L;\r
1040   cf.lpfnHook = (LPCFHOOKPROC)NULL;\r
1041   cf.lpTemplateName = (LPSTR)NULL;\r
1042   cf.hInstance = (HINSTANCE) NULL;\r
1043   cf.lpszStyle = (LPSTR)NULL;\r
1044   cf.nFontType = SCREEN_FONTTYPE;\r
1045   cf.nSizeMin = 0;\r
1046   cf.nSizeMax = 0;\r
1047 \r
1048   /* Display the CHOOSEFONT common-dialog box. */\r
1049   if (!ChooseFont(&cf)) {\r
1050     return FALSE;\r
1051   }\r
1052 \r
1053   /* Create a logical font based on the user's   */\r
1054   /* selection and return a handle identifying   */\r
1055   /* that font. */\r
1056   hf = CreateFontIndirect(cf.lpLogFont);\r
1057   if (hf == NULL) {\r
1058     return FALSE;\r
1059   }\r
1060 \r
1061   font->hf = hf;\r
1062   font->mfp.pointSize = (float) (cf.iPointSize / 10.0);\r
1063   font->mfp.bold = (font->lf.lfWeight >= FW_BOLD);\r
1064   font->mfp.italic = font->lf.lfItalic;\r
1065   font->mfp.underline = font->lf.lfUnderline;\r
1066   font->mfp.strikeout = font->lf.lfStrikeOut;\r
1067   font->mfp.charset = font->lf.lfCharSet;\r
1068   safeStrCpy(font->mfp.faceName, font->lf.lfFaceName, sizeof(font->mfp.faceName)/sizeof(font->mfp.faceName[0]) );\r
1069   return TRUE;\r
1070 }\r
1071 \r
1072 \r
1073 VOID\r
1074 UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca)\r
1075 {\r
1076   CHARFORMAT cf;\r
1077   cf.cbSize = sizeof(CHARFORMAT);\r
1078   cf.dwMask =\r
1079     CFM_COLOR|CFM_CHARSET|CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_STRIKEOUT|CFM_FACE|CFM_SIZE;\r
1080   cf.crTextColor = mca->color;\r
1081   cf.dwEffects = mca->effects;\r
1082   safeStrCpy(cf.szFaceName, font[boardSize][CONSOLE_FONT]->mfp.faceName, sizeof(cf.szFaceName)/sizeof(cf.szFaceName[0]) );\r
1083   /*\r
1084    * The 20.0 below is in fact documented. yHeight is expressed in twips.\r
1085    * A twip is 1/20 of a font's point size. See documentation of CHARFORMAT.\r
1086    * --msw\r
1087    */\r
1088   cf.yHeight = (int)(font[boardSize][CONSOLE_FONT]->mfp.pointSize * 20.0 + 0.5);\r
1089   cf.bCharSet = DEFAULT_CHARSET; /* should be ignored anyway */\r
1090   cf.bPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;\r
1091   SendDlgItemMessage(hDlg, id, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);\r
1092 }\r
1093 \r
1094 LRESULT CALLBACK\r
1095 ColorizeTextDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
1096 {\r
1097   static MyColorizeAttribs mca;\r
1098   static ColorClass cc;\r
1099   COLORREF background = (COLORREF)0;\r
1100 \r
1101   switch (message) {\r
1102   case WM_INITDIALOG:\r
1103     cc = (ColorClass)lParam;\r
1104     mca = colorizeAttribs[cc];\r
1105     /* Center the dialog over the application window */\r
1106     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
1107     Translate(hDlg, DLG_Colorize);\r
1108     /* Initialize the dialog items */\r
1109     CheckDlgButton(hDlg, OPT_Bold, (mca.effects & CFE_BOLD) != 0);\r
1110     CheckDlgButton(hDlg, OPT_Italic, (mca.effects & CFE_ITALIC) != 0);\r
1111     CheckDlgButton(hDlg, OPT_Underline, (mca.effects & CFE_UNDERLINE) != 0);\r
1112     CheckDlgButton(hDlg, OPT_Strikeout, (mca.effects & CFE_STRIKEOUT) != 0);\r
1113 \r
1114     /* get the current background color from the parent window */\r
1115     SendMessage(GetWindow(hDlg, GW_OWNER),WM_COMMAND,\r
1116                 (WPARAM)WM_USER_GetConsoleBackground,\r
1117                 (LPARAM)&background);\r
1118 \r
1119     /* set the background color */\r
1120     SendDlgItemMessage(hDlg, OPT_Sample, EM_SETBKGNDCOLOR, FALSE, background);\r
1121 \r
1122     SetDlgItemText(hDlg, OPT_Sample, T_(mca.name));\r
1123     UpdateSampleText(hDlg, OPT_Sample, &mca);\r
1124     return TRUE;\r
1125 \r
1126   case WM_COMMAND: /* message: received a command */\r
1127     switch (LOWORD(wParam)) {\r
1128     case IDOK:\r
1129       /* Read changed options from the dialog box */\r
1130       colorizeAttribs[cc] = mca;\r
1131       textAttribs[cc].color = mca.color;\r
1132       textAttribs[cc].effects = mca.effects;\r
1133       Colorize(currentColorClass, TRUE);\r
1134       if (cc == ColorNormal) {\r
1135         CHARFORMAT cf;\r
1136         cf.cbSize = sizeof(CHARFORMAT);\r
1137         cf.dwMask = CFM_COLOR;\r
1138         cf.crTextColor = mca.color;\r
1139         SendDlgItemMessage(hwndConsole, OPT_ConsoleInput,\r
1140           EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);\r
1141       }\r
1142       EndDialog(hDlg, TRUE);\r
1143       return TRUE;\r
1144 \r
1145     case IDCANCEL:\r
1146       EndDialog(hDlg, FALSE);\r
1147       return TRUE;\r
1148 \r
1149     case OPT_ChooseColor:\r
1150       ChangeColor(hDlg, &mca.color);\r
1151       UpdateSampleText(hDlg, OPT_Sample, &mca);\r
1152       return TRUE;\r
1153 \r
1154     default:\r
1155       mca.effects =\r
1156         (IsDlgButtonChecked(hDlg, OPT_Bold) ? CFE_BOLD : 0) |\r
1157         (IsDlgButtonChecked(hDlg, OPT_Italic) ? CFE_ITALIC : 0) |\r
1158         (IsDlgButtonChecked(hDlg, OPT_Underline) ? CFE_UNDERLINE : 0) |\r
1159         (IsDlgButtonChecked(hDlg, OPT_Strikeout) ? CFE_STRIKEOUT : 0);\r
1160       UpdateSampleText(hDlg, OPT_Sample, &mca);\r
1161       break;\r
1162     }\r
1163     break;\r
1164   }\r
1165   return FALSE;\r
1166 }\r
1167 \r
1168 VOID\r
1169 ColorizeTextPopup(HWND hwnd, ColorClass cc)\r
1170 {\r
1171   FARPROC lpProc;\r
1172 \r
1173   lpProc = MakeProcInstance((FARPROC)ColorizeTextDialog, hInst);\r
1174   DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_Colorize),\r
1175     hwnd, (DLGPROC)lpProc, (LPARAM) cc);\r
1176   FreeProcInstance(lpProc);\r
1177 }\r
1178 \r
1179 VOID\r
1180 SetIcsOptionEnables(HWND hDlg)\r
1181 {\r
1182 #define ENABLE_DLG_ITEM(x,y) EnableWindow(GetDlgItem(hDlg,(x)), (y))\r
1183 \r
1184   UINT state = IsDlgButtonChecked(hDlg, OPT_Premove);\r
1185   ENABLE_DLG_ITEM(OPT_PremoveWhite, state);\r
1186   ENABLE_DLG_ITEM(OPT_PremoveWhiteText, state);\r
1187   ENABLE_DLG_ITEM(OPT_PremoveBlack, state);\r
1188   ENABLE_DLG_ITEM(OPT_PremoveBlackText, state);\r
1189 \r
1190   ENABLE_DLG_ITEM(OPT_IcsAlarmTime, IsDlgButtonChecked(hDlg, OPT_IcsAlarm));\r
1191 \r
1192 #undef ENABLE_DLG_ITEM\r
1193 }\r
1194 \r
1195 \r
1196 LRESULT CALLBACK\r
1197 IcsOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
1198 {\r
1199   char buf[MSG_SIZ];\r
1200   int number;\r
1201   int i;\r
1202   static COLORREF cbc;\r
1203   static MyColorizeAttribs *mca;\r
1204   COLORREF *colorref;\r
1205 \r
1206   switch (message) {\r
1207   case WM_INITDIALOG: /* message: initialize dialog box */\r
1208 \r
1209     mca = colorizeAttribs;\r
1210 \r
1211     for (i=0; i < NColorClasses - 1; i++) {\r
1212       mca[i].color   = textAttribs[i].color;\r
1213       mca[i].effects = textAttribs[i].effects;\r
1214     }\r
1215     cbc = consoleBackgroundColor;\r
1216 \r
1217     /* Center the dialog over the application window */\r
1218     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
1219     Translate(hDlg, DLG_IcsOptions);\r
1220 \r
1221     /* Initialize the dialog items */\r
1222 #define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y))\r
1223 \r
1224     CHECK_BOX(OPT_AutoKibitz, appData.autoKibitz);\r
1225     CHECK_BOX(OPT_AutoComment, appData.autoComment);\r
1226     CHECK_BOX(OPT_AutoObserve, appData.autoObserve);\r
1227     CHECK_BOX(OPT_AutoCreate, appData.autoCreateLogon);\r
1228     CHECK_BOX(OPT_GetMoveList, appData.getMoveList);\r
1229     CHECK_BOX(OPT_LocalLineEditing, appData.localLineEditing);\r
1230     CHECK_BOX(OPT_QuietPlay, appData.quietPlay);\r
1231     CHECK_BOX(OPT_SeekGraph, appData.seekGraph);\r
1232     CHECK_BOX(OPT_AutoRefresh, appData.autoRefresh);\r
1233     CHECK_BOX(OPT_BgObserve, appData.bgObserve);\r
1234     CHECK_BOX(OPT_DualBoard, appData.dualBoard);\r
1235     CHECK_BOX(OPT_SmartMove, appData.oneClick);\r
1236     CHECK_BOX(OPT_Premove, appData.premove);\r
1237     CHECK_BOX(OPT_PremoveWhite, appData.premoveWhite);\r
1238     CHECK_BOX(OPT_PremoveBlack, appData.premoveBlack);\r
1239     CHECK_BOX(OPT_IcsAlarm, appData.icsAlarm);\r
1240     CHECK_BOX(OPT_DontColorize, !appData.colorize);\r
1241 \r
1242 #undef CHECK_BOX\r
1243 \r
1244     snprintf(buf, MSG_SIZ, "%d", appData.icsAlarmTime / 1000);\r
1245     SetDlgItemText(hDlg, OPT_IcsAlarmTime, buf);\r
1246     SetDlgItemText(hDlg, OPT_PremoveWhiteText, appData.premoveWhiteText);\r
1247     SetDlgItemText(hDlg, OPT_PremoveBlackText, appData.premoveBlackText);\r
1248     SetDlgItemText(hDlg, OPT_StartupChatBoxes, appData.chatBoxes);\r
1249 \r
1250     SendDlgItemMessage(hDlg, OPT_SampleShout,     EM_SETBKGNDCOLOR, 0, cbc);\r
1251     SendDlgItemMessage(hDlg, OPT_SampleSShout,    EM_SETBKGNDCOLOR, 0, cbc);\r
1252     SendDlgItemMessage(hDlg, OPT_SampleChannel1,  EM_SETBKGNDCOLOR, 0, cbc);\r
1253     SendDlgItemMessage(hDlg, OPT_SampleChannel,   EM_SETBKGNDCOLOR, 0, cbc);\r
1254     SendDlgItemMessage(hDlg, OPT_SampleKibitz,    EM_SETBKGNDCOLOR, 0, cbc);\r
1255     SendDlgItemMessage(hDlg, OPT_SampleTell,      EM_SETBKGNDCOLOR, 0, cbc);\r
1256     SendDlgItemMessage(hDlg, OPT_SampleChallenge, EM_SETBKGNDCOLOR, 0, cbc);\r
1257     SendDlgItemMessage(hDlg, OPT_SampleRequest,   EM_SETBKGNDCOLOR, 0, cbc);\r
1258     SendDlgItemMessage(hDlg, OPT_SampleSeek,      EM_SETBKGNDCOLOR, 0, cbc);\r
1259     SendDlgItemMessage(hDlg, OPT_SampleNormal,    EM_SETBKGNDCOLOR, 0, cbc);\r
1260 \r
1261     SetDlgItemText(hDlg, OPT_SampleShout,     T_(mca[ColorShout].name));\r
1262     SetDlgItemText(hDlg, OPT_SampleSShout,    T_(mca[ColorSShout].name));\r
1263     SetDlgItemText(hDlg, OPT_SampleChannel1,  T_(mca[ColorChannel1].name));\r
1264     SetDlgItemText(hDlg, OPT_SampleChannel,   T_(mca[ColorChannel].name));\r
1265     SetDlgItemText(hDlg, OPT_SampleKibitz,    T_(mca[ColorKibitz].name));\r
1266     SetDlgItemText(hDlg, OPT_SampleTell,      T_(mca[ColorTell].name));\r
1267     SetDlgItemText(hDlg, OPT_SampleChallenge, T_(mca[ColorChallenge].name));\r
1268     SetDlgItemText(hDlg, OPT_SampleRequest,   T_(mca[ColorRequest].name));\r
1269     SetDlgItemText(hDlg, OPT_SampleSeek,      T_(mca[ColorSeek].name));\r
1270     SetDlgItemText(hDlg, OPT_SampleNormal,    T_(mca[ColorNormal].name));\r
1271 \r
1272     UpdateSampleText(hDlg, OPT_SampleShout,     &mca[ColorShout]);\r
1273     UpdateSampleText(hDlg, OPT_SampleSShout,    &mca[ColorSShout]);\r
1274     UpdateSampleText(hDlg, OPT_SampleChannel1,  &mca[ColorChannel1]);\r
1275     UpdateSampleText(hDlg, OPT_SampleChannel,   &mca[ColorChannel]);\r
1276     UpdateSampleText(hDlg, OPT_SampleKibitz,    &mca[ColorKibitz]);\r
1277     UpdateSampleText(hDlg, OPT_SampleTell,      &mca[ColorTell]);\r
1278     UpdateSampleText(hDlg, OPT_SampleChallenge, &mca[ColorChallenge]);\r
1279     UpdateSampleText(hDlg, OPT_SampleRequest,   &mca[ColorRequest]);\r
1280     UpdateSampleText(hDlg, OPT_SampleSeek,      &mca[ColorSeek]);\r
1281     UpdateSampleText(hDlg, OPT_SampleNormal,    &mca[ColorNormal]);\r
1282 \r
1283     SetIcsOptionEnables(hDlg);\r
1284     return TRUE;\r
1285 \r
1286   case WM_COMMAND: /* message: received a command */\r
1287     switch (LOWORD(wParam)) {\r
1288 \r
1289     case WM_USER_GetConsoleBackground:\r
1290       /* the ColorizeTextDialog needs the current background color */\r
1291       colorref = (COLORREF *)lParam;\r
1292       *colorref = cbc;\r
1293       return FALSE;\r
1294 \r
1295     case IDOK:\r
1296       /* Read changed options from the dialog box */\r
1297       GetDlgItemText(hDlg, OPT_IcsAlarmTime, buf, MSG_SIZ);\r
1298       if (sscanf(buf, "%d", &number) != 1 || (number < 0)){\r
1299           MessageBox(hDlg, _("Invalid ICS Alarm Time"),\r
1300                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
1301           return FALSE;\r
1302       }\r
1303 \r
1304 #define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x))\r
1305 \r
1306       appData.icsAlarm         = IS_CHECKED(OPT_IcsAlarm);\r
1307       appData.premove          = IS_CHECKED(OPT_Premove);\r
1308       appData.premoveWhite     = IS_CHECKED(OPT_PremoveWhite);\r
1309       appData.premoveBlack     = IS_CHECKED(OPT_PremoveBlack);\r
1310       appData.autoKibitz       = IS_CHECKED(OPT_AutoKibitz);\r
1311       appData.autoComment      = IS_CHECKED(OPT_AutoComment);\r
1312       appData.autoObserve      = IS_CHECKED(OPT_AutoObserve);\r
1313       appData.autoCreateLogon  = IS_CHECKED(OPT_AutoCreate);\r
1314       appData.getMoveList      = IS_CHECKED(OPT_GetMoveList);\r
1315       appData.localLineEditing = IS_CHECKED(OPT_LocalLineEditing);\r
1316       appData.quietPlay        = IS_CHECKED(OPT_QuietPlay);\r
1317       appData.seekGraph        = IS_CHECKED(OPT_SeekGraph);\r
1318       appData.autoRefresh      = IS_CHECKED(OPT_AutoRefresh);\r
1319       appData.bgObserve        = IS_CHECKED(OPT_BgObserve);\r
1320       appData.dualBoard        = IS_CHECKED(OPT_DualBoard);\r
1321       appData.oneClick         = IS_CHECKED(OPT_SmartMove);\r
1322 \r
1323 #undef IS_CHECKED\r
1324 \r
1325       appData.icsAlarmTime = number * 1000;\r
1326       GetDlgItemText(hDlg, OPT_PremoveWhiteText, appData.premoveWhiteText, 5);\r
1327       GetDlgItemText(hDlg, OPT_PremoveBlackText, appData.premoveBlackText, 5);\r
1328       GetDlgItemText(hDlg, OPT_StartupChatBoxes, buf, sizeof(buf));\r
1329       buf[sizeof(buf)-1] = NULLCHAR; appData.chatBoxes = StrSave(buf); // memory leak\r
1330 \r
1331       if (appData.localLineEditing) {\r
1332         DontEcho();\r
1333         EchoOn();\r
1334       } else {\r
1335         DoEcho();\r
1336         EchoOff();\r
1337       }\r
1338 \r
1339       appData.colorize =\r
1340         (Boolean)!IsDlgButtonChecked(hDlg, OPT_DontColorize);\r
1341 \r
1342     ChangedConsoleFont();\r
1343 \r
1344     if (!appData.colorize) {\r
1345         CHARFORMAT cf;\r
1346         COLORREF background = ParseColorName(COLOR_BKGD);\r
1347         /*\r
1348         SetDefaultTextAttribs();\r
1349         Colorize(currentColorClass);\r
1350         */\r
1351         cf.cbSize = sizeof(CHARFORMAT);\r
1352         cf.dwMask = CFM_COLOR;\r
1353         cf.crTextColor = ParseColorName(COLOR_NORMAL);\r
1354 \r
1355         SendDlgItemMessage(hwndConsole, OPT_ConsoleInput,\r
1356           EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);\r
1357         SendDlgItemMessage(hwndConsole, OPT_ConsoleText,\r
1358           EM_SETBKGNDCOLOR, FALSE, background);\r
1359         SendDlgItemMessage(hwndConsole, OPT_ConsoleInput,\r
1360           EM_SETBKGNDCOLOR, FALSE, background);\r
1361       }\r
1362 \r
1363       if (cbc != consoleBackgroundColor) {\r
1364         consoleBackgroundColor = cbc;\r
1365         if (appData.colorize) {\r
1366           SendDlgItemMessage(hwndConsole, OPT_ConsoleText,\r
1367             EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor);\r
1368           SendDlgItemMessage(hwndConsole, OPT_ConsoleInput,\r
1369             EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor);\r
1370         }\r
1371       }\r
1372 \r
1373       for (i=0; i < NColorClasses - 1; i++) {\r
1374         textAttribs[i].color   = mca[i].color;\r
1375         textAttribs[i].effects = mca[i].effects;\r
1376       }\r
1377 \r
1378       EndDialog(hDlg, TRUE);\r
1379       return TRUE;\r
1380 \r
1381     case IDCANCEL:\r
1382       EndDialog(hDlg, FALSE);\r
1383       return TRUE;\r
1384 \r
1385     case OPT_ChooseShoutColor:\r
1386       ColorizeTextPopup(hDlg, ColorShout);\r
1387       UpdateSampleText(hDlg, OPT_SampleShout, &mca[ColorShout]);\r
1388       break;\r
1389 \r
1390     case OPT_ChooseSShoutColor:\r
1391       ColorizeTextPopup(hDlg, ColorSShout);\r
1392       UpdateSampleText(hDlg, OPT_SampleSShout, &mca[ColorSShout]);\r
1393       break;\r
1394 \r
1395     case OPT_ChooseChannel1Color:\r
1396       ColorizeTextPopup(hDlg, ColorChannel1);\r
1397       UpdateSampleText(hDlg, OPT_SampleChannel1,\r
1398                        &colorizeAttribs[ColorChannel1]);\r
1399       break;\r
1400 \r
1401     case OPT_ChooseChannelColor:\r
1402       ColorizeTextPopup(hDlg, ColorChannel);\r
1403       UpdateSampleText(hDlg, OPT_SampleChannel, &mca[ColorChannel]);\r
1404       break;\r
1405 \r
1406     case OPT_ChooseKibitzColor:\r
1407       ColorizeTextPopup(hDlg, ColorKibitz);\r
1408       UpdateSampleText(hDlg, OPT_SampleKibitz, &mca[ColorKibitz]);\r
1409       break;\r
1410 \r
1411     case OPT_ChooseTellColor:\r
1412       ColorizeTextPopup(hDlg, ColorTell);\r
1413       UpdateSampleText(hDlg, OPT_SampleTell, &mca[ColorTell]);\r
1414       break;\r
1415 \r
1416     case OPT_ChooseChallengeColor:\r
1417       ColorizeTextPopup(hDlg, ColorChallenge);\r
1418       UpdateSampleText(hDlg, OPT_SampleChallenge, &mca[ColorChallenge]);\r
1419       break;\r
1420 \r
1421     case OPT_ChooseRequestColor:\r
1422       ColorizeTextPopup(hDlg, ColorRequest);\r
1423       UpdateSampleText(hDlg, OPT_SampleRequest, &mca[ColorRequest]);\r
1424       break;\r
1425 \r
1426     case OPT_ChooseSeekColor:\r
1427       ColorizeTextPopup(hDlg, ColorSeek);\r
1428       UpdateSampleText(hDlg, OPT_SampleSeek, &mca[ColorSeek]);\r
1429       break;\r
1430 \r
1431 \r
1432 \r
1433 \r
1434     case OPT_ChooseNormalColor:\r
1435       ColorizeTextPopup(hDlg, ColorNormal);\r
1436       UpdateSampleText(hDlg, OPT_SampleNormal, &mca[ColorNormal]);\r
1437       break;\r
1438 \r
1439     case OPT_ChooseBackgroundColor:\r
1440       if (ChangeColor(hDlg, &cbc)) {\r
1441         SendDlgItemMessage(hDlg, OPT_SampleShout,     EM_SETBKGNDCOLOR, 0, cbc);\r
1442         SendDlgItemMessage(hDlg, OPT_SampleSShout,    EM_SETBKGNDCOLOR, 0, cbc);\r
1443         SendDlgItemMessage(hDlg, OPT_SampleChannel1,  EM_SETBKGNDCOLOR, 0, cbc);\r
1444         SendDlgItemMessage(hDlg, OPT_SampleChannel,   EM_SETBKGNDCOLOR, 0, cbc);\r
1445         SendDlgItemMessage(hDlg, OPT_SampleKibitz,    EM_SETBKGNDCOLOR, 0, cbc);\r
1446         SendDlgItemMessage(hDlg, OPT_SampleTell,      EM_SETBKGNDCOLOR, 0, cbc);\r
1447         SendDlgItemMessage(hDlg, OPT_SampleChallenge, EM_SETBKGNDCOLOR, 0, cbc);\r
1448         SendDlgItemMessage(hDlg, OPT_SampleRequest,   EM_SETBKGNDCOLOR, 0, cbc);\r
1449         SendDlgItemMessage(hDlg, OPT_SampleSeek,      EM_SETBKGNDCOLOR, 0, cbc);\r
1450         SendDlgItemMessage(hDlg, OPT_SampleNormal,    EM_SETBKGNDCOLOR, 0, cbc);\r
1451       }\r
1452       break;\r
1453 \r
1454     case OPT_DefaultColors:\r
1455       for (i=0; i < NColorClasses - 1; i++)\r
1456         ParseAttribs(&mca[i].color,\r
1457                      &mca[i].effects,\r
1458                      defaultTextAttribs[i]);\r
1459 \r
1460       cbc = ParseColorName(COLOR_BKGD);\r
1461       SendDlgItemMessage(hDlg, OPT_SampleShout,     EM_SETBKGNDCOLOR, 0, cbc);\r
1462       SendDlgItemMessage(hDlg, OPT_SampleSShout,    EM_SETBKGNDCOLOR, 0, cbc);\r
1463       SendDlgItemMessage(hDlg, OPT_SampleChannel1,  EM_SETBKGNDCOLOR, 0, cbc);\r
1464       SendDlgItemMessage(hDlg, OPT_SampleChannel,   EM_SETBKGNDCOLOR, 0, cbc);\r
1465       SendDlgItemMessage(hDlg, OPT_SampleKibitz,    EM_SETBKGNDCOLOR, 0, cbc);\r
1466       SendDlgItemMessage(hDlg, OPT_SampleTell,      EM_SETBKGNDCOLOR, 0, cbc);\r
1467       SendDlgItemMessage(hDlg, OPT_SampleChallenge, EM_SETBKGNDCOLOR, 0, cbc);\r
1468       SendDlgItemMessage(hDlg, OPT_SampleRequest,   EM_SETBKGNDCOLOR, 0, cbc);\r
1469       SendDlgItemMessage(hDlg, OPT_SampleSeek,      EM_SETBKGNDCOLOR, 0, cbc);\r
1470       SendDlgItemMessage(hDlg, OPT_SampleNormal,    EM_SETBKGNDCOLOR, 0, cbc);\r
1471 \r
1472       UpdateSampleText(hDlg, OPT_SampleShout,     &mca[ColorShout]);\r
1473       UpdateSampleText(hDlg, OPT_SampleSShout,    &mca[ColorSShout]);\r
1474       UpdateSampleText(hDlg, OPT_SampleChannel1,  &mca[ColorChannel1]);\r
1475       UpdateSampleText(hDlg, OPT_SampleChannel,   &mca[ColorChannel]);\r
1476       UpdateSampleText(hDlg, OPT_SampleKibitz,    &mca[ColorKibitz]);\r
1477       UpdateSampleText(hDlg, OPT_SampleTell,      &mca[ColorTell]);\r
1478       UpdateSampleText(hDlg, OPT_SampleChallenge, &mca[ColorChallenge]);\r
1479       UpdateSampleText(hDlg, OPT_SampleRequest,   &mca[ColorRequest]);\r
1480       UpdateSampleText(hDlg, OPT_SampleSeek,      &mca[ColorSeek]);\r
1481       UpdateSampleText(hDlg, OPT_SampleNormal,    &mca[ColorNormal]);\r
1482       break;\r
1483 \r
1484     default:\r
1485       SetIcsOptionEnables(hDlg);\r
1486       break;\r
1487     }\r
1488     break;\r
1489   }\r
1490   return FALSE;\r
1491 }\r
1492 \r
1493 VOID\r
1494 IcsOptionsPopup(HWND hwnd)\r
1495 {\r
1496   FARPROC lpProc = MakeProcInstance((FARPROC)IcsOptionsDialog, hInst);\r
1497   DialogBox(hInst, MAKEINTRESOURCE(DLG_IcsOptions), hwnd,\r
1498             (DLGPROC) lpProc);\r
1499   FreeProcInstance(lpProc);\r
1500 }\r
1501 \r
1502 /*---------------------------------------------------------------------------*\\r
1503  *\r
1504  * Fonts Dialog functions\r
1505  *\r
1506 \*---------------------------------------------------------------------------*/\r
1507 \r
1508 char *string; // sorry\r
1509 \r
1510 VOID\r
1511 SetSampleFontText(HWND hwnd, int id, const MyFont *mf)\r
1512 {\r
1513   char buf[MSG_SIZ];\r
1514   HWND hControl;\r
1515   HDC hdc;\r
1516   CHARFORMAT cf;\r
1517   SIZE size;\r
1518   RECT rectClient, rectFormat;\r
1519   HFONT oldFont;\r
1520   POINT center;\r
1521   int len;\r
1522 \r
1523   len = snprintf(buf, MSG_SIZ, "%.0f pt. %s%s%s\n",\r
1524                  mf->mfp.pointSize, mf->mfp.faceName,\r
1525                  mf->mfp.bold ? " bold" : "",\r
1526                  mf->mfp.italic ? " italic" : "");\r
1527  if(id != OPT_SamplePieceFont)\r
1528   SetDlgItemText(hwnd, id, buf);\r
1529  else SetDlgItemText(hwnd, id, string);\r
1530 \r
1531   hControl = GetDlgItem(hwnd, id);\r
1532   hdc = GetDC(hControl);\r
1533   SetMapMode(hdc, MM_TEXT);     /* 1 pixel == 1 logical unit */\r
1534   oldFont = SelectObject(hdc, mf->hf);\r
1535 \r
1536   /* get number of logical units necessary to display font name */\r
1537   GetTextExtentPoint32(hdc, buf, len, &size);\r
1538 \r
1539   /* calculate formatting rectangle in the rich edit control.\r
1540    * May be larger or smaller than the actual control.\r
1541    */\r
1542   GetClientRect(hControl, &rectClient);\r
1543   center.x = (rectClient.left + rectClient.right) / 2;\r
1544   center.y = (rectClient.top  + rectClient.bottom) / 2;\r
1545   rectFormat.top    = center.y - (size.cy / 2) - 1;\r
1546   rectFormat.bottom = center.y + (size.cy / 2) + 1;\r
1547   rectFormat.left   = center.x - (size.cx / 2) - 1;\r
1548   rectFormat.right  = center.x + (size.cx / 2) + 1;\r
1549 \r
1550   cf.cbSize = sizeof(CHARFORMAT);\r
1551   cf.dwMask = CFM_FACE|CFM_SIZE|CFM_CHARSET|CFM_BOLD|CFM_ITALIC;\r
1552   cf.dwEffects = 0;\r
1553   if (mf->lf.lfWeight == FW_BOLD) cf.dwEffects |= CFE_BOLD;\r
1554   if (mf->lf.lfItalic) cf.dwEffects |= CFE_ITALIC;\r
1555   safeStrCpy(cf.szFaceName, mf->mfp.faceName, sizeof(cf.szFaceName)/sizeof(cf.szFaceName[0]) );\r
1556   /*\r
1557    * yHeight is expressed in twips.  A twip is 1/20 of a font's point\r
1558    * size. See documentation of CHARFORMAT.  --msw\r
1559    */\r
1560   cf.yHeight = (int)(mf->mfp.pointSize * 20.0 + 0.5);\r
1561   cf.bCharSet = mf->lf.lfCharSet;\r
1562   cf.bPitchAndFamily = mf->lf.lfPitchAndFamily;\r
1563 \r
1564   /* format the text in the rich edit control */\r
1565   SendMessage(hControl, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &cf);\r
1566  if(id != OPT_SamplePieceFont)\r
1567   SendMessage(hControl, EM_SETRECT, (WPARAM)0, (LPARAM) &rectFormat);\r
1568 \r
1569   /* clean up */\r
1570   SelectObject(hdc, oldFont);\r
1571   ReleaseDC(hControl, hdc);\r
1572 }\r
1573 \r
1574 VOID\r
1575 CopyFont(MyFont *dest, const MyFont *src)\r
1576 {\r
1577   dest->mfp.pointSize = src->mfp.pointSize;\r
1578   dest->mfp.bold      = src->mfp.bold;\r
1579   dest->mfp.italic    = src->mfp.italic;\r
1580   dest->mfp.underline = src->mfp.underline;\r
1581   dest->mfp.strikeout = src->mfp.strikeout;\r
1582   dest->mfp.charset   = src->mfp.charset;\r
1583   safeStrCpy(dest->mfp.faceName, src->mfp.faceName, sizeof(dest->mfp.faceName)/sizeof(dest->mfp.faceName[0]) );\r
1584   CreateFontInMF(dest);\r
1585 }\r
1586 \r
1587 \r
1588 LRESULT CALLBACK\r
1589 FontOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
1590 {\r
1591   static MyFont workFont[NUM_FONTS+1];\r
1592   static BOOL firstPaint;\r
1593   static char pieceText[] = "ABCDEFGHIJKLMNOPQRSTUVWXZabcdefghijklmnopqrstuvwxyz";\r
1594   int i;\r
1595   RECT rect;\r
1596 \r
1597   switch (message) {\r
1598   case WM_INITDIALOG:\r
1599 \r
1600     /* copy the current font settings into a working copy */\r
1601     for (i=0; i < NUM_FONTS; i++)\r
1602       CopyFont(&workFont[i], font[boardSize][i]);\r
1603     strncpy(workFont[NUM_FONTS].mfp.faceName, appData.renderPiecesWithFont, sizeof(workFont[NUM_FONTS].mfp.faceName));\r
1604     workFont[NUM_FONTS].mfp.pointSize = 16.;\r
1605     workFont[NUM_FONTS].mfp.charset = DEFAULT_CHARSET;\r
1606 \r
1607     Translate(hDlg, DLG_Fonts);\r
1608     if (!appData.icsActive)\r
1609       EnableWindow(GetDlgItem(hDlg, OPT_ChooseConsoleFont), FALSE);\r
1610 \r
1611     firstPaint = TRUE;  /* see rant below */\r
1612 \r
1613     /* If I don't call SetFocus(), the dialog won't respond to the keyboard\r
1614      * when first drawn. Why is this the only dialog that behaves this way? Is\r
1615      * is the WM_PAINT stuff below?? Sigh...\r
1616      */\r
1617     SetFocus(GetDlgItem(hDlg, IDOK));\r
1618     break;\r
1619 \r
1620   case WM_PAINT:\r
1621     /* This should not be necessary. However, if SetSampleFontText() is called\r
1622      * in response to WM_INITDIALOG, the strings are not properly centered in\r
1623      * the controls when the dialog first appears. I can't figure out why, so\r
1624      * this is the workaround.  --msw\r
1625      */\r
1626     if (firstPaint) {\r
1627       SetSampleFontText(hDlg, OPT_SampleClockFont, &workFont[CLOCK_FONT]);\r
1628       SetSampleFontText(hDlg, OPT_SampleMessageFont, &workFont[MESSAGE_FONT]);\r
1629       SetSampleFontText(hDlg, OPT_SampleCoordFont, &workFont[COORD_FONT]);\r
1630       SetSampleFontText(hDlg, OPT_SampleTagFont, &workFont[EDITTAGS_FONT]);\r
1631       SetSampleFontText(hDlg, OPT_SampleCommentsFont, &workFont[COMMENT_FONT]);\r
1632       SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]);\r
1633       SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]);\r
1634       SetSampleFontText(hDlg, OPT_SampleGameListFont, &workFont[GAMELIST_FONT]);\r
1635       string = appData.fontToPieceTable;\r
1636       SetSampleFontText(hDlg, OPT_SamplePieceFont, &workFont[NUM_FONTS]);\r
1637       firstPaint = FALSE;\r
1638     }\r
1639     break;\r
1640 \r
1641   case WM_COMMAND: /* message: received a command */\r
1642     switch (LOWORD(wParam)) {\r
1643 \r
1644     case IDOK:\r
1645       /* again, it seems to avoid redraw problems if we call EndDialog first */\r
1646       EndDialog(hDlg, FALSE);\r
1647 \r
1648       /* copy modified settings back to the fonts array */\r
1649       for (i=0; i < NUM_FONTS; i++)\r
1650         CopyFont(font[boardSize][i], &workFont[i]);\r
1651 \r
1652       { // Make new piece-to-char table\r
1653         char buf[MSG_SIZ];\r
1654         GetDlgItemText(hDlg, OPT_SamplePieceFont, buf, MSG_SIZ);\r
1655         ASSIGN(appData.fontToPieceTable, buf);\r
1656       }\r
1657       ASSIGN(appData.renderPiecesWithFont, workFont[NUM_FONTS].mfp.faceName); // piece font\r
1658 \r
1659       /* a sad necessity due to the original design of having a separate\r
1660        * console font, tags font, and comment font for each board size.  IMHO\r
1661        * these fonts should not be dependent on the current board size.  I'm\r
1662        * running out of time, so I am doing this hack rather than redesign the\r
1663        * data structure. Besides, I think if I redesigned the data structure, I\r
1664        * might break backwards compatibility with old winboard.ini files.\r
1665        * --msw\r
1666        */\r
1667       for (i=0; i < NUM_SIZES; i++) {\r
1668         CopyFont(font[i][EDITTAGS_FONT], &workFont[EDITTAGS_FONT]);\r
1669         CopyFont(font[i][CONSOLE_FONT],  &workFont[CONSOLE_FONT]);\r
1670         CopyFont(font[i][COMMENT_FONT],  &workFont[COMMENT_FONT]);\r
1671         CopyFont(font[i][MOVEHISTORY_FONT],  &workFont[MOVEHISTORY_FONT]);\r
1672         CopyFont(font[i][GAMELIST_FONT],  &workFont[GAMELIST_FONT]);\r
1673       }\r
1674       /* end sad necessity */\r
1675 \r
1676       InitDrawingSizes(boardSize, 0);\r
1677       InvalidateRect(hwndMain, NULL, TRUE);\r
1678 \r
1679       if (commentDialog) {\r
1680         SendDlgItemMessage(commentDialog, OPT_CommentText,\r
1681           WM_SETFONT, (WPARAM)font[boardSize][COMMENT_FONT]->hf,\r
1682           MAKELPARAM(TRUE, 0));\r
1683         GetClientRect(GetDlgItem(commentDialog, OPT_CommentText), &rect);\r
1684         InvalidateRect(commentDialog, &rect, TRUE);\r
1685       }\r
1686 \r
1687       if (editTagsDialog) {\r
1688         SendDlgItemMessage(editTagsDialog, OPT_TagsText,\r
1689           WM_SETFONT, (WPARAM)font[boardSize][EDITTAGS_FONT]->hf,\r
1690           MAKELPARAM(TRUE, 0));\r
1691         GetClientRect(GetDlgItem(editTagsDialog, OPT_TagsText), &rect);\r
1692         InvalidateRect(editTagsDialog, &rect, TRUE);\r
1693       }\r
1694 \r
1695       if( moveHistoryDialog != NULL ) {\r
1696         SendDlgItemMessage(moveHistoryDialog, IDC_MoveHistory,\r
1697           WM_SETFONT, (WPARAM)font[boardSize][MOVEHISTORY_FONT]->hf,\r
1698           MAKELPARAM(TRUE, 0));\r
1699         SendMessage( moveHistoryDialog, WM_INITDIALOG, 0, 0 );\r
1700 //      InvalidateRect(editTagsDialog, NULL, TRUE); // [HGM] this ws improperly cloned?\r
1701       }\r
1702 \r
1703       if( engineOutputDialog != NULL ) {\r
1704         SendDlgItemMessage(engineOutputDialog, IDC_EngineMemo1,\r
1705           WM_SETFONT, (WPARAM)font[boardSize][MOVEHISTORY_FONT]->hf,\r
1706           MAKELPARAM(TRUE, 0));\r
1707         SendDlgItemMessage(engineOutputDialog, IDC_EngineMemo2,\r
1708           WM_SETFONT, (WPARAM)font[boardSize][MOVEHISTORY_FONT]->hf,\r
1709           MAKELPARAM(TRUE, 0));\r
1710       }\r
1711 \r
1712       if (hwndConsole) {\r
1713         ChangedConsoleFont();\r
1714       }\r
1715 \r
1716       for (i=0; i<NUM_FONTS; i++)\r
1717         DeleteObject(&workFont[i].hf);\r
1718 \r
1719       return TRUE;\r
1720 \r
1721     case IDCANCEL:\r
1722       for (i=0; i<NUM_FONTS; i++)\r
1723         DeleteObject(&workFont[i].hf);\r
1724       EndDialog(hDlg, FALSE);\r
1725       return TRUE;\r
1726 \r
1727     case OPT_ChooseClockFont:\r
1728       MyCreateFont(hDlg, &workFont[CLOCK_FONT]);\r
1729       SetSampleFontText(hDlg, OPT_SampleClockFont, &workFont[CLOCK_FONT]);\r
1730       break;\r
1731 \r
1732     case OPT_ChooseMessageFont:\r
1733       MyCreateFont(hDlg, &workFont[MESSAGE_FONT]);\r
1734       SetSampleFontText(hDlg, OPT_SampleMessageFont, &workFont[MESSAGE_FONT]);\r
1735       break;\r
1736 \r
1737     case OPT_ChooseCoordFont:\r
1738       MyCreateFont(hDlg, &workFont[COORD_FONT]);\r
1739       SetSampleFontText(hDlg, OPT_SampleCoordFont, &workFont[COORD_FONT]);\r
1740       break;\r
1741 \r
1742     case OPT_ChooseTagFont:\r
1743       MyCreateFont(hDlg, &workFont[EDITTAGS_FONT]);\r
1744       SetSampleFontText(hDlg, OPT_SampleTagFont, &workFont[EDITTAGS_FONT]);\r
1745       break;\r
1746 \r
1747     case OPT_ChooseCommentsFont:\r
1748       MyCreateFont(hDlg, &workFont[COMMENT_FONT]);\r
1749       SetSampleFontText(hDlg, OPT_SampleCommentsFont, &workFont[COMMENT_FONT]);\r
1750       break;\r
1751 \r
1752     case OPT_ChooseConsoleFont:\r
1753       MyCreateFont(hDlg, &workFont[CONSOLE_FONT]);\r
1754       SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]);\r
1755       break;\r
1756 \r
1757     case OPT_ChooseMoveHistoryFont:\r
1758       MyCreateFont(hDlg, &workFont[MOVEHISTORY_FONT]);\r
1759       SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]);\r
1760       break;\r
1761 \r
1762     case OPT_ChooseGameListFont:\r
1763       MyCreateFont(hDlg, &workFont[GAMELIST_FONT]);\r
1764       SetSampleFontText(hDlg, OPT_SampleGameListFont, &workFont[GAMELIST_FONT]);\r
1765       break;\r
1766 \r
1767     case OPT_ChoosePieceFont:\r
1768       MyCreateFont(hDlg, &workFont[NUM_FONTS]);\r
1769       string = pieceText;\r
1770       SetSampleFontText(hDlg, OPT_SamplePieceFont, &workFont[NUM_FONTS]);\r
1771       break;\r
1772 \r
1773     case OPT_DefaultFonts:\r
1774       for (i=0; i<NUM_FONTS; i++) {\r
1775         DeleteObject(&workFont[i].hf);\r
1776         ParseFontName(font[boardSize][i]->def, &workFont[i].mfp);\r
1777         CreateFontInMF(&workFont[i]);\r
1778       }\r
1779       SetSampleFontText(hDlg, OPT_SampleClockFont, &workFont[CLOCK_FONT]);\r
1780       SetSampleFontText(hDlg, OPT_SampleMessageFont, &workFont[MESSAGE_FONT]);\r
1781       SetSampleFontText(hDlg, OPT_SampleCoordFont, &workFont[COORD_FONT]);\r
1782       SetSampleFontText(hDlg, OPT_SampleTagFont, &workFont[EDITTAGS_FONT]);\r
1783       SetSampleFontText(hDlg, OPT_SampleCommentsFont, &workFont[COMMENT_FONT]);\r
1784       SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]);\r
1785       SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]);\r
1786       SetSampleFontText(hDlg, OPT_SampleGameListFont, &workFont[GAMELIST_FONT]);\r
1787       break;\r
1788     }\r
1789   }\r
1790   return FALSE;\r
1791 }\r
1792 \r
1793 VOID\r
1794 FontsOptionsPopup(HWND hwnd)\r
1795 {\r
1796   FARPROC lpProc = MakeProcInstance((FARPROC)FontOptionsDialog, hInst);\r
1797   DialogBox(hInst, MAKEINTRESOURCE(DLG_Fonts), hwnd,\r
1798           (DLGPROC) lpProc);\r
1799   FreeProcInstance(lpProc);\r
1800 }\r
1801 \r
1802 /*---------------------------------------------------------------------------*\\r
1803  *\r
1804  * Sounds Dialog functions\r
1805  *\r
1806 \*---------------------------------------------------------------------------*/\r
1807 \r
1808 \r
1809 SoundComboData soundComboData[] = {\r
1810   {N_("Move"), NULL},\r
1811   {N_("Bell"), NULL},\r
1812   {N_("Roar"), NULL},\r
1813   {N_("ICS Alarm"), NULL},\r
1814   {N_("ICS Win"), NULL},\r
1815   {N_("ICS Loss"), NULL},\r
1816   {N_("ICS Draw"), NULL},\r
1817   {N_("ICS Unfinished"), NULL},\r
1818   {N_("Shout"), NULL},\r
1819   {N_("SShout/CShout"), NULL},\r
1820   {N_("Channel 1"), NULL},\r
1821   {N_("Channel"), NULL},\r
1822   {N_("Kibitz"), NULL},\r
1823   {N_("Tell"), NULL},\r
1824   {N_("Challenge"), NULL},\r
1825   {N_("Request"), NULL},\r
1826   {N_("Seek"), NULL},\r
1827   {NULL, NULL},\r
1828 };\r
1829 \r
1830 \r
1831 void\r
1832 InitSoundComboData(SoundComboData *scd)\r
1833 {\r
1834   SoundClass sc;\r
1835   ColorClass cc;\r
1836   int index;\r
1837 \r
1838   /* copy current sound settings to combo array */\r
1839 \r
1840   for ( sc = (SoundClass)0; sc < NSoundClasses; sc++) {\r
1841     scd[sc].name = strdup(sounds[sc].name);\r
1842   }\r
1843   for ( cc = (ColorClass)0; cc < NColorClasses - 2; cc++) {\r
1844     index = (int)cc + (int)NSoundClasses;\r
1845     scd[index].name = strdup(textAttribs[cc].sound.name);\r
1846   }\r
1847 }\r
1848 \r
1849 \r
1850 void\r
1851 ResetSoundComboData(SoundComboData *scd)\r
1852 {\r
1853   while (scd->label) {\r
1854     if (scd->name != NULL) {\r
1855       free (scd->name);\r
1856       scd->name = NULL;\r
1857     }\r
1858     scd++;\r
1859   }\r
1860 }\r
1861 \r
1862 void\r
1863 InitSoundCombo(HWND hwndCombo, SoundComboData *scd)\r
1864 {\r
1865   char buf[255];\r
1866   DWORD err;\r
1867   DWORD cnt = 0;\r
1868   SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0);\r
1869 \r
1870   /* send the labels to the combo box */\r
1871   while (scd->label) {\r
1872     err = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) T_(scd->label));\r
1873     if (err != cnt++) {\r
1874       snprintf(buf, MSG_SIZ,  "InitSoundCombo(): err '%d', cnt '%d'\n",\r
1875           (int)err, (int)cnt);\r
1876       MessageBox(NULL, buf, NULL, MB_OK);\r
1877     }\r
1878     scd++;\r
1879   }\r
1880   SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
1881 }\r
1882 \r
1883 int\r
1884 SoundDialogWhichRadio(HWND hDlg)\r
1885 {\r
1886   if (IsDlgButtonChecked(hDlg, OPT_NoSound)) return OPT_NoSound;\r
1887   if (IsDlgButtonChecked(hDlg, OPT_DefaultBeep)) return OPT_DefaultBeep;\r
1888   if (IsDlgButtonChecked(hDlg, OPT_BuiltInSound)) return OPT_BuiltInSound;\r
1889   if (IsDlgButtonChecked(hDlg, OPT_WavFile)) return OPT_WavFile;\r
1890   return -1;\r
1891 }\r
1892 \r
1893 VOID\r
1894 SoundDialogSetEnables(HWND hDlg, int radio)\r
1895 {\r
1896   EnableWindow(GetDlgItem(hDlg, OPT_BuiltInSoundName),\r
1897                radio == OPT_BuiltInSound);\r
1898   EnableWindow(GetDlgItem(hDlg, OPT_WavFileName), radio == OPT_WavFile);\r
1899   EnableWindow(GetDlgItem(hDlg, OPT_BrowseSound), radio == OPT_WavFile);\r
1900 }\r
1901 \r
1902 char *\r
1903 SoundDialogGetName(HWND hDlg, int radio)\r
1904 {\r
1905   static char buf[MSG_SIZ], buf2[MSG_SIZ], buf3[MSG_SIZ];\r
1906   char *dummy, *ret;\r
1907   switch (radio) {\r
1908   case OPT_NoSound:\r
1909   default:\r
1910     return "";\r
1911   case OPT_DefaultBeep:\r
1912     return "$";\r
1913   case OPT_BuiltInSound:\r
1914     buf[0] = '!';\r
1915     GetDlgItemText(hDlg, OPT_BuiltInSoundName, buf + 1, sizeof(buf) - 1);\r
1916     return buf;\r
1917   case OPT_WavFile:\r
1918     GetDlgItemText(hDlg, OPT_WavFileName, buf, sizeof(buf));\r
1919     GetCurrentDirectory(MSG_SIZ, buf3);\r
1920     SetCurrentDirectory(installDir);\r
1921     if (GetFullPathName(buf, MSG_SIZ, buf2, &dummy)) {\r
1922       ret = buf2;\r
1923     } else {\r
1924       ret = buf;\r
1925     }\r
1926     SetCurrentDirectory(buf3);\r
1927     return ret;\r
1928   }\r
1929 }\r
1930 \r
1931 void\r
1932 DisplaySelectedSound(HWND hDlg, HWND hCombo, const char *name)\r
1933 {\r
1934   int radio;\r
1935   /*\r
1936    * I think it's best to clear the combo and edit boxes. It looks stupid\r
1937    * to have a value from another sound event sitting there grayed out.\r
1938    */\r
1939   SetDlgItemText(hDlg, OPT_WavFileName, "");\r
1940   SendMessage(hCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);\r
1941 \r
1942   if (appData.debugMode)\r
1943       fprintf(debugFP, "DisplaySelectedSound(,,'%s'):\n", name);\r
1944   switch (name[0]) {\r
1945   case NULLCHAR:\r
1946     radio = OPT_NoSound;\r
1947     break;\r
1948   case '$':\r
1949     if (name[1] == NULLCHAR) {\r
1950       radio = OPT_DefaultBeep;\r
1951     } else {\r
1952       radio = OPT_WavFile;\r
1953       SetDlgItemText(hDlg, OPT_WavFileName, name);\r
1954     }\r
1955     break;\r
1956   case '!':\r
1957     if (name[1] == NULLCHAR) {\r
1958       radio = OPT_NoSound;\r
1959     } else {\r
1960       radio = OPT_BuiltInSound;\r
1961       if (SendMessage(hCombo, CB_SELECTSTRING, (WPARAM) -1,\r
1962                       (LPARAM) (name + 1)) == CB_ERR) {\r
1963         SendMessage(hCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);\r
1964         SendMessage(hCombo, WM_SETTEXT, (WPARAM) 0, (LPARAM) (name + 1));\r
1965       }\r
1966     }\r
1967     break;\r
1968   default:\r
1969     radio = OPT_WavFile;\r
1970     SetDlgItemText(hDlg, OPT_WavFileName, name);\r
1971     break;\r
1972   }\r
1973   SoundDialogSetEnables(hDlg, radio);\r
1974   CheckRadioButton(hDlg, OPT_NoSound, OPT_WavFile, radio);\r
1975 }\r
1976 \r
1977 \r
1978 char *builtInSoundNames[] = BUILT_IN_SOUND_NAMES;\r
1979 \r
1980 LRESULT CALLBACK\r
1981 SoundOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
1982 {\r
1983   static HWND hSoundCombo;\r
1984   static DWORD index;\r
1985   static HWND hBISN;\r
1986   int radio;\r
1987   MySound tmp;\r
1988   FILE *f;\r
1989   char buf[MSG_SIZ];\r
1990   char *newName;\r
1991   SoundClass sc;\r
1992   ColorClass cc;\r
1993   SoundComboData *scd;\r
1994   int oldMute;\r
1995 \r
1996   switch (message) {\r
1997   case WM_INITDIALOG:\r
1998     /* Center the dialog over the application window */\r
1999     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
2000     Translate(hDlg, DLG_Sound);\r
2001 \r
2002     /* Initialize the built-in sounds combo */\r
2003     hBISN = GetDlgItem(hDlg, OPT_BuiltInSoundName);\r
2004      InitComboStrings(hBISN, builtInSoundNames);\r
2005 \r
2006     /* Initialize the  sound events combo */\r
2007     index = 0;\r
2008     InitSoundComboData(soundComboData);\r
2009     hSoundCombo = GetDlgItem(hDlg, CBO_Sounds);\r
2010     InitSoundCombo(hSoundCombo, soundComboData);\r
2011 \r
2012     /* update the dialog */\r
2013     DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name);\r
2014     return TRUE;\r
2015 \r
2016   case WM_COMMAND: /* message: received a command */\r
2017 \r
2018     if (((HWND)lParam == hSoundCombo) &&\r
2019         (HIWORD(wParam) == CBN_SELCHANGE)) {\r
2020       /*\r
2021        * the user has selected a new sound event. We must store the name for\r
2022        * the previously selected event, then retrieve the name for the\r
2023        * newly selected event and update the dialog.\r
2024        */\r
2025       radio = SoundDialogWhichRadio(hDlg);\r
2026       newName = strdup(SoundDialogGetName(hDlg, radio));\r
2027 \r
2028       if (strcmp(newName, soundComboData[index].name) != 0) {\r
2029         free(soundComboData[index].name);\r
2030         soundComboData[index].name = newName;\r
2031       } else {\r
2032         free(newName);\r
2033         newName = NULL;\r
2034       }\r
2035       /* now get the settings for the newly selected event */\r
2036       index = SendMessage(hSoundCombo, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);\r
2037       DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name);\r
2038 \r
2039       return TRUE;\r
2040     }\r
2041     switch (LOWORD(wParam)) {\r
2042     case IDOK:\r
2043       /*\r
2044        * save the name for the currently selected sound event\r
2045        */\r
2046       radio = SoundDialogWhichRadio(hDlg);\r
2047       newName = strdup(SoundDialogGetName(hDlg, radio));\r
2048 \r
2049       if (strcmp(soundComboData[index].name, newName) != 0) {\r
2050         free(soundComboData[index].name);\r
2051         soundComboData[index].name = newName;\r
2052       } else {\r
2053         free(newName);\r
2054         newName = NULL;\r
2055       }\r
2056 \r
2057       /* save all the sound names that changed and load the sounds */\r
2058 \r
2059       for ( sc = (SoundClass)0; sc < NSoundClasses; sc++) {\r
2060         if (strcmp(soundComboData[sc].name, sounds[sc].name) != 0) {\r
2061           free(sounds[sc].name);\r
2062           sounds[sc].name = strdup(soundComboData[sc].name);\r
2063           MyLoadSound(&sounds[sc]);\r
2064         }\r
2065       }\r
2066       for ( cc = (ColorClass)0; cc < NColorClasses - 2; cc++) {\r
2067         index = (int)cc + (int)NSoundClasses;\r
2068         if (strcmp(soundComboData[index].name,\r
2069                    textAttribs[cc].sound.name) != 0) {\r
2070           free(textAttribs[cc].sound.name);\r
2071           textAttribs[cc].sound.name = strdup(soundComboData[index].name);\r
2072           MyLoadSound(&textAttribs[cc].sound);\r
2073         }\r
2074       }\r
2075 \r
2076         mute = FALSE; // [HGM] mute: switch sounds automatically on if we select one\r
2077       CheckMenuItem(GetMenu(hwndMain),IDM_MuteSounds,MF_BYCOMMAND|MF_UNCHECKED);\r
2078       ResetSoundComboData(soundComboData);\r
2079       EndDialog(hDlg, TRUE);\r
2080       return TRUE;\r
2081 \r
2082     case IDCANCEL:\r
2083       ResetSoundComboData(soundComboData);\r
2084       EndDialog(hDlg, FALSE);\r
2085       return TRUE;\r
2086 \r
2087     case OPT_DefaultSounds:\r
2088       /* can't use SetDefaultSounds() because we need to be able to "undo" if\r
2089        * user selects "Cancel" later on. So we do it the hard way here.\r
2090        */\r
2091       scd = &soundComboData[0];\r
2092       while (scd->label != NULL) {\r
2093         if (scd->name != NULL) free(scd->name);\r
2094         scd->name = strdup("");\r
2095         scd++;\r
2096       }\r
2097       free(soundComboData[(int)SoundBell].name);\r
2098       soundComboData[(int)SoundBell].name = strdup(SOUND_BELL);\r
2099       DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name);\r
2100       break;\r
2101 \r
2102     case OPT_PlaySound:\r
2103       radio = SoundDialogWhichRadio(hDlg);\r
2104       tmp.name = strdup(SoundDialogGetName(hDlg, radio));\r
2105       tmp.data = NULL;\r
2106       MyLoadSound(&tmp);\r
2107         oldMute = mute; mute = FALSE; // [HGM] mute: always sound when user presses play, ignorig mute setting\r
2108       MyPlaySound(&tmp);\r
2109         mute = oldMute;\r
2110       if (tmp.data  != NULL) FreeResource(tmp.data); // technically obsolete fn, but tmp.data is NOT malloc'd mem\r
2111       if (tmp.name != NULL) free(tmp.name);\r
2112       return TRUE;\r
2113 \r
2114     case OPT_BrowseSound:\r
2115       f = OpenFileDialog(hDlg, "rb", NULL, "wav", SOUND_FILT,\r
2116         _("Browse for Sound File"), NULL, NULL, buf);\r
2117       if (f != NULL) {\r
2118         fclose(f);\r
2119         SetDlgItemText(hDlg, OPT_WavFileName, buf);\r
2120       }\r
2121       return TRUE;\r
2122 \r
2123     default:\r
2124       radio = SoundDialogWhichRadio(hDlg);\r
2125       SoundDialogSetEnables(hDlg, radio);\r
2126       break;\r
2127     }\r
2128     break;\r
2129   }\r
2130   return FALSE;\r
2131 }\r
2132 \r
2133 \r
2134 VOID SoundOptionsPopup(HWND hwnd)\r
2135 {\r
2136   FARPROC lpProc;\r
2137 \r
2138   lpProc = MakeProcInstance((FARPROC)SoundOptionsDialog, hInst);\r
2139   DialogBox(hInst, MAKEINTRESOURCE(DLG_Sound), hwnd, (DLGPROC)lpProc);\r
2140   FreeProcInstance(lpProc);\r
2141 }\r
2142 \r
2143 \r
2144 /*---------------------------------------------------------------------------*\\r
2145  *\r
2146  * Comm Port dialog functions\r
2147  *\r
2148 \*---------------------------------------------------------------------------*/\r
2149 \r
2150 \r
2151 #define FLOW_NONE   0\r
2152 #define FLOW_XOFF   1\r
2153 #define FLOW_CTS    2\r
2154 #define FLOW_DSR    3\r
2155 \r
2156 #define PORT_NONE\r
2157 \r
2158 ComboData cdPort[]     = { {"None", PORT_NONE}, {"COM1", 1}, {"COM2", 2},\r
2159                            {"COM3", 3}, {"COM4", 4}, {NULL, 0} };\r
2160 ComboData cdDataRate[] = { {"110", 110}, {"300", 300}, {"600", 600}, {"1200", 1200},\r
2161                            {"2400", 2400}, {"4800", 4800}, {"9600", 9600}, {"19200", 19200},\r
2162                            {"38400", 38400}, {NULL, 0} };\r
2163 ComboData cdDataBits[] = { {"5", 5}, {"6", 6}, {"7", 7}, {"8", 8}, {NULL, 0} };\r
2164 ComboData cdParity[]   = { {"None", NOPARITY}, {"Odd", ODDPARITY}, {"Even", EVENPARITY},\r
2165                            {"Mark", MARKPARITY}, {"Space", SPACEPARITY}, {NULL, 0} };\r
2166 ComboData cdStopBits[] = { {"1", ONESTOPBIT}, {"1.5", ONE5STOPBITS},\r
2167                            {"2", TWOSTOPBITS}, {NULL, 0} };\r
2168 ComboData cdFlow[]     = { {"None", FLOW_NONE}, {"Xoff/Xon", FLOW_XOFF}, {"CTS", FLOW_CTS},\r
2169                            {"DSR", FLOW_DSR}, {NULL, 0} };\r
2170 \r
2171 \r
2172 VOID\r
2173 ParseCommSettings(char *arg, DCB *dcb)\r
2174 {\r
2175   int dataRate, count;\r
2176   char bits[MSG_SIZ], parity[MSG_SIZ], stopBits[MSG_SIZ], flow[MSG_SIZ];\r
2177   ComboData *cd;\r
2178   count = sscanf(arg, "%d%*[, ]%[^, ]%*[, ]%[^, ]%*[, ]%[^, ]%*[, ]%[^, ]",\r
2179     &dataRate, bits, parity, stopBits, flow);\r
2180   if (count != 5) goto cant_parse;\r
2181   dcb->BaudRate = dataRate;\r
2182   cd = cdDataBits;\r
2183   while (cd->label != NULL) {\r
2184     if (StrCaseCmp(cd->label, bits) == 0) {\r
2185       dcb->ByteSize = cd->value;\r
2186       break;\r
2187     }\r
2188     cd++;\r
2189   }\r
2190   if (cd->label == NULL) goto cant_parse;\r
2191   cd = cdParity;\r
2192   while (cd->label != NULL) {\r
2193     if (StrCaseCmp(cd->label, parity) == 0) {\r
2194       dcb->Parity = cd->value;\r
2195       break;\r
2196     }\r
2197     cd++;\r
2198   }\r
2199   if (cd->label == NULL) goto cant_parse;\r
2200   cd = cdStopBits;\r
2201   while (cd->label != NULL) {\r
2202     if (StrCaseCmp(cd->label, stopBits) == 0) {\r
2203       dcb->StopBits = cd->value;\r
2204       break;\r
2205     }\r
2206     cd++;\r
2207   }\r
2208   cd = cdFlow;\r
2209   if (cd->label == NULL) goto cant_parse;\r
2210   while (cd->label != NULL) {\r
2211     if (StrCaseCmp(cd->label, flow) == 0) {\r
2212       switch (cd->value) {\r
2213       case FLOW_NONE:\r
2214         dcb->fOutX = FALSE;\r
2215         dcb->fOutxCtsFlow = FALSE;\r
2216         dcb->fOutxDsrFlow = FALSE;\r
2217         break;\r
2218       case FLOW_CTS:\r
2219         dcb->fOutX = FALSE;\r
2220         dcb->fOutxCtsFlow = TRUE;\r
2221         dcb->fOutxDsrFlow = FALSE;\r
2222         break;\r
2223       case FLOW_DSR:\r
2224         dcb->fOutX = FALSE;\r
2225         dcb->fOutxCtsFlow = FALSE;\r
2226         dcb->fOutxDsrFlow = TRUE;\r
2227         break;\r
2228       case FLOW_XOFF:\r
2229         dcb->fOutX = TRUE;\r
2230         dcb->fOutxCtsFlow = FALSE;\r
2231         dcb->fOutxDsrFlow = FALSE;\r
2232         break;\r
2233       }\r
2234       break;\r
2235     }\r
2236     cd++;\r
2237   }\r
2238   if (cd->label == NULL) goto cant_parse;\r
2239   return;\r
2240 cant_parse:\r
2241     ExitArgError(_("Can't parse com port settings"), arg, TRUE);\r
2242 }\r
2243 \r
2244 \r
2245 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb)\r
2246 {\r
2247   char *flow = "??", *parity = "??", *stopBits = "??";\r
2248   ComboData *cd;\r
2249 \r
2250   cd = cdParity;\r
2251   while (cd->label != NULL) {\r
2252     if (dcb->Parity == cd->value) {\r
2253       parity = cd->label;\r
2254       break;\r
2255     }\r
2256     cd++;\r
2257   }\r
2258   cd = cdStopBits;\r
2259   while (cd->label != NULL) {\r
2260     if (dcb->StopBits == cd->value) {\r
2261       stopBits = cd->label;\r
2262       break;\r
2263     }\r
2264     cd++;\r
2265   }\r
2266   if (dcb->fOutX) {\r
2267     flow = cdFlow[FLOW_XOFF].label;\r
2268   } else if (dcb->fOutxCtsFlow) {\r
2269     flow = cdFlow[FLOW_CTS].label;\r
2270   } else if (dcb->fOutxDsrFlow) {\r
2271     flow = cdFlow[FLOW_DSR].label;\r
2272   } else {\r
2273     flow = cdFlow[FLOW_NONE].label;\r
2274   }\r
2275   fprintf(f, "/%s=%d,%d,%s,%s,%s\n", name,\r
2276     (int)dcb->BaudRate, dcb->ByteSize, parity, stopBits, flow);\r
2277 }\r
2278 \r
2279 \r
2280 void\r
2281 InitCombo(HANDLE hwndCombo, ComboData *cd)\r
2282 {\r
2283   SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0);\r
2284 \r
2285   while (cd->label != NULL) {\r
2286     SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) cd->label);\r
2287     cd++;\r
2288   }\r
2289 }\r
2290 \r
2291 void\r
2292 SelectComboValue(HANDLE hwndCombo, ComboData *cd, unsigned value)\r
2293 {\r
2294   int i;\r
2295 \r
2296   i = 0;\r
2297   while (cd->label != NULL) {\r
2298     if (cd->value == value) {\r
2299       SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) i, (LPARAM) 0);\r
2300       return;\r
2301     }\r
2302     cd++;\r
2303     i++;\r
2304   }\r
2305 }\r
2306 \r
2307 LRESULT CALLBACK\r
2308 CommPortOptionsDialog(HWND hDlg, UINT message, WPARAM wParam,   LPARAM lParam)\r
2309 {\r
2310   char buf[MSG_SIZ];\r
2311   HANDLE hwndCombo;\r
2312   char *p;\r
2313   LRESULT index;\r
2314   unsigned value;\r
2315   int err;\r
2316 \r
2317   switch (message) {\r
2318   case WM_INITDIALOG: /* message: initialize dialog box */\r
2319     /* Center the dialog over the application window */\r
2320     CenterWindow (hDlg, GetWindow(hDlg, GW_OWNER));\r
2321     Translate(hDlg, DLG_CommPort);\r
2322     /* Initialize the dialog items */\r
2323     /* !! There should probably be some synchronization\r
2324        in accessing hCommPort and dcb.  Or does modal nature\r
2325        of this dialog box do it for us?\r
2326        */\r
2327     hwndCombo = GetDlgItem(hDlg, OPT_Port);\r
2328     InitCombo(hwndCombo, cdPort);\r
2329     p = strrchr(appData.icsCommPort, '\\');\r
2330     if (p++ == NULL) p = appData.icsCommPort;\r
2331     if ((*p == '\0') ||\r
2332         (SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) p) == CB_ERR)) {\r
2333       SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) "None");\r
2334     }\r
2335     EnableWindow(hwndCombo, hCommPort == NULL); /*!! don't allow change for now*/\r
2336 \r
2337     hwndCombo = GetDlgItem(hDlg, OPT_DataRate);\r
2338     InitCombo(hwndCombo, cdDataRate);\r
2339     snprintf(buf, MSG_SIZ, "%u", (int)dcb.BaudRate);\r
2340     if (SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) buf) == CB_ERR) {\r
2341       SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);\r
2342       SendMessage(hwndCombo, WM_SETTEXT, (WPARAM) 0, (LPARAM) buf);\r
2343     }\r
2344 \r
2345     hwndCombo = GetDlgItem(hDlg, OPT_Bits);\r
2346     InitCombo(hwndCombo, cdDataBits);\r
2347     SelectComboValue(hwndCombo, cdDataBits, dcb.ByteSize);\r
2348 \r
2349     hwndCombo = GetDlgItem(hDlg, OPT_Parity);\r
2350     InitCombo(hwndCombo, cdParity);\r
2351     SelectComboValue(hwndCombo, cdParity, dcb.Parity);\r
2352 \r
2353     hwndCombo = GetDlgItem(hDlg, OPT_StopBits);\r
2354     InitCombo(hwndCombo, cdStopBits);\r
2355     SelectComboValue(hwndCombo, cdStopBits, dcb.StopBits);\r
2356 \r
2357     hwndCombo = GetDlgItem(hDlg, OPT_Flow);\r
2358     InitCombo(hwndCombo, cdFlow);\r
2359     if (dcb.fOutX) {\r
2360       SelectComboValue(hwndCombo, cdFlow, FLOW_XOFF);\r
2361     } else if (dcb.fOutxCtsFlow) {\r
2362       SelectComboValue(hwndCombo, cdFlow, FLOW_CTS);\r
2363     } else if (dcb.fOutxDsrFlow) {\r
2364       SelectComboValue(hwndCombo, cdFlow, FLOW_DSR);\r
2365     } else {\r
2366       SelectComboValue(hwndCombo, cdFlow, FLOW_NONE);\r
2367     }\r
2368     return TRUE;\r
2369 \r
2370   case WM_COMMAND: /* message: received a command */\r
2371     switch (LOWORD(wParam)) {\r
2372     case IDOK:\r
2373       /* Read changed options from the dialog box */\r
2374 #ifdef NOTDEF\r
2375       /* !! Currently we can't change comm ports in midstream */\r
2376       hwndCombo = GetDlgItem(hDlg, OPT_Port);\r
2377       index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
2378       if (index == PORT_NONE) {\r
2379         appData.icsCommPort = "";\r
2380         if (hCommPort != NULL) {\r
2381           CloseHandle(hCommPort);\r
2382           hCommPort = NULL;\r
2383         }\r
2384         EndDialog(hDlg, TRUE);\r
2385         return TRUE;\r
2386       }\r
2387       SendMessage(hwndCombo, WM_GETTEXT, (WPARAM) MSG_SIZ, (LPARAM) buf);\r
2388       appData.icsCommPort = strdup(buf);\r
2389       if (hCommPort != NULL) {\r
2390         CloseHandle(hCommPort);\r
2391         hCommPort = NULL;\r
2392       }\r
2393       /* now what?? can't really do this; have to fix up the ChildProc\r
2394          and InputSource records for the comm port that we gave to the\r
2395          back end. */\r
2396 #endif /*NOTDEF*/\r
2397 \r
2398       hwndCombo = GetDlgItem(hDlg, OPT_DataRate);\r
2399       SendMessage(hwndCombo, WM_GETTEXT, (WPARAM) MSG_SIZ, (LPARAM) buf);\r
2400       if (sscanf(buf, "%u", &value) != 1) {\r
2401         MessageBox(hDlg, _("Invalid data rate"),\r
2402                    _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2403         return TRUE;\r
2404       }\r
2405       dcb.BaudRate = value;\r
2406 \r
2407       hwndCombo = GetDlgItem(hDlg, OPT_Bits);\r
2408       index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
2409       dcb.ByteSize = cdDataBits[index].value;\r
2410 \r
2411       hwndCombo = GetDlgItem(hDlg, OPT_Parity);\r
2412       index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
2413       dcb.Parity = cdParity[index].value;\r
2414 \r
2415       hwndCombo = GetDlgItem(hDlg, OPT_StopBits);\r
2416       index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
2417       dcb.StopBits = cdStopBits[index].value;\r
2418 \r
2419       hwndCombo = GetDlgItem(hDlg, OPT_Flow);\r
2420       index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
2421       switch (cdFlow[index].value) {\r
2422       case FLOW_NONE:\r
2423         dcb.fOutX = FALSE;\r
2424         dcb.fOutxCtsFlow = FALSE;\r
2425         dcb.fOutxDsrFlow = FALSE;\r
2426         break;\r
2427       case FLOW_CTS:\r
2428         dcb.fOutX = FALSE;\r
2429         dcb.fOutxCtsFlow = TRUE;\r
2430         dcb.fOutxDsrFlow = FALSE;\r
2431         break;\r
2432       case FLOW_DSR:\r
2433         dcb.fOutX = FALSE;\r
2434         dcb.fOutxCtsFlow = FALSE;\r
2435         dcb.fOutxDsrFlow = TRUE;\r
2436         break;\r
2437       case FLOW_XOFF:\r
2438         dcb.fOutX = TRUE;\r
2439         dcb.fOutxCtsFlow = FALSE;\r
2440         dcb.fOutxDsrFlow = FALSE;\r
2441         break;\r
2442       }\r
2443       if (!SetCommState(hCommPort, (LPDCB) &dcb)) {\r
2444         err = GetLastError();\r
2445         switch(MessageBox(hDlg,\r
2446                          "Failed to set comm port state;\r\ninvalid options?",\r
2447                          _("Option Error"), MB_ABORTRETRYIGNORE|MB_ICONQUESTION)) {\r
2448         case IDABORT:\r
2449           DisplayFatalError(_("Failed to set comm port state"), err, 1);\r
2450           exit(1);  /*is it ok to do this from here?*/\r
2451 \r
2452         case IDRETRY:\r
2453           return TRUE;\r
2454 \r
2455         case IDIGNORE:\r
2456           EndDialog(hDlg, TRUE);\r
2457           return TRUE;\r
2458         }\r
2459       }\r
2460 \r
2461       EndDialog(hDlg, TRUE);\r
2462       return TRUE;\r
2463 \r
2464     case IDCANCEL:\r
2465       EndDialog(hDlg, FALSE);\r
2466       return TRUE;\r
2467 \r
2468     default:\r
2469       break;\r
2470     }\r
2471     break;\r
2472   }\r
2473   return FALSE;\r
2474 }\r
2475 \r
2476 VOID\r
2477 CommPortOptionsPopup(HWND hwnd)\r
2478 {\r
2479   FARPROC lpProc = MakeProcInstance((FARPROC)CommPortOptionsDialog, hInst);\r
2480   DialogBox(hInst, MAKEINTRESOURCE(DLG_CommPort), hwnd, (DLGPROC) lpProc);\r
2481   FreeProcInstance(lpProc);\r
2482 }\r
2483 \r
2484 /*---------------------------------------------------------------------------*\\r
2485  *\r
2486  * Load Options dialog functions\r
2487  *\r
2488 \*---------------------------------------------------------------------------*/\r
2489 \r
2490 int\r
2491 LoadOptionsWhichRadio(HWND hDlg)\r
2492 {\r
2493   return (IsDlgButtonChecked(hDlg, OPT_Exact) ? 1 :\r
2494          (IsDlgButtonChecked(hDlg, OPT_Subset) ? 2 :\r
2495          (IsDlgButtonChecked(hDlg, OPT_Struct) ? 3 :\r
2496          (IsDlgButtonChecked(hDlg, OPT_Material) ? 4 :\r
2497          (IsDlgButtonChecked(hDlg, OPT_Range) ? 5 :\r
2498          (IsDlgButtonChecked(hDlg, OPT_Difference) ? 6 : -1))))));\r
2499 }\r
2500 \r
2501 VOID\r
2502 SetLoadOptionEnables(HWND hDlg)\r
2503 {\r
2504   UINT state;\r
2505 \r
2506   state = IsDlgButtonChecked(hDlg, OPT_Autostep);\r
2507   EnableWindow(GetDlgItem(hDlg, OPT_ASTimeDelay), state);\r
2508   EnableWindow(GetDlgItem(hDlg, OPT_AStext1), state);\r
2509 }\r
2510 \r
2511 LRESULT CALLBACK\r
2512 LoadOptions(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
2513 {\r
2514   char buf[MSG_SIZ];\r
2515   float fnumber;\r
2516   int ok;\r
2517 \r
2518   switch (message) {\r
2519   case WM_INITDIALOG: /* message: initialize dialog box */\r
2520     /* Center the dialog over the application window */\r
2521     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
2522     Translate(hDlg, DLG_LoadOptions);\r
2523     /* Initialize the dialog items */\r
2524     if (appData.timeDelay >= 0.0) {\r
2525       CheckDlgButton(hDlg, OPT_Autostep, TRUE);\r
2526       snprintf(buf, MSG_SIZ, "%.2g", appData.timeDelay);\r
2527       SetDlgItemText(hDlg, OPT_ASTimeDelay, buf);\r
2528     } else {\r
2529       CheckDlgButton(hDlg, OPT_Autostep, FALSE);\r
2530     }\r
2531     SetLoadOptionEnables(hDlg);\r
2532     SetDlgItemInt(hDlg, OPT_elo1, appData.eloThreshold1, FALSE);\r
2533     SetDlgItemInt(hDlg, OPT_elo2, appData.eloThreshold2, FALSE);\r
2534     SetDlgItemInt(hDlg, OPT_date, appData.dateThreshold, FALSE);\r
2535     SetDlgItemInt(hDlg, OPT_Stretch, appData.stretch, FALSE);\r
2536     CheckDlgButton(hDlg, OPT_Reversed, appData.ignoreColors);\r
2537     CheckDlgButton(hDlg, OPT_Mirror, appData.findMirror);\r
2538     SetDlgItemText(hDlg, OPT_Counts,  "");\r
2539     switch (appData.searchMode) {\r
2540     case 1:\r
2541       CheckDlgButton(hDlg, OPT_Exact, TRUE);\r
2542       break;\r
2543     case 2:\r
2544       CheckDlgButton(hDlg, OPT_Subset, TRUE);\r
2545       break;\r
2546     case 3:\r
2547       CheckDlgButton(hDlg, OPT_Struct, TRUE);\r
2548       break;\r
2549     case 4:\r
2550       CheckDlgButton(hDlg, OPT_Material, TRUE);\r
2551       break;\r
2552     case 5:\r
2553       CheckDlgButton(hDlg, OPT_Range, TRUE);\r
2554       break;\r
2555     case 6:\r
2556       CheckDlgButton(hDlg, OPT_Difference, TRUE);\r
2557       break;\r
2558     }\r
2559     return TRUE;\r
2560 \r
2561   case WM_COMMAND: /* message: received a command */\r
2562     switch (LOWORD(wParam)) {\r
2563     case IDOK:\r
2564       /* Read changed options from the dialog box */\r
2565       if (IsDlgButtonChecked(hDlg, OPT_Autostep)) {\r
2566         GetDlgItemText(hDlg, OPT_ASTimeDelay, buf, MSG_SIZ);\r
2567         if (sscanf(buf, "%f", &fnumber) != 1) {\r
2568           MessageBox(hDlg, _("Invalid load game step rate"),\r
2569                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2570           return FALSE;\r
2571         }\r
2572         appData.timeDelay = fnumber;\r
2573       } else {\r
2574         appData.timeDelay = (float) -1.0;\r
2575       }\r
2576       appData.eloThreshold1 = GetDlgItemInt(hDlg, OPT_elo1, &ok, FALSE);\r
2577       appData.eloThreshold2 = GetDlgItemInt(hDlg, OPT_elo2, &ok, FALSE);\r
2578       appData.dateThreshold = GetDlgItemInt(hDlg, OPT_date, &ok, FALSE);\r
2579       appData.stretch = GetDlgItemInt(hDlg, OPT_Stretch, &ok, FALSE);\r
2580       appData.searchMode = LoadOptionsWhichRadio(hDlg);\r
2581       appData.ignoreColors = IsDlgButtonChecked(hDlg, OPT_Reversed);\r
2582       appData.findMirror   = IsDlgButtonChecked(hDlg, OPT_Mirror);\r
2583       GetDlgItemText(hDlg, OPT_Counts, buf, MSG_SIZ);\r
2584       appData.minPieces = appData.maxPieces = 0;\r
2585       sscanf(buf, "%d-%d", &appData.minPieces, &appData.maxPieces);\r
2586       if(appData.maxPieces < appData.minPieces) appData.maxPieces = appData.minPieces;\r
2587       EndDialog(hDlg, TRUE);\r
2588       return TRUE;\r
2589 \r
2590     case IDCANCEL:\r
2591       EndDialog(hDlg, FALSE);\r
2592       return TRUE;\r
2593 \r
2594     default:\r
2595       SetLoadOptionEnables(hDlg);\r
2596       break;\r
2597     }\r
2598     break;\r
2599   }\r
2600   return FALSE;\r
2601 }\r
2602 \r
2603 \r
2604 VOID\r
2605 LoadOptionsPopup(HWND hwnd)\r
2606 {\r
2607   FARPROC lpProc = MakeProcInstance((FARPROC)LoadOptions, hInst);\r
2608   DialogBox(hInst, MAKEINTRESOURCE(DLG_LoadOptions), hwnd, (DLGPROC) lpProc);\r
2609   FreeProcInstance(lpProc);\r
2610 }\r
2611 \r
2612 /*---------------------------------------------------------------------------*\\r
2613  *\r
2614  * Save Options dialog functions\r
2615  *\r
2616 \*---------------------------------------------------------------------------*/\r
2617 \r
2618 VOID\r
2619 SetSaveOptionEnables(HWND hDlg)\r
2620 {\r
2621   UINT state;\r
2622 \r
2623   state = IsDlgButtonChecked(hDlg, OPT_Autosave);\r
2624   EnableWindow(GetDlgItem(hDlg, OPT_AVPrompt), state);\r
2625   EnableWindow(GetDlgItem(hDlg, OPT_AVToFile), state);\r
2626   if (state && !IsDlgButtonChecked(hDlg, OPT_AVPrompt) &&\r
2627       !IsDlgButtonChecked(hDlg, OPT_AVToFile)) {\r
2628     CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVPrompt);\r
2629   }\r
2630 \r
2631   state = state && IsDlgButtonChecked(hDlg, OPT_AVToFile);\r
2632   EnableWindow(GetDlgItem(hDlg, OPT_AVFilename), state);\r
2633   EnableWindow(GetDlgItem(hDlg, OPT_AVBrowse), state);\r
2634 }\r
2635 \r
2636 LRESULT CALLBACK\r
2637 SaveOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
2638 {\r
2639   char buf[MSG_SIZ];\r
2640   FILE *f;\r
2641 \r
2642   switch (message) {\r
2643   case WM_INITDIALOG: /* message: initialize dialog box */\r
2644     /* Center the dialog over the application window */\r
2645     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
2646     Translate(hDlg, DLG_SaveOptions);\r
2647     /* Initialize the dialog items */\r
2648     if (*appData.saveGameFile != NULLCHAR) {\r
2649       CheckDlgButton(hDlg, OPT_Autosave, (UINT) TRUE);\r
2650       CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVToFile);\r
2651       SetDlgItemText(hDlg, OPT_AVFilename, appData.saveGameFile);\r
2652     } else if (appData.autoSaveGames) {\r
2653       CheckDlgButton(hDlg, OPT_Autosave, (UINT) TRUE);\r
2654       CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVPrompt);\r
2655     } else {\r
2656       CheckDlgButton(hDlg, OPT_Autosave, (UINT) FALSE);\r
2657     }\r
2658     if (appData.oldSaveStyle) {\r
2659       CheckRadioButton(hDlg, OPT_PGN, OPT_Old, OPT_Old);\r
2660     } else {\r
2661       CheckRadioButton(hDlg, OPT_PGN, OPT_Old, OPT_PGN);\r
2662     }\r
2663     CheckDlgButton( hDlg, OPT_OutOfBookInfo, appData.saveOutOfBookInfo );\r
2664     SetSaveOptionEnables(hDlg);\r
2665     return TRUE;\r
2666 \r
2667   case WM_COMMAND: /* message: received a command */\r
2668     switch (LOWORD(wParam)) {\r
2669     case IDOK:\r
2670       /* Read changed options from the dialog box */\r
2671       if (IsDlgButtonChecked(hDlg, OPT_Autosave)) {\r
2672         appData.autoSaveGames = TRUE;\r
2673         if (IsDlgButtonChecked(hDlg, OPT_AVPrompt)) {\r
2674           ASSIGN(appData.saveGameFile, ""); // [HGM] make sure value is ALWAYS in allocated memory\r
2675         } else /*if (IsDlgButtonChecked(hDlg, OPT_AVToFile))*/ {\r
2676           GetDlgItemText(hDlg, OPT_AVFilename, buf, MSG_SIZ);\r
2677           if (*buf == NULLCHAR) {\r
2678             MessageBox(hDlg, _("Invalid save game file name"),\r
2679                        _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2680             return FALSE;\r
2681           }\r
2682           FREE(appData.saveGameFile);\r
2683           appData.saveGameFile = InterpretFileName(buf, homeDir);\r
2684         }\r
2685       } else {\r
2686         appData.autoSaveGames = FALSE;\r
2687         ASSIGN(appData.saveGameFile, "");\r
2688       }\r
2689       appData.oldSaveStyle = IsDlgButtonChecked(hDlg, OPT_Old);\r
2690       appData.saveOutOfBookInfo = IsDlgButtonChecked( hDlg, OPT_OutOfBookInfo );\r
2691       EndDialog(hDlg, TRUE);\r
2692       return TRUE;\r
2693 \r
2694     case IDCANCEL:\r
2695       EndDialog(hDlg, FALSE);\r
2696       return TRUE;\r
2697 \r
2698     case OPT_AVBrowse:\r
2699       f = OpenFileDialog(hDlg, "a", NULL,\r
2700                          appData.oldSaveStyle ? "gam" : "pgn",\r
2701                          GAME_FILT, _("Browse for Auto Save File"),\r
2702                          NULL, NULL, buf);\r
2703       if (f != NULL) {\r
2704         fclose(f);\r
2705         SetDlgItemText(hDlg, OPT_AVFilename, buf);\r
2706       }\r
2707       break;\r
2708 \r
2709     default:\r
2710       SetSaveOptionEnables(hDlg);\r
2711       break;\r
2712     }\r
2713     break;\r
2714   }\r
2715   return FALSE;\r
2716 }\r
2717 \r
2718 VOID\r
2719 SaveOptionsPopup(HWND hwnd)\r
2720 {\r
2721   FARPROC lpProc = MakeProcInstance((FARPROC)SaveOptionsDialog, hInst);\r
2722   DialogBox(hInst, MAKEINTRESOURCE(DLG_SaveOptions), hwnd, (DLGPROC) lpProc);\r
2723   FreeProcInstance(lpProc);\r
2724 }\r
2725 \r
2726 /*---------------------------------------------------------------------------*\\r
2727  *\r
2728  * Time Control Options dialog functions\r
2729  *\r
2730 \*---------------------------------------------------------------------------*/\r
2731 \r
2732 VOID\r
2733 SetTimeControlEnables(HWND hDlg)\r
2734 {\r
2735   UINT state;\r
2736 \r
2737   state = IsDlgButtonChecked(hDlg, OPT_TCUseMoves)\r
2738         + 2*IsDlgButtonChecked(hDlg, OPT_TCUseFixed);\r
2739   EnableWindow(GetDlgItem(hDlg, OPT_TCTime), state == 1);\r
2740   EnableWindow(GetDlgItem(hDlg, OPT_TCMoves), state == 1);\r
2741   EnableWindow(GetDlgItem(hDlg, OPT_TCtext1), state == 1);\r
2742   EnableWindow(GetDlgItem(hDlg, OPT_TCtext2), state == 1);\r
2743   EnableWindow(GetDlgItem(hDlg, OPT_TCTime2), !state);\r
2744   EnableWindow(GetDlgItem(hDlg, OPT_TCInc), !state);\r
2745   EnableWindow(GetDlgItem(hDlg, OPT_TCitext1), !state);\r
2746   EnableWindow(GetDlgItem(hDlg, OPT_TCitext2), !state);\r
2747   EnableWindow(GetDlgItem(hDlg, OPT_TCitext3), !state);\r
2748   EnableWindow(GetDlgItem(hDlg, OPT_TCFixed), state == 2);\r
2749   EnableWindow(GetDlgItem(hDlg, OPT_TCftext), state == 2);\r
2750 }\r
2751 \r
2752 \r
2753 LRESULT CALLBACK\r
2754 TimeControl(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
2755 {\r
2756   char buf[MSG_SIZ], *tc;\r
2757   int mps, odds1, odds2, st;\r
2758   float increment;\r
2759   BOOL ok, ok2;\r
2760 \r
2761   switch (message) {\r
2762   case WM_INITDIALOG: /* message: initialize dialog box */\r
2763     /* Center the dialog over the application window */\r
2764     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
2765     Translate(hDlg, DLG_TimeControl);\r
2766     /* Initialize the dialog items */\r
2767     if (/*appData.clockMode &&*/ !appData.icsActive) { // [HGM] even if !clockMode, we could want to set it in tournament dialog\r
2768       if (searchTime) {\r
2769         CheckRadioButton(hDlg, OPT_TCUseMoves, OPT_TCUseFixed,\r
2770                          OPT_TCUseFixed);\r
2771         SetDlgItemInt(hDlg, OPT_TCFixed, searchTime, FALSE);\r
2772       } else\r
2773       if (appData.timeIncrement == -1) {\r
2774         CheckRadioButton(hDlg, OPT_TCUseMoves, OPT_TCUseFixed,\r
2775                          OPT_TCUseMoves);\r
2776         SetDlgItemText(hDlg, OPT_TCTime, appData.timeControl);\r
2777         SetDlgItemInt(hDlg, OPT_TCMoves, appData.movesPerSession,\r
2778                       FALSE);\r
2779         SetDlgItemText(hDlg, OPT_TCTime2, "");\r
2780         SetDlgItemText(hDlg, OPT_TCInc, "");\r
2781       } else {\r
2782         int i = appData.timeIncrement;\r
2783         if(i == appData.timeIncrement) snprintf(buf, MSG_SIZ, "%d", i);\r
2784         else snprintf(buf, MSG_SIZ, "%4.2f", appData.timeIncrement);\r
2785         CheckRadioButton(hDlg, OPT_TCUseMoves, OPT_TCUseFixed,\r
2786                          OPT_TCUseInc);\r
2787         SetDlgItemText(hDlg, OPT_TCTime, "");\r
2788         SetDlgItemText(hDlg, OPT_TCMoves, "");\r
2789         SetDlgItemText(hDlg, OPT_TCTime2, appData.timeControl);\r
2790         SetDlgItemText(hDlg, OPT_TCInc, buf);\r
2791       }\r
2792       SetDlgItemInt(hDlg, OPT_TCOdds1, 1, FALSE);\r
2793       SetDlgItemInt(hDlg, OPT_TCOdds2, 1, FALSE);\r
2794       SetTimeControlEnables(hDlg);\r
2795     }\r
2796     return TRUE;\r
2797 \r
2798   case WM_COMMAND: /* message: received a command */\r
2799     switch (LOWORD(wParam)) {\r
2800     case IDOK:\r
2801       mps = appData.movesPerSession;\r
2802       increment = appData.timeIncrement;\r
2803       tc = appData.timeControl;\r
2804       st = 0;\r
2805       /* Read changed options from the dialog box */\r
2806       if (IsDlgButtonChecked(hDlg, OPT_TCUseFixed)) {\r
2807         st = GetDlgItemInt(hDlg, OPT_TCFixed, &ok, FALSE);\r
2808         if (!ok || st <= 0) {\r
2809           MessageBox(hDlg, _("Invalid max time per move"),\r
2810                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2811           return FALSE;\r
2812         }\r
2813       } else\r
2814       if (IsDlgButtonChecked(hDlg, OPT_TCUseMoves)) {\r
2815         increment = -1;\r
2816         mps = GetDlgItemInt(hDlg, OPT_TCMoves, &ok, FALSE);\r
2817         if (!ok || mps <= 0) {\r
2818           MessageBox(hDlg, _("Invalid moves per time control"),\r
2819                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2820           return FALSE;\r
2821         }\r
2822         GetDlgItemText(hDlg, OPT_TCTime, buf, MSG_SIZ);\r
2823         if (!ParseTimeControl(buf, increment, mps)) {\r
2824           MessageBox(hDlg, _("Invalid minutes per time control"),\r
2825                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2826           return FALSE;\r
2827         }\r
2828       tc = buf;\r
2829       } else {\r
2830         GetDlgItemText(hDlg, OPT_TCInc, buf, MSG_SIZ);\r
2831         ok = (sscanf(buf, "%f%c", &increment, buf) == 1);\r
2832         if (!ok || increment < 0) {\r
2833           MessageBox(hDlg, _("Invalid increment"),\r
2834                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2835           return FALSE;\r
2836         }\r
2837         GetDlgItemText(hDlg, OPT_TCTime2, buf, MSG_SIZ);\r
2838         if (!ParseTimeControl(buf, increment, mps)) {\r
2839           MessageBox(hDlg, _("Invalid initial time"),\r
2840                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2841           return FALSE;\r
2842         }\r
2843       tc = buf;\r
2844       }\r
2845       odds1 = GetDlgItemInt(hDlg, OPT_TCOdds1, &ok, FALSE);\r
2846       odds2 = GetDlgItemInt(hDlg, OPT_TCOdds2, &ok2, FALSE);\r
2847       if (!ok || !ok2 || odds1 <= 0 || odds2 <= 0) {\r
2848           MessageBox(hDlg, _("Invalid time-odds factor"),\r
2849                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2850           return FALSE;\r
2851       }\r
2852       searchTime = st;\r
2853       appData.timeControl = strdup(tc);\r
2854       appData.movesPerSession = mps;\r
2855       appData.timeIncrement = increment;\r
2856       appData.firstTimeOdds  = first.timeOdds  = odds1;\r
2857       appData.secondTimeOdds = second.timeOdds = odds2;\r
2858       Reset(TRUE, TRUE);\r
2859       EndDialog(hDlg, TRUE);\r
2860       return TRUE;\r
2861 \r
2862     case IDCANCEL:\r
2863       EndDialog(hDlg, FALSE);\r
2864       return TRUE;\r
2865 \r
2866     default:\r
2867       SetTimeControlEnables(hDlg);\r
2868       break;\r
2869     }\r
2870     break;\r
2871   }\r
2872   return FALSE;\r
2873 }\r
2874 \r
2875 VOID\r
2876 TimeControlOptionsPopup(HWND hwnd)\r
2877 {\r
2878   if (gameMode != BeginningOfGame) {\r
2879     DisplayError(_("Changing time control during a game is not implemented"), 0);\r
2880   } else {\r
2881     FARPROC lpProc = MakeProcInstance((FARPROC)TimeControl, hInst);\r
2882     DialogBox(hInst, MAKEINTRESOURCE(DLG_TimeControl), hwnd, (DLGPROC) lpProc);\r
2883     FreeProcInstance(lpProc);\r
2884   }\r
2885 }\r
2886 \r
2887 /*---------------------------------------------------------------------------*\\r
2888  *\r
2889  * Engine Options Dialog functions\r
2890  *\r
2891 \*---------------------------------------------------------------------------*/\r
2892 #define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y))\r
2893 #define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x))\r
2894 \r
2895 #define INT_ABS( n )    ((n) >= 0 ? (n) : -(n))\r
2896 \r
2897 LRESULT CALLBACK EnginePlayOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
2898 {\r
2899   switch (message) {\r
2900   case WM_INITDIALOG: /* message: initialize dialog box */\r
2901 \r
2902     /* Center the dialog over the application window */\r
2903     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
2904     Translate(hDlg, DLG_EnginePlayOptions);\r
2905 \r
2906     /* Initialize the dialog items */\r
2907     CHECK_BOX(IDC_EpPeriodicUpdates, appData.periodicUpdates);\r
2908     CHECK_BOX(IDC_EpPonder, appData.ponderNextMove);\r
2909     CHECK_BOX(IDC_EpShowThinking, appData.showThinking);\r
2910     CHECK_BOX(IDC_EpHideThinkingHuman, appData.hideThinkingFromHuman);\r
2911 \r
2912     CHECK_BOX(IDC_TestClaims, appData.testClaims);\r
2913     CHECK_BOX(IDC_DetectMates, appData.checkMates);\r
2914     CHECK_BOX(IDC_MaterialDraws, appData.materialDraws);\r
2915     CHECK_BOX(IDC_TrivialDraws, appData.trivialDraws);\r
2916 \r
2917     CHECK_BOX(IDC_ScoreAbs1, appData.firstScoreIsAbsolute);\r
2918     CHECK_BOX(IDC_ScoreAbs2, appData.secondScoreIsAbsolute);\r
2919 \r
2920     SetDlgItemInt( hDlg, IDC_EpDrawMoveCount, appData.adjudicateDrawMoves, TRUE );\r
2921     SendDlgItemMessage( hDlg, IDC_EpDrawMoveCount, EM_SETSEL, 0, -1 );\r
2922 \r
2923     SetDlgItemInt( hDlg, IDC_EpAdjudicationThreshold, INT_ABS(appData.adjudicateLossThreshold), TRUE );\r
2924     SendDlgItemMessage( hDlg, IDC_EpAdjudicationThreshold, EM_SETSEL, 0, -1 );\r
2925 \r
2926     SetDlgItemInt( hDlg, IDC_RuleMoves, appData.ruleMoves, TRUE );\r
2927     SendDlgItemMessage( hDlg, IDC_RuleMoves, EM_SETSEL, 0, -1 );\r
2928 \r
2929     SetDlgItemInt( hDlg, IDC_DrawRepeats, INT_ABS(appData.drawRepeats), TRUE );\r
2930     SendDlgItemMessage( hDlg, IDC_DrawRepeats, EM_SETSEL, 0, -1 );\r
2931 \r
2932     return TRUE;\r
2933 \r
2934   case WM_COMMAND: /* message: received a command */\r
2935     switch (LOWORD(wParam)) {\r
2936     case IDOK:\r
2937       /* Read changed options from the dialog box */\r
2938       PeriodicUpdatesEvent(          IS_CHECKED(IDC_EpPeriodicUpdates));\r
2939       PonderNextMoveEvent(           IS_CHECKED(IDC_EpPonder));\r
2940       appData.hideThinkingFromHuman= IS_CHECKED(IDC_EpHideThinkingHuman); // [HGM] thinking: moved up\r
2941       appData.showThinking   = IS_CHECKED(IDC_EpShowThinking);\r
2942       ShowThinkingEvent(); // [HGM] thinking: tests all options that need thinking output\r
2943       appData.testClaims    = IS_CHECKED(IDC_TestClaims);\r
2944       appData.checkMates    = IS_CHECKED(IDC_DetectMates);\r
2945       appData.materialDraws = IS_CHECKED(IDC_MaterialDraws);\r
2946       appData.trivialDraws  = IS_CHECKED(IDC_TrivialDraws);\r
2947 \r
2948       appData.adjudicateDrawMoves = GetDlgItemInt(hDlg, IDC_EpDrawMoveCount, NULL, FALSE );\r
2949       appData.adjudicateLossThreshold = - (int) GetDlgItemInt(hDlg, IDC_EpAdjudicationThreshold, NULL, FALSE );\r
2950       appData.ruleMoves = GetDlgItemInt(hDlg, IDC_RuleMoves, NULL, FALSE );\r
2951       appData.drawRepeats = (int) GetDlgItemInt(hDlg, IDC_DrawRepeats, NULL, FALSE );\r
2952 \r
2953       first.scoreIsAbsolute  = appData.firstScoreIsAbsolute  = IS_CHECKED(IDC_ScoreAbs1);\r
2954       second.scoreIsAbsolute = appData.secondScoreIsAbsolute = IS_CHECKED(IDC_ScoreAbs2);\r
2955 \r
2956       EndDialog(hDlg, TRUE);\r
2957       return TRUE;\r
2958 \r
2959     case IDCANCEL:\r
2960       EndDialog(hDlg, FALSE);\r
2961       return TRUE;\r
2962 \r
2963     case IDC_EpDrawMoveCount:\r
2964     case IDC_EpAdjudicationThreshold:\r
2965     case IDC_DrawRepeats:\r
2966     case IDC_RuleMoves:\r
2967         if( HIWORD(wParam) == EN_CHANGE ) {\r
2968             int n1_ok;\r
2969             int n2_ok;\r
2970             int n3_ok;\r
2971             int n4_ok;\r
2972 \r
2973             GetDlgItemInt(hDlg, IDC_EpDrawMoveCount, &n1_ok, FALSE );\r
2974             GetDlgItemInt(hDlg, IDC_EpAdjudicationThreshold, &n2_ok, FALSE );\r
2975             GetDlgItemInt(hDlg, IDC_RuleMoves, &n3_ok, FALSE );\r
2976             GetDlgItemInt(hDlg, IDC_DrawRepeats, &n4_ok, FALSE );\r
2977 \r
2978             EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok && n3_ok && n4_ok ? TRUE : FALSE );\r
2979         }\r
2980         return TRUE;\r
2981     }\r
2982     break;\r
2983   }\r
2984   return FALSE;\r
2985 }\r
2986 \r
2987 VOID EnginePlayOptionsPopup(HWND hwnd)\r
2988 {\r
2989   FARPROC lpProc;\r
2990 \r
2991   lpProc = MakeProcInstance((FARPROC)EnginePlayOptionsDialog, hInst);\r
2992   DialogBox(hInst, MAKEINTRESOURCE(DLG_EnginePlayOptions), hwnd, (DLGPROC) lpProc);\r
2993   FreeProcInstance(lpProc);\r
2994 }\r
2995 \r
2996 /*---------------------------------------------------------------------------*\\r
2997  *\r
2998  * UCI Options Dialog functions\r
2999  *\r
3000 \*---------------------------------------------------------------------------*/\r
3001 INT CALLBACK BrowseCallbackProc(HWND hwnd, \r
3002                                 UINT uMsg,\r
3003                                 LPARAM lp, \r
3004                                 LPARAM pData) \r
3005 {\r
3006     switch(uMsg) \r
3007     {\r
3008       case BFFM_INITIALIZED: \r
3009         SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)pData);\r
3010         break;\r
3011     }\r
3012     return 0;\r
3013 }\r
3014 \r
3015 BOOL BrowseForFolder( const char * title, char * path )\r
3016 {\r
3017     BOOL result = FALSE;\r
3018     BROWSEINFO bi;\r
3019     LPITEMIDLIST pidl;\r
3020 \r
3021     ZeroMemory( &bi, sizeof(bi) );\r
3022 \r
3023     bi.lpszTitle = title == 0 ? _("Choose Folder") : title;\r
3024     bi.ulFlags = BIF_RETURNONLYFSDIRS;\r
3025     bi.lpfn = BrowseCallbackProc;\r
3026     bi.lParam = (LPARAM) path;\r
3027 \r
3028     pidl = SHBrowseForFolder( &bi );\r
3029 \r
3030     if( pidl != 0 ) {\r
3031         IMalloc * imalloc = 0;\r
3032 \r
3033         if( SHGetPathFromIDList( pidl, path ) ) {\r
3034             result = TRUE;\r
3035         }\r
3036 \r
3037         if( SUCCEEDED( SHGetMalloc ( &imalloc ) ) ) {\r
3038             imalloc->lpVtbl->Free(imalloc,pidl);\r
3039             imalloc->lpVtbl->Release(imalloc);\r
3040         }\r
3041     }\r
3042 \r
3043     return result;\r
3044 }\r
3045 \r
3046 int\r
3047 IsMultiFormat(char *s)\r
3048 {\r
3049   char *p = strchr(s, ':');\r
3050   return p && p != s+1;\r
3051 }\r
3052 \r
3053 LRESULT CALLBACK UciOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
3054 {\r
3055   char buf[MAX_PATH];\r
3056   int oldCores;\r
3057 \r
3058   switch (message) {\r
3059   case WM_INITDIALOG: /* message: initialize dialog box */\r
3060 \r
3061     /* Center the dialog over the application window */\r
3062     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
3063     Translate(hDlg, DLG_OptionsUCI);\r
3064 \r
3065     /* Initialize the dialog items */\r
3066     SetDlgItemText( hDlg, IDC_PolyglotDir, appData.polyglotDir );\r
3067     SetDlgItemInt( hDlg, IDC_HashSize, appData.defaultHashSize, TRUE );\r
3068     if(appData.defaultPathEGTB[0])\r
3069     SetDlgItemText( hDlg, IDC_PathToEGTB, appData.defaultPathEGTB );\r
3070     else\r
3071     SetDlgItemText( hDlg, IDC_PathToEGTB, appData.egtFormats );\r
3072     SetDlgItemInt( hDlg, IDC_SizeOfEGTB, appData.defaultCacheSizeEGTB, TRUE );\r
3073     CheckDlgButton( hDlg, IDC_UseBook, (BOOL) appData.usePolyglotBook );\r
3074     SetDlgItemText( hDlg, IDC_BookFile, appData.polyglotBook );\r
3075     // [HGM] smp: input field for nr of cores:\r
3076     SetDlgItemInt( hDlg, IDC_Cores, appData.smpCores, TRUE );\r
3077     // [HGM] book: tick boxes for own book use\r
3078     CheckDlgButton( hDlg, IDC_OwnBook1, (BOOL) appData.firstHasOwnBookUCI );\r
3079     CheckDlgButton( hDlg, IDC_OwnBook2, (BOOL) appData.secondHasOwnBookUCI );\r
3080     SetDlgItemInt( hDlg, IDC_BookDep, appData.bookDepth, TRUE );\r
3081     SetDlgItemInt( hDlg, IDC_BookStr, appData.bookStrength, TRUE );\r
3082     SetDlgItemInt( hDlg, IDC_Games, appData.defaultMatchGames, TRUE );\r
3083 \r
3084     SendDlgItemMessage( hDlg, IDC_PolyglotDir, EM_SETSEL, 0, -1 );\r
3085     // [HGM] Yet another ponder duplicate\r
3086     CheckDlgButton( hDlg, OPT_PonderNextMove, (BOOL) appData.ponderNextMove );\r
3087 \r
3088     return TRUE;\r
3089 \r
3090   case WM_COMMAND: /* message: received a command */\r
3091     switch (LOWORD(wParam)) {\r
3092     case IDOK:\r
3093       GetDlgItemText( hDlg, IDC_PolyglotDir, buf, sizeof(buf) );\r
3094       appData.polyglotDir = strdup(buf);\r
3095       appData.defaultHashSize = GetDlgItemInt(hDlg, IDC_HashSize, NULL, FALSE );\r
3096       appData.defaultCacheSizeEGTB = GetDlgItemInt(hDlg, IDC_SizeOfEGTB, NULL, FALSE );\r
3097       GetDlgItemText( hDlg, IDC_PathToEGTB, buf, sizeof(buf) );\r
3098       if(IsMultiFormat(buf)) {\r
3099         ASSIGN(appData.egtFormats, buf);\r
3100       } else {\r
3101         ASSIGN(appData.defaultPathEGTB, buf);\r
3102       }\r
3103       GetDlgItemText( hDlg, IDC_BookFile, buf, sizeof(buf) );\r
3104       appData.polyglotBook = strdup(buf);\r
3105       appData.usePolyglotBook = (Boolean) IsDlgButtonChecked( hDlg, IDC_UseBook );\r
3106       // [HGM] smp: get nr of cores and ponder:\r
3107       oldCores = appData.smpCores;\r
3108       appData.smpCores = GetDlgItemInt(hDlg, IDC_Cores, NULL, FALSE );\r
3109       if(appData.smpCores != oldCores) NewSettingEvent(FALSE, &(first.maxCores), "cores", appData.smpCores);\r
3110       PonderNextMoveEvent((Boolean) IsDlgButtonChecked( hDlg, OPT_PonderNextMove ));\r
3111       // [HGM] book: read tick boxes for own book use\r
3112       appData.firstHasOwnBookUCI  = (Boolean) IsDlgButtonChecked( hDlg, IDC_OwnBook1 );\r
3113       appData.secondHasOwnBookUCI = (Boolean) IsDlgButtonChecked( hDlg, IDC_OwnBook2 );\r
3114       appData.bookDepth = GetDlgItemInt(hDlg, IDC_BookDep, NULL, FALSE );\r
3115       appData.bookStrength = GetDlgItemInt(hDlg, IDC_BookStr, NULL, FALSE );\r
3116       appData.defaultMatchGames = GetDlgItemInt(hDlg, IDC_Games, NULL, FALSE );\r
3117 \r
3118       if(gameMode == BeginningOfGame) Reset(TRUE, TRUE);\r
3119       EndDialog(hDlg, TRUE);\r
3120       return TRUE;\r
3121 \r
3122     case IDCANCEL:\r
3123       EndDialog(hDlg, FALSE);\r
3124       return TRUE;\r
3125 \r
3126     case IDC_BrowseForBook:\r
3127       {\r
3128           char filter[] = {\r
3129               'A','l','l',' ','F','i','l','e','s', 0,\r
3130               '*','.','*', 0,\r
3131               'B','I','N',' ','F','i','l','e','s', 0,\r
3132               '*','.','b','i','n', 0,\r
3133               0 };\r
3134 \r
3135           OPENFILENAME ofn;\r
3136 \r
3137           safeStrCpy( buf, "" , sizeof( buf)/sizeof( buf[0]) );\r
3138 \r
3139           ZeroMemory( &ofn, sizeof(ofn) );\r
3140 \r
3141           ofn.lStructSize = sizeof(ofn);\r
3142           ofn.hwndOwner = hDlg;\r
3143           ofn.hInstance = hInst;\r
3144           ofn.lpstrFilter = filter;\r
3145 \r
3146           ofn.lpstrFile = buf;\r
3147           ofn.nMaxFile = sizeof(buf);\r
3148           ofn.lpstrTitle = _("Choose Book");\r
3149           ofn.Flags = OFN_FILEMUSTEXIST | OFN_LONGNAMES | OFN_HIDEREADONLY;\r
3150 \r
3151           if( GetOpenFileName( &ofn ) ) {\r
3152               SetDlgItemText( hDlg, IDC_BookFile, buf );\r
3153           }\r
3154       }\r
3155       return TRUE;\r
3156 \r
3157     case IDC_BrowseForPolyglotDir:\r
3158       if( BrowseForFolder( _("Choose Polyglot Directory"), buf ) ) {\r
3159         SetDlgItemText( hDlg, IDC_PolyglotDir, buf );\r
3160 \r
3161         strcat( buf, "\\polyglot.exe" );\r
3162 \r
3163         if( GetFileAttributes(buf) == 0xFFFFFFFF ) {\r
3164             MessageBox( hDlg, _("Polyglot was not found in the specified folder!"), "Warning", MB_OK | MB_ICONWARNING );\r
3165         }\r
3166       }\r
3167       return TRUE;\r
3168 \r
3169     case IDC_BrowseForEGTB:\r
3170       if( BrowseForFolder( _("Choose EGTB Directory:"), buf ) ) {\r
3171         SetDlgItemText( hDlg, IDC_PathToEGTB, buf );\r
3172       }\r
3173       return TRUE;\r
3174 \r
3175     case IDC_HashSize:\r
3176     case IDC_SizeOfEGTB:\r
3177         if( HIWORD(wParam) == EN_CHANGE ) {\r
3178             int n1_ok;\r
3179             int n2_ok;\r
3180 \r
3181             GetDlgItemInt(hDlg, IDC_HashSize, &n1_ok, FALSE );\r
3182             GetDlgItemInt(hDlg, IDC_SizeOfEGTB, &n2_ok, FALSE );\r
3183 \r
3184             EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok ? TRUE : FALSE );\r
3185         }\r
3186         return TRUE;\r
3187     }\r
3188     break;\r
3189   }\r
3190   return FALSE;\r
3191 }\r
3192 \r
3193 VOID UciOptionsPopup(HWND hwnd)\r
3194 {\r
3195   FARPROC lpProc;\r
3196 \r
3197   lpProc = MakeProcInstance((FARPROC)UciOptionsDialog, hInst);\r
3198   DialogBox(hInst, MAKEINTRESOURCE(DLG_OptionsUCI), hwnd, (DLGPROC) lpProc);\r
3199   FreeProcInstance(lpProc);\r
3200 }\r