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