977c0c685b25592e55aaaa09651ff8f889683e57
[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_VariantXiangqi,\r
854     OPT_VariantCourier,\r
855     OPT_VariantGothic,\r
856     OPT_VariantCapablanca,\r
857     OPT_VariantKnightmate,\r
858     OPT_VariantFairy,        \r
859     OPT_VariantCylinder,\r
860     OPT_VariantFalcon,\r
861     OPT_VariantCRC,\r
862     OPT_VariantBerolina,\r
863     OPT_VariantJanus,\r
864     OPT_VariantSuper,\r
865     OPT_VariantGreat,\r
866     -1, // Twilight,\r
867     OPT_VariantMakruk,\r
868     OPT_VariantASEAN,\r
869     OPT_VariantSChess,\r
870     OPT_VariantGrand,\r
871     OPT_VariantSpartan, // Spartan\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     switch (appData.searchMode) {\r
2539     case 1:\r
2540       CheckDlgButton(hDlg, OPT_Exact, TRUE);\r
2541       break;\r
2542     case 2:\r
2543       CheckDlgButton(hDlg, OPT_Subset, TRUE);\r
2544       break;\r
2545     case 3:\r
2546       CheckDlgButton(hDlg, OPT_Struct, TRUE);\r
2547       break;\r
2548     case 4:\r
2549       CheckDlgButton(hDlg, OPT_Material, TRUE);\r
2550       break;\r
2551     case 5:\r
2552       CheckDlgButton(hDlg, OPT_Range, TRUE);\r
2553       break;\r
2554     case 6:\r
2555       CheckDlgButton(hDlg, OPT_Difference, TRUE);\r
2556       break;\r
2557     }\r
2558     return TRUE;\r
2559 \r
2560   case WM_COMMAND: /* message: received a command */\r
2561     switch (LOWORD(wParam)) {\r
2562     case IDOK:\r
2563       /* Read changed options from the dialog box */\r
2564       if (IsDlgButtonChecked(hDlg, OPT_Autostep)) {\r
2565         GetDlgItemText(hDlg, OPT_ASTimeDelay, buf, MSG_SIZ);\r
2566         if (sscanf(buf, "%f", &fnumber) != 1) {\r
2567           MessageBox(hDlg, _("Invalid load game step rate"),\r
2568                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2569           return FALSE;\r
2570         }\r
2571         appData.timeDelay = fnumber;\r
2572       } else {\r
2573         appData.timeDelay = (float) -1.0;\r
2574       }\r
2575       appData.eloThreshold1 = GetDlgItemInt(hDlg, OPT_elo1, &ok, FALSE);\r
2576       appData.eloThreshold2 = GetDlgItemInt(hDlg, OPT_elo2, &ok, FALSE);\r
2577       appData.dateThreshold = GetDlgItemInt(hDlg, OPT_date, &ok, FALSE);\r
2578       appData.stretch = GetDlgItemInt(hDlg, OPT_Stretch, &ok, FALSE);\r
2579       appData.searchMode = LoadOptionsWhichRadio(hDlg);\r
2580       appData.ignoreColors = IsDlgButtonChecked(hDlg, OPT_Reversed);\r
2581       appData.findMirror   = IsDlgButtonChecked(hDlg, OPT_Mirror);\r
2582       EndDialog(hDlg, TRUE);\r
2583       return TRUE;\r
2584 \r
2585     case IDCANCEL:\r
2586       EndDialog(hDlg, FALSE);\r
2587       return TRUE;\r
2588 \r
2589     default:\r
2590       SetLoadOptionEnables(hDlg);\r
2591       break;\r
2592     }\r
2593     break;\r
2594   }\r
2595   return FALSE;\r
2596 }\r
2597 \r
2598 \r
2599 VOID\r
2600 LoadOptionsPopup(HWND hwnd)\r
2601 {\r
2602   FARPROC lpProc = MakeProcInstance((FARPROC)LoadOptions, hInst);\r
2603   DialogBox(hInst, MAKEINTRESOURCE(DLG_LoadOptions), hwnd, (DLGPROC) lpProc);\r
2604   FreeProcInstance(lpProc);\r
2605 }\r
2606 \r
2607 /*---------------------------------------------------------------------------*\\r
2608  *\r
2609  * Save Options dialog functions\r
2610  *\r
2611 \*---------------------------------------------------------------------------*/\r
2612 \r
2613 VOID\r
2614 SetSaveOptionEnables(HWND hDlg)\r
2615 {\r
2616   UINT state;\r
2617 \r
2618   state = IsDlgButtonChecked(hDlg, OPT_Autosave);\r
2619   EnableWindow(GetDlgItem(hDlg, OPT_AVPrompt), state);\r
2620   EnableWindow(GetDlgItem(hDlg, OPT_AVToFile), state);\r
2621   if (state && !IsDlgButtonChecked(hDlg, OPT_AVPrompt) &&\r
2622       !IsDlgButtonChecked(hDlg, OPT_AVToFile)) {\r
2623     CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVPrompt);\r
2624   }\r
2625 \r
2626   state = state && IsDlgButtonChecked(hDlg, OPT_AVToFile);\r
2627   EnableWindow(GetDlgItem(hDlg, OPT_AVFilename), state);\r
2628   EnableWindow(GetDlgItem(hDlg, OPT_AVBrowse), state);\r
2629 }\r
2630 \r
2631 LRESULT CALLBACK\r
2632 SaveOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
2633 {\r
2634   char buf[MSG_SIZ];\r
2635   FILE *f;\r
2636 \r
2637   switch (message) {\r
2638   case WM_INITDIALOG: /* message: initialize dialog box */\r
2639     /* Center the dialog over the application window */\r
2640     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
2641     Translate(hDlg, DLG_SaveOptions);\r
2642     /* Initialize the dialog items */\r
2643     if (*appData.saveGameFile != NULLCHAR) {\r
2644       CheckDlgButton(hDlg, OPT_Autosave, (UINT) TRUE);\r
2645       CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVToFile);\r
2646       SetDlgItemText(hDlg, OPT_AVFilename, appData.saveGameFile);\r
2647     } else if (appData.autoSaveGames) {\r
2648       CheckDlgButton(hDlg, OPT_Autosave, (UINT) TRUE);\r
2649       CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVPrompt);\r
2650     } else {\r
2651       CheckDlgButton(hDlg, OPT_Autosave, (UINT) FALSE);\r
2652     }\r
2653     if (appData.oldSaveStyle) {\r
2654       CheckRadioButton(hDlg, OPT_PGN, OPT_Old, OPT_Old);\r
2655     } else {\r
2656       CheckRadioButton(hDlg, OPT_PGN, OPT_Old, OPT_PGN);\r
2657     }\r
2658     CheckDlgButton( hDlg, OPT_OutOfBookInfo, appData.saveOutOfBookInfo );\r
2659     SetSaveOptionEnables(hDlg);\r
2660     return TRUE;\r
2661 \r
2662   case WM_COMMAND: /* message: received a command */\r
2663     switch (LOWORD(wParam)) {\r
2664     case IDOK:\r
2665       /* Read changed options from the dialog box */\r
2666       if (IsDlgButtonChecked(hDlg, OPT_Autosave)) {\r
2667         appData.autoSaveGames = TRUE;\r
2668         if (IsDlgButtonChecked(hDlg, OPT_AVPrompt)) {\r
2669           ASSIGN(appData.saveGameFile, ""); // [HGM] make sure value is ALWAYS in allocated memory\r
2670         } else /*if (IsDlgButtonChecked(hDlg, OPT_AVToFile))*/ {\r
2671           GetDlgItemText(hDlg, OPT_AVFilename, buf, MSG_SIZ);\r
2672           if (*buf == NULLCHAR) {\r
2673             MessageBox(hDlg, _("Invalid save game file name"),\r
2674                        _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2675             return FALSE;\r
2676           }\r
2677           FREE(appData.saveGameFile);\r
2678           appData.saveGameFile = InterpretFileName(buf, homeDir);\r
2679         }\r
2680       } else {\r
2681         appData.autoSaveGames = FALSE;\r
2682         ASSIGN(appData.saveGameFile, "");\r
2683       }\r
2684       appData.oldSaveStyle = IsDlgButtonChecked(hDlg, OPT_Old);\r
2685       appData.saveOutOfBookInfo = IsDlgButtonChecked( hDlg, OPT_OutOfBookInfo );\r
2686       EndDialog(hDlg, TRUE);\r
2687       return TRUE;\r
2688 \r
2689     case IDCANCEL:\r
2690       EndDialog(hDlg, FALSE);\r
2691       return TRUE;\r
2692 \r
2693     case OPT_AVBrowse:\r
2694       f = OpenFileDialog(hDlg, "a", NULL,\r
2695                          appData.oldSaveStyle ? "gam" : "pgn",\r
2696                          GAME_FILT, _("Browse for Auto Save File"),\r
2697                          NULL, NULL, buf);\r
2698       if (f != NULL) {\r
2699         fclose(f);\r
2700         SetDlgItemText(hDlg, OPT_AVFilename, buf);\r
2701       }\r
2702       break;\r
2703 \r
2704     default:\r
2705       SetSaveOptionEnables(hDlg);\r
2706       break;\r
2707     }\r
2708     break;\r
2709   }\r
2710   return FALSE;\r
2711 }\r
2712 \r
2713 VOID\r
2714 SaveOptionsPopup(HWND hwnd)\r
2715 {\r
2716   FARPROC lpProc = MakeProcInstance((FARPROC)SaveOptionsDialog, hInst);\r
2717   DialogBox(hInst, MAKEINTRESOURCE(DLG_SaveOptions), hwnd, (DLGPROC) lpProc);\r
2718   FreeProcInstance(lpProc);\r
2719 }\r
2720 \r
2721 /*---------------------------------------------------------------------------*\\r
2722  *\r
2723  * Time Control Options dialog functions\r
2724  *\r
2725 \*---------------------------------------------------------------------------*/\r
2726 \r
2727 VOID\r
2728 SetTimeControlEnables(HWND hDlg)\r
2729 {\r
2730   UINT state;\r
2731 \r
2732   state = IsDlgButtonChecked(hDlg, OPT_TCUseMoves)\r
2733         + 2*IsDlgButtonChecked(hDlg, OPT_TCUseFixed);\r
2734   EnableWindow(GetDlgItem(hDlg, OPT_TCTime), state == 1);\r
2735   EnableWindow(GetDlgItem(hDlg, OPT_TCMoves), state == 1);\r
2736   EnableWindow(GetDlgItem(hDlg, OPT_TCtext1), state == 1);\r
2737   EnableWindow(GetDlgItem(hDlg, OPT_TCtext2), state == 1);\r
2738   EnableWindow(GetDlgItem(hDlg, OPT_TCTime2), !state);\r
2739   EnableWindow(GetDlgItem(hDlg, OPT_TCInc), !state);\r
2740   EnableWindow(GetDlgItem(hDlg, OPT_TCitext1), !state);\r
2741   EnableWindow(GetDlgItem(hDlg, OPT_TCitext2), !state);\r
2742   EnableWindow(GetDlgItem(hDlg, OPT_TCitext3), !state);\r
2743   EnableWindow(GetDlgItem(hDlg, OPT_TCFixed), state == 2);\r
2744   EnableWindow(GetDlgItem(hDlg, OPT_TCftext), state == 2);\r
2745 }\r
2746 \r
2747 \r
2748 LRESULT CALLBACK\r
2749 TimeControl(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
2750 {\r
2751   char buf[MSG_SIZ], *tc;\r
2752   int mps, odds1, odds2, st;\r
2753   float increment;\r
2754   BOOL ok, ok2;\r
2755 \r
2756   switch (message) {\r
2757   case WM_INITDIALOG: /* message: initialize dialog box */\r
2758     /* Center the dialog over the application window */\r
2759     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
2760     Translate(hDlg, DLG_TimeControl);\r
2761     /* Initialize the dialog items */\r
2762     if (/*appData.clockMode &&*/ !appData.icsActive) { // [HGM] even if !clockMode, we could want to set it in tournament dialog\r
2763       if (searchTime) {\r
2764         CheckRadioButton(hDlg, OPT_TCUseMoves, OPT_TCUseFixed,\r
2765                          OPT_TCUseFixed);\r
2766         SetDlgItemInt(hDlg, OPT_TCFixed, searchTime, FALSE);\r
2767       } else\r
2768       if (appData.timeIncrement == -1) {\r
2769         CheckRadioButton(hDlg, OPT_TCUseMoves, OPT_TCUseFixed,\r
2770                          OPT_TCUseMoves);\r
2771         SetDlgItemText(hDlg, OPT_TCTime, appData.timeControl);\r
2772         SetDlgItemInt(hDlg, OPT_TCMoves, appData.movesPerSession,\r
2773                       FALSE);\r
2774         SetDlgItemText(hDlg, OPT_TCTime2, "");\r
2775         SetDlgItemText(hDlg, OPT_TCInc, "");\r
2776       } else {\r
2777         int i = appData.timeIncrement;\r
2778         if(i == appData.timeIncrement) snprintf(buf, MSG_SIZ, "%d", i);\r
2779         else snprintf(buf, MSG_SIZ, "%4.2f", appData.timeIncrement);\r
2780         CheckRadioButton(hDlg, OPT_TCUseMoves, OPT_TCUseFixed,\r
2781                          OPT_TCUseInc);\r
2782         SetDlgItemText(hDlg, OPT_TCTime, "");\r
2783         SetDlgItemText(hDlg, OPT_TCMoves, "");\r
2784         SetDlgItemText(hDlg, OPT_TCTime2, appData.timeControl);\r
2785         SetDlgItemText(hDlg, OPT_TCInc, buf);\r
2786       }\r
2787       SetDlgItemInt(hDlg, OPT_TCOdds1, 1, FALSE);\r
2788       SetDlgItemInt(hDlg, OPT_TCOdds2, 1, FALSE);\r
2789       SetTimeControlEnables(hDlg);\r
2790     }\r
2791     return TRUE;\r
2792 \r
2793   case WM_COMMAND: /* message: received a command */\r
2794     switch (LOWORD(wParam)) {\r
2795     case IDOK:\r
2796       mps = appData.movesPerSession;\r
2797       increment = appData.timeIncrement;\r
2798       tc = appData.timeControl;\r
2799       st = 0;\r
2800       /* Read changed options from the dialog box */\r
2801       if (IsDlgButtonChecked(hDlg, OPT_TCUseFixed)) {\r
2802         st = GetDlgItemInt(hDlg, OPT_TCFixed, &ok, FALSE);\r
2803         if (!ok || st <= 0) {\r
2804           MessageBox(hDlg, _("Invalid max time per move"),\r
2805                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2806           return FALSE;\r
2807         }\r
2808       } else\r
2809       if (IsDlgButtonChecked(hDlg, OPT_TCUseMoves)) {\r
2810         increment = -1;\r
2811         mps = GetDlgItemInt(hDlg, OPT_TCMoves, &ok, FALSE);\r
2812         if (!ok || mps <= 0) {\r
2813           MessageBox(hDlg, _("Invalid moves per time control"),\r
2814                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2815           return FALSE;\r
2816         }\r
2817         GetDlgItemText(hDlg, OPT_TCTime, buf, MSG_SIZ);\r
2818         if (!ParseTimeControl(buf, increment, mps)) {\r
2819           MessageBox(hDlg, _("Invalid minutes per time control"),\r
2820                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2821           return FALSE;\r
2822         }\r
2823       tc = buf;\r
2824       } else {\r
2825         GetDlgItemText(hDlg, OPT_TCInc, buf, MSG_SIZ);\r
2826         ok = (sscanf(buf, "%f%c", &increment, buf) == 1);\r
2827         if (!ok || increment < 0) {\r
2828           MessageBox(hDlg, _("Invalid increment"),\r
2829                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2830           return FALSE;\r
2831         }\r
2832         GetDlgItemText(hDlg, OPT_TCTime2, buf, MSG_SIZ);\r
2833         if (!ParseTimeControl(buf, increment, mps)) {\r
2834           MessageBox(hDlg, _("Invalid initial time"),\r
2835                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2836           return FALSE;\r
2837         }\r
2838       tc = buf;\r
2839       }\r
2840       odds1 = GetDlgItemInt(hDlg, OPT_TCOdds1, &ok, FALSE);\r
2841       odds2 = GetDlgItemInt(hDlg, OPT_TCOdds2, &ok2, FALSE);\r
2842       if (!ok || !ok2 || odds1 <= 0 || odds2 <= 0) {\r
2843           MessageBox(hDlg, _("Invalid time-odds factor"),\r
2844                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2845           return FALSE;\r
2846       }\r
2847       searchTime = st;\r
2848       appData.timeControl = strdup(tc);\r
2849       appData.movesPerSession = mps;\r
2850       appData.timeIncrement = increment;\r
2851       appData.firstTimeOdds  = first.timeOdds  = odds1;\r
2852       appData.secondTimeOdds = second.timeOdds = odds2;\r
2853       Reset(TRUE, TRUE);\r
2854       EndDialog(hDlg, TRUE);\r
2855       return TRUE;\r
2856 \r
2857     case IDCANCEL:\r
2858       EndDialog(hDlg, FALSE);\r
2859       return TRUE;\r
2860 \r
2861     default:\r
2862       SetTimeControlEnables(hDlg);\r
2863       break;\r
2864     }\r
2865     break;\r
2866   }\r
2867   return FALSE;\r
2868 }\r
2869 \r
2870 VOID\r
2871 TimeControlOptionsPopup(HWND hwnd)\r
2872 {\r
2873   if (gameMode != BeginningOfGame) {\r
2874     DisplayError(_("Changing time control during a game is not implemented"), 0);\r
2875   } else {\r
2876     FARPROC lpProc = MakeProcInstance((FARPROC)TimeControl, hInst);\r
2877     DialogBox(hInst, MAKEINTRESOURCE(DLG_TimeControl), hwnd, (DLGPROC) lpProc);\r
2878     FreeProcInstance(lpProc);\r
2879   }\r
2880 }\r
2881 \r
2882 /*---------------------------------------------------------------------------*\\r
2883  *\r
2884  * Engine Options Dialog functions\r
2885  *\r
2886 \*---------------------------------------------------------------------------*/\r
2887 #define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y))\r
2888 #define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x))\r
2889 \r
2890 #define INT_ABS( n )    ((n) >= 0 ? (n) : -(n))\r
2891 \r
2892 LRESULT CALLBACK EnginePlayOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
2893 {\r
2894   switch (message) {\r
2895   case WM_INITDIALOG: /* message: initialize dialog box */\r
2896 \r
2897     /* Center the dialog over the application window */\r
2898     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
2899     Translate(hDlg, DLG_EnginePlayOptions);\r
2900 \r
2901     /* Initialize the dialog items */\r
2902     CHECK_BOX(IDC_EpPeriodicUpdates, appData.periodicUpdates);\r
2903     CHECK_BOX(IDC_EpPonder, appData.ponderNextMove);\r
2904     CHECK_BOX(IDC_EpShowThinking, appData.showThinking);\r
2905     CHECK_BOX(IDC_EpHideThinkingHuman, appData.hideThinkingFromHuman);\r
2906 \r
2907     CHECK_BOX(IDC_TestClaims, appData.testClaims);\r
2908     CHECK_BOX(IDC_DetectMates, appData.checkMates);\r
2909     CHECK_BOX(IDC_MaterialDraws, appData.materialDraws);\r
2910     CHECK_BOX(IDC_TrivialDraws, appData.trivialDraws);\r
2911 \r
2912     CHECK_BOX(IDC_ScoreAbs1, appData.firstScoreIsAbsolute);\r
2913     CHECK_BOX(IDC_ScoreAbs2, appData.secondScoreIsAbsolute);\r
2914 \r
2915     SetDlgItemInt( hDlg, IDC_EpDrawMoveCount, appData.adjudicateDrawMoves, TRUE );\r
2916     SendDlgItemMessage( hDlg, IDC_EpDrawMoveCount, EM_SETSEL, 0, -1 );\r
2917 \r
2918     SetDlgItemInt( hDlg, IDC_EpAdjudicationThreshold, INT_ABS(appData.adjudicateLossThreshold), TRUE );\r
2919     SendDlgItemMessage( hDlg, IDC_EpAdjudicationThreshold, EM_SETSEL, 0, -1 );\r
2920 \r
2921     SetDlgItemInt( hDlg, IDC_RuleMoves, appData.ruleMoves, TRUE );\r
2922     SendDlgItemMessage( hDlg, IDC_RuleMoves, EM_SETSEL, 0, -1 );\r
2923 \r
2924     SetDlgItemInt( hDlg, IDC_DrawRepeats, INT_ABS(appData.drawRepeats), TRUE );\r
2925     SendDlgItemMessage( hDlg, IDC_DrawRepeats, EM_SETSEL, 0, -1 );\r
2926 \r
2927     return TRUE;\r
2928 \r
2929   case WM_COMMAND: /* message: received a command */\r
2930     switch (LOWORD(wParam)) {\r
2931     case IDOK:\r
2932       /* Read changed options from the dialog box */\r
2933       PeriodicUpdatesEvent(          IS_CHECKED(IDC_EpPeriodicUpdates));\r
2934       PonderNextMoveEvent(           IS_CHECKED(IDC_EpPonder));\r
2935       appData.hideThinkingFromHuman= IS_CHECKED(IDC_EpHideThinkingHuman); // [HGM] thinking: moved up\r
2936       appData.showThinking   = IS_CHECKED(IDC_EpShowThinking);\r
2937       ShowThinkingEvent(); // [HGM] thinking: tests all options that need thinking output\r
2938       appData.testClaims    = IS_CHECKED(IDC_TestClaims);\r
2939       appData.checkMates    = IS_CHECKED(IDC_DetectMates);\r
2940       appData.materialDraws = IS_CHECKED(IDC_MaterialDraws);\r
2941       appData.trivialDraws  = IS_CHECKED(IDC_TrivialDraws);\r
2942 \r
2943       appData.adjudicateDrawMoves = GetDlgItemInt(hDlg, IDC_EpDrawMoveCount, NULL, FALSE );\r
2944       appData.adjudicateLossThreshold = - (int) GetDlgItemInt(hDlg, IDC_EpAdjudicationThreshold, NULL, FALSE );\r
2945       appData.ruleMoves = GetDlgItemInt(hDlg, IDC_RuleMoves, NULL, FALSE );\r
2946       appData.drawRepeats = (int) GetDlgItemInt(hDlg, IDC_DrawRepeats, NULL, FALSE );\r
2947 \r
2948       first.scoreIsAbsolute  = appData.firstScoreIsAbsolute  = IS_CHECKED(IDC_ScoreAbs1);\r
2949       second.scoreIsAbsolute = appData.secondScoreIsAbsolute = IS_CHECKED(IDC_ScoreAbs2);\r
2950 \r
2951       EndDialog(hDlg, TRUE);\r
2952       return TRUE;\r
2953 \r
2954     case IDCANCEL:\r
2955       EndDialog(hDlg, FALSE);\r
2956       return TRUE;\r
2957 \r
2958     case IDC_EpDrawMoveCount:\r
2959     case IDC_EpAdjudicationThreshold:\r
2960     case IDC_DrawRepeats:\r
2961     case IDC_RuleMoves:\r
2962         if( HIWORD(wParam) == EN_CHANGE ) {\r
2963             int n1_ok;\r
2964             int n2_ok;\r
2965             int n3_ok;\r
2966             int n4_ok;\r
2967 \r
2968             GetDlgItemInt(hDlg, IDC_EpDrawMoveCount, &n1_ok, FALSE );\r
2969             GetDlgItemInt(hDlg, IDC_EpAdjudicationThreshold, &n2_ok, FALSE );\r
2970             GetDlgItemInt(hDlg, IDC_RuleMoves, &n3_ok, FALSE );\r
2971             GetDlgItemInt(hDlg, IDC_DrawRepeats, &n4_ok, FALSE );\r
2972 \r
2973             EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok && n3_ok && n4_ok ? TRUE : FALSE );\r
2974         }\r
2975         return TRUE;\r
2976     }\r
2977     break;\r
2978   }\r
2979   return FALSE;\r
2980 }\r
2981 \r
2982 VOID EnginePlayOptionsPopup(HWND hwnd)\r
2983 {\r
2984   FARPROC lpProc;\r
2985 \r
2986   lpProc = MakeProcInstance((FARPROC)EnginePlayOptionsDialog, hInst);\r
2987   DialogBox(hInst, MAKEINTRESOURCE(DLG_EnginePlayOptions), hwnd, (DLGPROC) lpProc);\r
2988   FreeProcInstance(lpProc);\r
2989 }\r
2990 \r
2991 /*---------------------------------------------------------------------------*\\r
2992  *\r
2993  * UCI Options Dialog functions\r
2994  *\r
2995 \*---------------------------------------------------------------------------*/\r
2996 INT CALLBACK BrowseCallbackProc(HWND hwnd, \r
2997                                 UINT uMsg,\r
2998                                 LPARAM lp, \r
2999                                 LPARAM pData) \r
3000 {\r
3001     switch(uMsg) \r
3002     {\r
3003       case BFFM_INITIALIZED: \r
3004         SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)pData);\r
3005         break;\r
3006     }\r
3007     return 0;\r
3008 }\r
3009 \r
3010 BOOL BrowseForFolder( const char * title, char * path )\r
3011 {\r
3012     BOOL result = FALSE;\r
3013     BROWSEINFO bi;\r
3014     LPITEMIDLIST pidl;\r
3015 \r
3016     ZeroMemory( &bi, sizeof(bi) );\r
3017 \r
3018     bi.lpszTitle = title == 0 ? _("Choose Folder") : title;\r
3019     bi.ulFlags = BIF_RETURNONLYFSDIRS;\r
3020     bi.lpfn = BrowseCallbackProc;\r
3021     bi.lParam = (LPARAM) path;\r
3022 \r
3023     pidl = SHBrowseForFolder( &bi );\r
3024 \r
3025     if( pidl != 0 ) {\r
3026         IMalloc * imalloc = 0;\r
3027 \r
3028         if( SHGetPathFromIDList( pidl, path ) ) {\r
3029             result = TRUE;\r
3030         }\r
3031 \r
3032         if( SUCCEEDED( SHGetMalloc ( &imalloc ) ) ) {\r
3033             imalloc->lpVtbl->Free(imalloc,pidl);\r
3034             imalloc->lpVtbl->Release(imalloc);\r
3035         }\r
3036     }\r
3037 \r
3038     return result;\r
3039 }\r
3040 \r
3041 int\r
3042 IsMultiFormat(char *s)\r
3043 {\r
3044   char *p = strchr(s, ':');\r
3045   return p && p != s+1;\r
3046 }\r
3047 \r
3048 LRESULT CALLBACK UciOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
3049 {\r
3050   char buf[MAX_PATH];\r
3051   int oldCores;\r
3052 \r
3053   switch (message) {\r
3054   case WM_INITDIALOG: /* message: initialize dialog box */\r
3055 \r
3056     /* Center the dialog over the application window */\r
3057     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
3058     Translate(hDlg, DLG_OptionsUCI);\r
3059 \r
3060     /* Initialize the dialog items */\r
3061     SetDlgItemText( hDlg, IDC_PolyglotDir, appData.polyglotDir );\r
3062     SetDlgItemInt( hDlg, IDC_HashSize, appData.defaultHashSize, TRUE );\r
3063     if(appData.defaultPathEGTB[0])\r
3064     SetDlgItemText( hDlg, IDC_PathToEGTB, appData.defaultPathEGTB );\r
3065     else\r
3066     SetDlgItemText( hDlg, IDC_PathToEGTB, appData.egtFormats );\r
3067     SetDlgItemInt( hDlg, IDC_SizeOfEGTB, appData.defaultCacheSizeEGTB, TRUE );\r
3068     CheckDlgButton( hDlg, IDC_UseBook, (BOOL) appData.usePolyglotBook );\r
3069     SetDlgItemText( hDlg, IDC_BookFile, appData.polyglotBook );\r
3070     // [HGM] smp: input field for nr of cores:\r
3071     SetDlgItemInt( hDlg, IDC_Cores, appData.smpCores, TRUE );\r
3072     // [HGM] book: tick boxes for own book use\r
3073     CheckDlgButton( hDlg, IDC_OwnBook1, (BOOL) appData.firstHasOwnBookUCI );\r
3074     CheckDlgButton( hDlg, IDC_OwnBook2, (BOOL) appData.secondHasOwnBookUCI );\r
3075     SetDlgItemInt( hDlg, IDC_BookDep, appData.bookDepth, TRUE );\r
3076     SetDlgItemInt( hDlg, IDC_BookStr, appData.bookStrength, TRUE );\r
3077     SetDlgItemInt( hDlg, IDC_Games, appData.defaultMatchGames, TRUE );\r
3078 \r
3079     SendDlgItemMessage( hDlg, IDC_PolyglotDir, EM_SETSEL, 0, -1 );\r
3080     // [HGM] Yet another ponder duplicate\r
3081     CheckDlgButton( hDlg, OPT_PonderNextMove, (BOOL) appData.ponderNextMove );\r
3082 \r
3083     return TRUE;\r
3084 \r
3085   case WM_COMMAND: /* message: received a command */\r
3086     switch (LOWORD(wParam)) {\r
3087     case IDOK:\r
3088       GetDlgItemText( hDlg, IDC_PolyglotDir, buf, sizeof(buf) );\r
3089       appData.polyglotDir = strdup(buf);\r
3090       appData.defaultHashSize = GetDlgItemInt(hDlg, IDC_HashSize, NULL, FALSE );\r
3091       appData.defaultCacheSizeEGTB = GetDlgItemInt(hDlg, IDC_SizeOfEGTB, NULL, FALSE );\r
3092       GetDlgItemText( hDlg, IDC_PathToEGTB, buf, sizeof(buf) );\r
3093       if(IsMultiFormat(buf)) {\r
3094         ASSIGN(appData.egtFormats, buf);\r
3095       } else {\r
3096         ASSIGN(appData.defaultPathEGTB, buf);\r
3097       }\r
3098       GetDlgItemText( hDlg, IDC_BookFile, buf, sizeof(buf) );\r
3099       appData.polyglotBook = strdup(buf);\r
3100       appData.usePolyglotBook = (Boolean) IsDlgButtonChecked( hDlg, IDC_UseBook );\r
3101       // [HGM] smp: get nr of cores and ponder:\r
3102       oldCores = appData.smpCores;\r
3103       appData.smpCores = GetDlgItemInt(hDlg, IDC_Cores, NULL, FALSE );\r
3104       if(appData.smpCores != oldCores) NewSettingEvent(FALSE, &(first.maxCores), "cores", appData.smpCores);\r
3105       PonderNextMoveEvent((Boolean) IsDlgButtonChecked( hDlg, OPT_PonderNextMove ));\r
3106       // [HGM] book: read tick boxes for own book use\r
3107       appData.firstHasOwnBookUCI  = (Boolean) IsDlgButtonChecked( hDlg, IDC_OwnBook1 );\r
3108       appData.secondHasOwnBookUCI = (Boolean) IsDlgButtonChecked( hDlg, IDC_OwnBook2 );\r
3109       appData.bookDepth = GetDlgItemInt(hDlg, IDC_BookDep, NULL, FALSE );\r
3110       appData.bookStrength = GetDlgItemInt(hDlg, IDC_BookStr, NULL, FALSE );\r
3111       appData.defaultMatchGames = GetDlgItemInt(hDlg, IDC_Games, NULL, FALSE );\r
3112 \r
3113       if(gameMode == BeginningOfGame) Reset(TRUE, TRUE);\r
3114       EndDialog(hDlg, TRUE);\r
3115       return TRUE;\r
3116 \r
3117     case IDCANCEL:\r
3118       EndDialog(hDlg, FALSE);\r
3119       return TRUE;\r
3120 \r
3121     case IDC_BrowseForBook:\r
3122       {\r
3123           char filter[] = {\r
3124               'A','l','l',' ','F','i','l','e','s', 0,\r
3125               '*','.','*', 0,\r
3126               'B','I','N',' ','F','i','l','e','s', 0,\r
3127               '*','.','b','i','n', 0,\r
3128               0 };\r
3129 \r
3130           OPENFILENAME ofn;\r
3131 \r
3132           safeStrCpy( buf, "" , sizeof( buf)/sizeof( buf[0]) );\r
3133 \r
3134           ZeroMemory( &ofn, sizeof(ofn) );\r
3135 \r
3136           ofn.lStructSize = sizeof(ofn);\r
3137           ofn.hwndOwner = hDlg;\r
3138           ofn.hInstance = hInst;\r
3139           ofn.lpstrFilter = filter;\r
3140 \r
3141           ofn.lpstrFile = buf;\r
3142           ofn.nMaxFile = sizeof(buf);\r
3143           ofn.lpstrTitle = _("Choose Book");\r
3144           ofn.Flags = OFN_FILEMUSTEXIST | OFN_LONGNAMES | OFN_HIDEREADONLY;\r
3145 \r
3146           if( GetOpenFileName( &ofn ) ) {\r
3147               SetDlgItemText( hDlg, IDC_BookFile, buf );\r
3148           }\r
3149       }\r
3150       return TRUE;\r
3151 \r
3152     case IDC_BrowseForPolyglotDir:\r
3153       if( BrowseForFolder( _("Choose Polyglot Directory"), buf ) ) {\r
3154         SetDlgItemText( hDlg, IDC_PolyglotDir, buf );\r
3155 \r
3156         strcat( buf, "\\polyglot.exe" );\r
3157 \r
3158         if( GetFileAttributes(buf) == 0xFFFFFFFF ) {\r
3159             MessageBox( hDlg, _("Polyglot was not found in the specified folder!"), "Warning", MB_OK | MB_ICONWARNING );\r
3160         }\r
3161       }\r
3162       return TRUE;\r
3163 \r
3164     case IDC_BrowseForEGTB:\r
3165       if( BrowseForFolder( _("Choose EGTB Directory:"), buf ) ) {\r
3166         SetDlgItemText( hDlg, IDC_PathToEGTB, buf );\r
3167       }\r
3168       return TRUE;\r
3169 \r
3170     case IDC_HashSize:\r
3171     case IDC_SizeOfEGTB:\r
3172         if( HIWORD(wParam) == EN_CHANGE ) {\r
3173             int n1_ok;\r
3174             int n2_ok;\r
3175 \r
3176             GetDlgItemInt(hDlg, IDC_HashSize, &n1_ok, FALSE );\r
3177             GetDlgItemInt(hDlg, IDC_SizeOfEGTB, &n2_ok, FALSE );\r
3178 \r
3179             EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok ? TRUE : FALSE );\r
3180         }\r
3181         return TRUE;\r
3182     }\r
3183     break;\r
3184   }\r
3185   return FALSE;\r
3186 }\r
3187 \r
3188 VOID UciOptionsPopup(HWND hwnd)\r
3189 {\r
3190   FARPROC lpProc;\r
3191 \r
3192   lpProc = MakeProcInstance((FARPROC)UciOptionsDialog, hInst);\r
3193   DialogBox(hInst, MAKEINTRESOURCE(DLG_OptionsUCI), hwnd, (DLGPROC) lpProc);\r
3194   FreeProcInstance(lpProc);\r
3195 }\r