Fix variant choice for second engine
[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 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     OPT_VariantXiangqi,\r
847     OPT_VariantCourier,\r
848     OPT_VariantGothic,\r
849     OPT_VariantCapablanca,\r
850     OPT_VariantKnightmate,\r
851     OPT_VariantFairy,        \r
852     OPT_VariantCylinder,\r
853     OPT_VariantFalcon,\r
854     OPT_VariantCRC,\r
855     OPT_VariantBerolina,\r
856     OPT_VariantJanus,\r
857     OPT_VariantSuper,\r
858     OPT_VariantGreat,\r
859     -1, // Twilight,\r
860     OPT_VariantMakruk,\r
861     OPT_VariantASEAN,\r
862     OPT_VariantSChess,\r
863     OPT_VariantGrand,\r
864     OPT_VariantSpartan, // Spartan\r
865     -2 // sentinel\r
866 };\r
867 \r
868 VariantClass\r
869 VariantWhichRadio(HWND hDlg)\r
870 {\r
871   int i=0, j;\r
872   while((j = radioButton[i++]) != -2) {\r
873         if(j == -1) continue; // no menu button\r
874         if(IsDlgButtonChecked(hDlg, j) &&\r
875            (appData.noChessProgram || strstr(first.variants, VariantName(i-1)))) return (VariantClass) i-1;\r
876   }\r
877   *engineVariant = NULLCHAR;\r
878   for(i=0; i<9; i++) { // check for engine-defined variants\r
879     if(IsDlgButtonChecked(hDlg, OPT_EngineVariant+i) ) {\r
880         GetDlgItemText(hDlg, OPT_EngineVariant+i, engineVariant, MSG_SIZ); // remember name, so we can resolve it later\r
881         return VariantUnknown;\r
882     }\r
883   }\r
884   return gameInfo.variant; // If no button checked, keep old\r
885 }\r
886 \r
887 void\r
888 VariantShowRadio(HWND hDlg)\r
889 {\r
890   int i=0, j;\r
891   CheckDlgButton(hDlg, radioButton[gameInfo.variant], TRUE);\r
892   while((j = radioButton[i++]) != -2) {\r
893         if(j == -1) continue; // no menu button\r
894         EnableWindow(GetDlgItem(hDlg, j), appData.noChessProgram || strstr(first.variants, VariantName(i-1)));\r
895   }\r
896   for(i=0; i<9; i++) { // initialize engine-defined variants\r
897     char *v = EngineDefinedVariant(&first, i); // get name of #i\r
898     if(v) { // there is such a variant\r
899         EnableWindow(GetDlgItem(hDlg, OPT_EngineVariant+i), TRUE);     // and enable the button\r
900         SetDlgItemText(hDlg, OPT_EngineVariant+i, v);                  // put its name on button\r
901     } else EnableWindow(GetDlgItem(hDlg, OPT_EngineVariant+i), FALSE); // no such variant; disable button\r
902   }\r
903 }\r
904 \r
905 LRESULT CALLBACK\r
906 NewVariantDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
907 {\r
908   static VariantClass v;\r
909   static int n1_ok, n2_ok, n3_ok;\r
910 \r
911   switch (message) {\r
912   case WM_INITDIALOG: /* message: initialize dialog box */\r
913     /* Center the dialog over the application window */\r
914     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
915     Translate(hDlg, DLG_NewVariant);\r
916 \r
917     /* Initialize the dialog items */\r
918     VariantShowRadio(hDlg);\r
919 \r
920     SetDlgItemInt( hDlg, IDC_Files, -1, TRUE );\r
921     SendDlgItemMessage( hDlg, IDC_Files, EM_SETSEL, 0, -1 );\r
922 \r
923     SetDlgItemInt( hDlg, IDC_Ranks, -1, TRUE );\r
924     SendDlgItemMessage( hDlg, IDC_Ranks, EM_SETSEL, 0, -1 );\r
925 \r
926     SetDlgItemInt( hDlg, IDC_Holdings, -1, TRUE );\r
927     SendDlgItemMessage( hDlg, IDC_Ranks, EM_SETSEL, 0, -1 );\r
928 \r
929     n1_ok = n2_ok = n3_ok = FALSE;\r
930 \r
931     return TRUE;\r
932 \r
933   case WM_COMMAND: /* message: received a command */\r
934     switch (LOWORD(wParam)) {\r
935     case IDOK:\r
936       /*\r
937        * if we call EndDialog() after the call to ChangeBoardSize(),\r
938        * then ChangeBoardSize() does not take effect, although the new\r
939        * boardSize is saved. Go figure...\r
940        */\r
941       EndDialog(hDlg, TRUE);\r
942 \r
943       v = VariantWhichRadio(hDlg);\r
944       if(!appData.noChessProgram) {\r
945         char *name = VariantName(v), buf[MSG_SIZ];\r
946         if (first.protocolVersion > 1 && StrStr(first.variants, name) == NULL) {\r
947           /* [HGM] in protocol 2 we check if variant is suported by engine */\r
948           snprintf(buf, MSG_SIZ, _("Variant %s not supported by %s"), name, first.tidy);\r
949           DisplayError(buf, 0);\r
950           return TRUE; /* treat as _("Cancel") if first engine does not support it */\r
951         } else\r
952         if (second.initDone && second.protocolVersion > 1 && StrStr(second.variants, name) == NULL) {\r
953           snprintf(buf, MSG_SIZ, _("Warning: second engine (%s) does not support this!"), second.tidy);\r
954           DisplayError(buf, 0);   /* use of second engine is optional; only warn user */\r
955         }\r
956       }\r
957 \r
958       gameInfo.variant = v;\r
959       appData.variant = VariantName(v);\r
960 \r
961       appData.NrFiles = (int) GetDlgItemInt(hDlg, IDC_Files, NULL, FALSE );\r
962       appData.NrRanks = (int) GetDlgItemInt(hDlg, IDC_Ranks, NULL, FALSE );\r
963       appData.holdingsSize = (int) GetDlgItemInt(hDlg, IDC_Holdings, NULL, FALSE );\r
964 \r
965       if(!n1_ok) appData.NrFiles = -1;\r
966       if(!n2_ok) appData.NrRanks = -1;\r
967       if(!n3_ok) appData.holdingsSize = -1;\r
968 \r
969       shuffleOpenings = FALSE; /* [HGM] shuffle: possible shuffle reset when we switch */\r
970       startedFromPositionFile = FALSE; /* [HGM] loadPos: no longer valid in new variant */\r
971       appData.pieceToCharTable = NULL;\r
972       Reset(TRUE, TRUE);\r
973 \r
974       return TRUE;\r
975 \r
976     case IDCANCEL:\r
977       EndDialog(hDlg, FALSE);\r
978       return TRUE;\r
979 \r
980     case IDC_Ranks:\r
981     case IDC_Files:\r
982     case IDC_Holdings:\r
983         if( HIWORD(wParam) == EN_CHANGE ) {\r
984 \r
985             GetDlgItemInt(hDlg, IDC_Files, &n1_ok, FALSE );\r
986             GetDlgItemInt(hDlg, IDC_Ranks, &n2_ok, FALSE );\r
987             GetDlgItemInt(hDlg, IDC_Holdings, &n3_ok, FALSE );\r
988 \r
989             /*EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok && n3_ok ? TRUE : FALSE );*/\r
990         }\r
991         return TRUE;\r
992     }\r
993     break;\r
994   }\r
995   return FALSE;\r
996 }\r
997 \r
998 \r
999 VOID\r
1000 NewVariantPopup(HWND hwnd)\r
1001 {\r
1002   FARPROC lpProc = MakeProcInstance((FARPROC)NewVariantDialog, hInst);\r
1003   DialogBox(hInst, MAKEINTRESOURCE(DLG_NewVariant), hwnd,\r
1004           (DLGPROC) lpProc);\r
1005   FreeProcInstance(lpProc);\r
1006 }\r
1007 \r
1008 /*---------------------------------------------------------------------------*\\r
1009  *\r
1010  * ICS Options Dialog functions\r
1011  *\r
1012 \*---------------------------------------------------------------------------*/\r
1013 \r
1014 BOOL APIENTRY\r
1015 MyCreateFont(HWND hwnd, MyFont *font)\r
1016 {\r
1017   CHOOSEFONT cf;\r
1018   HFONT hf;\r
1019 \r
1020   /* Initialize members of the CHOOSEFONT structure. */\r
1021   cf.lStructSize = sizeof(CHOOSEFONT);\r
1022   cf.hwndOwner = hwnd;\r
1023   cf.hDC = (HDC)NULL;\r
1024   cf.lpLogFont = &font->lf;\r
1025   cf.iPointSize = 0;\r
1026   cf.Flags = CF_SCREENFONTS|/*CF_ANSIONLY|*/CF_INITTOLOGFONTSTRUCT;\r
1027   cf.rgbColors = RGB(0,0,0);\r
1028   cf.lCustData = 0L;\r
1029   cf.lpfnHook = (LPCFHOOKPROC)NULL;\r
1030   cf.lpTemplateName = (LPSTR)NULL;\r
1031   cf.hInstance = (HINSTANCE) NULL;\r
1032   cf.lpszStyle = (LPSTR)NULL;\r
1033   cf.nFontType = SCREEN_FONTTYPE;\r
1034   cf.nSizeMin = 0;\r
1035   cf.nSizeMax = 0;\r
1036 \r
1037   /* Display the CHOOSEFONT common-dialog box. */\r
1038   if (!ChooseFont(&cf)) {\r
1039     return FALSE;\r
1040   }\r
1041 \r
1042   /* Create a logical font based on the user's   */\r
1043   /* selection and return a handle identifying   */\r
1044   /* that font. */\r
1045   hf = CreateFontIndirect(cf.lpLogFont);\r
1046   if (hf == NULL) {\r
1047     return FALSE;\r
1048   }\r
1049 \r
1050   font->hf = hf;\r
1051   font->mfp.pointSize = (float) (cf.iPointSize / 10.0);\r
1052   font->mfp.bold = (font->lf.lfWeight >= FW_BOLD);\r
1053   font->mfp.italic = font->lf.lfItalic;\r
1054   font->mfp.underline = font->lf.lfUnderline;\r
1055   font->mfp.strikeout = font->lf.lfStrikeOut;\r
1056   font->mfp.charset = font->lf.lfCharSet;\r
1057   safeStrCpy(font->mfp.faceName, font->lf.lfFaceName, sizeof(font->mfp.faceName)/sizeof(font->mfp.faceName[0]) );\r
1058   return TRUE;\r
1059 }\r
1060 \r
1061 \r
1062 VOID\r
1063 UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca)\r
1064 {\r
1065   CHARFORMAT cf;\r
1066   cf.cbSize = sizeof(CHARFORMAT);\r
1067   cf.dwMask =\r
1068     CFM_COLOR|CFM_CHARSET|CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_STRIKEOUT|CFM_FACE|CFM_SIZE;\r
1069   cf.crTextColor = mca->color;\r
1070   cf.dwEffects = mca->effects;\r
1071   safeStrCpy(cf.szFaceName, font[boardSize][CONSOLE_FONT]->mfp.faceName, sizeof(cf.szFaceName)/sizeof(cf.szFaceName[0]) );\r
1072   /*\r
1073    * The 20.0 below is in fact documented. yHeight is expressed in twips.\r
1074    * A twip is 1/20 of a font's point size. See documentation of CHARFORMAT.\r
1075    * --msw\r
1076    */\r
1077   cf.yHeight = (int)(font[boardSize][CONSOLE_FONT]->mfp.pointSize * 20.0 + 0.5);\r
1078   cf.bCharSet = DEFAULT_CHARSET; /* should be ignored anyway */\r
1079   cf.bPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;\r
1080   SendDlgItemMessage(hDlg, id, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);\r
1081 }\r
1082 \r
1083 LRESULT CALLBACK\r
1084 ColorizeTextDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
1085 {\r
1086   static MyColorizeAttribs mca;\r
1087   static ColorClass cc;\r
1088   COLORREF background = (COLORREF)0;\r
1089 \r
1090   switch (message) {\r
1091   case WM_INITDIALOG:\r
1092     cc = (ColorClass)lParam;\r
1093     mca = colorizeAttribs[cc];\r
1094     /* Center the dialog over the application window */\r
1095     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
1096     Translate(hDlg, DLG_Colorize);\r
1097     /* Initialize the dialog items */\r
1098     CheckDlgButton(hDlg, OPT_Bold, (mca.effects & CFE_BOLD) != 0);\r
1099     CheckDlgButton(hDlg, OPT_Italic, (mca.effects & CFE_ITALIC) != 0);\r
1100     CheckDlgButton(hDlg, OPT_Underline, (mca.effects & CFE_UNDERLINE) != 0);\r
1101     CheckDlgButton(hDlg, OPT_Strikeout, (mca.effects & CFE_STRIKEOUT) != 0);\r
1102 \r
1103     /* get the current background color from the parent window */\r
1104     SendMessage(GetWindow(hDlg, GW_OWNER),WM_COMMAND,\r
1105                 (WPARAM)WM_USER_GetConsoleBackground,\r
1106                 (LPARAM)&background);\r
1107 \r
1108     /* set the background color */\r
1109     SendDlgItemMessage(hDlg, OPT_Sample, EM_SETBKGNDCOLOR, FALSE, background);\r
1110 \r
1111     SetDlgItemText(hDlg, OPT_Sample, T_(mca.name));\r
1112     UpdateSampleText(hDlg, OPT_Sample, &mca);\r
1113     return TRUE;\r
1114 \r
1115   case WM_COMMAND: /* message: received a command */\r
1116     switch (LOWORD(wParam)) {\r
1117     case IDOK:\r
1118       /* Read changed options from the dialog box */\r
1119       colorizeAttribs[cc] = mca;\r
1120       textAttribs[cc].color = mca.color;\r
1121       textAttribs[cc].effects = mca.effects;\r
1122       Colorize(currentColorClass, TRUE);\r
1123       if (cc == ColorNormal) {\r
1124         CHARFORMAT cf;\r
1125         cf.cbSize = sizeof(CHARFORMAT);\r
1126         cf.dwMask = CFM_COLOR;\r
1127         cf.crTextColor = mca.color;\r
1128         SendDlgItemMessage(hwndConsole, OPT_ConsoleInput,\r
1129           EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);\r
1130       }\r
1131       EndDialog(hDlg, TRUE);\r
1132       return TRUE;\r
1133 \r
1134     case IDCANCEL:\r
1135       EndDialog(hDlg, FALSE);\r
1136       return TRUE;\r
1137 \r
1138     case OPT_ChooseColor:\r
1139       ChangeColor(hDlg, &mca.color);\r
1140       UpdateSampleText(hDlg, OPT_Sample, &mca);\r
1141       return TRUE;\r
1142 \r
1143     default:\r
1144       mca.effects =\r
1145         (IsDlgButtonChecked(hDlg, OPT_Bold) ? CFE_BOLD : 0) |\r
1146         (IsDlgButtonChecked(hDlg, OPT_Italic) ? CFE_ITALIC : 0) |\r
1147         (IsDlgButtonChecked(hDlg, OPT_Underline) ? CFE_UNDERLINE : 0) |\r
1148         (IsDlgButtonChecked(hDlg, OPT_Strikeout) ? CFE_STRIKEOUT : 0);\r
1149       UpdateSampleText(hDlg, OPT_Sample, &mca);\r
1150       break;\r
1151     }\r
1152     break;\r
1153   }\r
1154   return FALSE;\r
1155 }\r
1156 \r
1157 VOID\r
1158 ColorizeTextPopup(HWND hwnd, ColorClass cc)\r
1159 {\r
1160   FARPROC lpProc;\r
1161 \r
1162   lpProc = MakeProcInstance((FARPROC)ColorizeTextDialog, hInst);\r
1163   DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_Colorize),\r
1164     hwnd, (DLGPROC)lpProc, (LPARAM) cc);\r
1165   FreeProcInstance(lpProc);\r
1166 }\r
1167 \r
1168 VOID\r
1169 SetIcsOptionEnables(HWND hDlg)\r
1170 {\r
1171 #define ENABLE_DLG_ITEM(x,y) EnableWindow(GetDlgItem(hDlg,(x)), (y))\r
1172 \r
1173   UINT state = IsDlgButtonChecked(hDlg, OPT_Premove);\r
1174   ENABLE_DLG_ITEM(OPT_PremoveWhite, state);\r
1175   ENABLE_DLG_ITEM(OPT_PremoveWhiteText, state);\r
1176   ENABLE_DLG_ITEM(OPT_PremoveBlack, state);\r
1177   ENABLE_DLG_ITEM(OPT_PremoveBlackText, state);\r
1178 \r
1179   ENABLE_DLG_ITEM(OPT_IcsAlarmTime, IsDlgButtonChecked(hDlg, OPT_IcsAlarm));\r
1180 \r
1181 #undef ENABLE_DLG_ITEM\r
1182 }\r
1183 \r
1184 \r
1185 LRESULT CALLBACK\r
1186 IcsOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
1187 {\r
1188   char buf[MSG_SIZ];\r
1189   int number;\r
1190   int i;\r
1191   static COLORREF cbc;\r
1192   static MyColorizeAttribs *mca;\r
1193   COLORREF *colorref;\r
1194 \r
1195   switch (message) {\r
1196   case WM_INITDIALOG: /* message: initialize dialog box */\r
1197 \r
1198     mca = colorizeAttribs;\r
1199 \r
1200     for (i=0; i < NColorClasses - 1; i++) {\r
1201       mca[i].color   = textAttribs[i].color;\r
1202       mca[i].effects = textAttribs[i].effects;\r
1203     }\r
1204     cbc = consoleBackgroundColor;\r
1205 \r
1206     /* Center the dialog over the application window */\r
1207     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
1208     Translate(hDlg, DLG_IcsOptions);\r
1209 \r
1210     /* Initialize the dialog items */\r
1211 #define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y))\r
1212 \r
1213     CHECK_BOX(OPT_AutoKibitz, appData.autoKibitz);\r
1214     CHECK_BOX(OPT_AutoComment, appData.autoComment);\r
1215     CHECK_BOX(OPT_AutoObserve, appData.autoObserve);\r
1216     CHECK_BOX(OPT_AutoCreate, appData.autoCreateLogon);\r
1217     CHECK_BOX(OPT_GetMoveList, appData.getMoveList);\r
1218     CHECK_BOX(OPT_LocalLineEditing, appData.localLineEditing);\r
1219     CHECK_BOX(OPT_QuietPlay, appData.quietPlay);\r
1220     CHECK_BOX(OPT_SeekGraph, appData.seekGraph);\r
1221     CHECK_BOX(OPT_AutoRefresh, appData.autoRefresh);\r
1222     CHECK_BOX(OPT_BgObserve, appData.bgObserve);\r
1223     CHECK_BOX(OPT_DualBoard, appData.dualBoard);\r
1224     CHECK_BOX(OPT_SmartMove, appData.oneClick);\r
1225     CHECK_BOX(OPT_Premove, appData.premove);\r
1226     CHECK_BOX(OPT_PremoveWhite, appData.premoveWhite);\r
1227     CHECK_BOX(OPT_PremoveBlack, appData.premoveBlack);\r
1228     CHECK_BOX(OPT_IcsAlarm, appData.icsAlarm);\r
1229     CHECK_BOX(OPT_DontColorize, !appData.colorize);\r
1230 \r
1231 #undef CHECK_BOX\r
1232 \r
1233     snprintf(buf, MSG_SIZ, "%d", appData.icsAlarmTime / 1000);\r
1234     SetDlgItemText(hDlg, OPT_IcsAlarmTime, buf);\r
1235     SetDlgItemText(hDlg, OPT_PremoveWhiteText, appData.premoveWhiteText);\r
1236     SetDlgItemText(hDlg, OPT_PremoveBlackText, appData.premoveBlackText);\r
1237     SetDlgItemText(hDlg, OPT_StartupChatBoxes, appData.chatBoxes);\r
1238 \r
1239     SendDlgItemMessage(hDlg, OPT_SampleShout,     EM_SETBKGNDCOLOR, 0, cbc);\r
1240     SendDlgItemMessage(hDlg, OPT_SampleSShout,    EM_SETBKGNDCOLOR, 0, cbc);\r
1241     SendDlgItemMessage(hDlg, OPT_SampleChannel1,  EM_SETBKGNDCOLOR, 0, cbc);\r
1242     SendDlgItemMessage(hDlg, OPT_SampleChannel,   EM_SETBKGNDCOLOR, 0, cbc);\r
1243     SendDlgItemMessage(hDlg, OPT_SampleKibitz,    EM_SETBKGNDCOLOR, 0, cbc);\r
1244     SendDlgItemMessage(hDlg, OPT_SampleTell,      EM_SETBKGNDCOLOR, 0, cbc);\r
1245     SendDlgItemMessage(hDlg, OPT_SampleChallenge, EM_SETBKGNDCOLOR, 0, cbc);\r
1246     SendDlgItemMessage(hDlg, OPT_SampleRequest,   EM_SETBKGNDCOLOR, 0, cbc);\r
1247     SendDlgItemMessage(hDlg, OPT_SampleSeek,      EM_SETBKGNDCOLOR, 0, cbc);\r
1248     SendDlgItemMessage(hDlg, OPT_SampleNormal,    EM_SETBKGNDCOLOR, 0, cbc);\r
1249 \r
1250     SetDlgItemText(hDlg, OPT_SampleShout,     T_(mca[ColorShout].name));\r
1251     SetDlgItemText(hDlg, OPT_SampleSShout,    T_(mca[ColorSShout].name));\r
1252     SetDlgItemText(hDlg, OPT_SampleChannel1,  T_(mca[ColorChannel1].name));\r
1253     SetDlgItemText(hDlg, OPT_SampleChannel,   T_(mca[ColorChannel].name));\r
1254     SetDlgItemText(hDlg, OPT_SampleKibitz,    T_(mca[ColorKibitz].name));\r
1255     SetDlgItemText(hDlg, OPT_SampleTell,      T_(mca[ColorTell].name));\r
1256     SetDlgItemText(hDlg, OPT_SampleChallenge, T_(mca[ColorChallenge].name));\r
1257     SetDlgItemText(hDlg, OPT_SampleRequest,   T_(mca[ColorRequest].name));\r
1258     SetDlgItemText(hDlg, OPT_SampleSeek,      T_(mca[ColorSeek].name));\r
1259     SetDlgItemText(hDlg, OPT_SampleNormal,    T_(mca[ColorNormal].name));\r
1260 \r
1261     UpdateSampleText(hDlg, OPT_SampleShout,     &mca[ColorShout]);\r
1262     UpdateSampleText(hDlg, OPT_SampleSShout,    &mca[ColorSShout]);\r
1263     UpdateSampleText(hDlg, OPT_SampleChannel1,  &mca[ColorChannel1]);\r
1264     UpdateSampleText(hDlg, OPT_SampleChannel,   &mca[ColorChannel]);\r
1265     UpdateSampleText(hDlg, OPT_SampleKibitz,    &mca[ColorKibitz]);\r
1266     UpdateSampleText(hDlg, OPT_SampleTell,      &mca[ColorTell]);\r
1267     UpdateSampleText(hDlg, OPT_SampleChallenge, &mca[ColorChallenge]);\r
1268     UpdateSampleText(hDlg, OPT_SampleRequest,   &mca[ColorRequest]);\r
1269     UpdateSampleText(hDlg, OPT_SampleSeek,      &mca[ColorSeek]);\r
1270     UpdateSampleText(hDlg, OPT_SampleNormal,    &mca[ColorNormal]);\r
1271 \r
1272     SetIcsOptionEnables(hDlg);\r
1273     return TRUE;\r
1274 \r
1275   case WM_COMMAND: /* message: received a command */\r
1276     switch (LOWORD(wParam)) {\r
1277 \r
1278     case WM_USER_GetConsoleBackground:\r
1279       /* the ColorizeTextDialog needs the current background color */\r
1280       colorref = (COLORREF *)lParam;\r
1281       *colorref = cbc;\r
1282       return FALSE;\r
1283 \r
1284     case IDOK:\r
1285       /* Read changed options from the dialog box */\r
1286       GetDlgItemText(hDlg, OPT_IcsAlarmTime, buf, MSG_SIZ);\r
1287       if (sscanf(buf, "%d", &number) != 1 || (number < 0)){\r
1288           MessageBox(hDlg, _("Invalid ICS Alarm Time"),\r
1289                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
1290           return FALSE;\r
1291       }\r
1292 \r
1293 #define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x))\r
1294 \r
1295       appData.icsAlarm         = IS_CHECKED(OPT_IcsAlarm);\r
1296       appData.premove          = IS_CHECKED(OPT_Premove);\r
1297       appData.premoveWhite     = IS_CHECKED(OPT_PremoveWhite);\r
1298       appData.premoveBlack     = IS_CHECKED(OPT_PremoveBlack);\r
1299       appData.autoKibitz       = IS_CHECKED(OPT_AutoKibitz);\r
1300       appData.autoComment      = IS_CHECKED(OPT_AutoComment);\r
1301       appData.autoObserve      = IS_CHECKED(OPT_AutoObserve);\r
1302       appData.autoCreateLogon  = IS_CHECKED(OPT_AutoCreate);\r
1303       appData.getMoveList      = IS_CHECKED(OPT_GetMoveList);\r
1304       appData.localLineEditing = IS_CHECKED(OPT_LocalLineEditing);\r
1305       appData.quietPlay        = IS_CHECKED(OPT_QuietPlay);\r
1306       appData.seekGraph        = IS_CHECKED(OPT_SeekGraph);\r
1307       appData.autoRefresh      = IS_CHECKED(OPT_AutoRefresh);\r
1308       appData.bgObserve        = IS_CHECKED(OPT_BgObserve);\r
1309       appData.dualBoard        = IS_CHECKED(OPT_DualBoard);\r
1310       appData.oneClick         = IS_CHECKED(OPT_SmartMove);\r
1311 \r
1312 #undef IS_CHECKED\r
1313 \r
1314       appData.icsAlarmTime = number * 1000;\r
1315       GetDlgItemText(hDlg, OPT_PremoveWhiteText, appData.premoveWhiteText, 5);\r
1316       GetDlgItemText(hDlg, OPT_PremoveBlackText, appData.premoveBlackText, 5);\r
1317       GetDlgItemText(hDlg, OPT_StartupChatBoxes, buf, sizeof(buf));\r
1318       buf[sizeof(buf)-1] = NULLCHAR; appData.chatBoxes = StrSave(buf); // memory leak\r
1319 \r
1320       if (appData.localLineEditing) {\r
1321         DontEcho();\r
1322         EchoOn();\r
1323       } else {\r
1324         DoEcho();\r
1325         EchoOff();\r
1326       }\r
1327 \r
1328       appData.colorize =\r
1329         (Boolean)!IsDlgButtonChecked(hDlg, OPT_DontColorize);\r
1330 \r
1331     ChangedConsoleFont();\r
1332 \r
1333     if (!appData.colorize) {\r
1334         CHARFORMAT cf;\r
1335         COLORREF background = ParseColorName(COLOR_BKGD);\r
1336         /*\r
1337         SetDefaultTextAttribs();\r
1338         Colorize(currentColorClass);\r
1339         */\r
1340         cf.cbSize = sizeof(CHARFORMAT);\r
1341         cf.dwMask = CFM_COLOR;\r
1342         cf.crTextColor = ParseColorName(COLOR_NORMAL);\r
1343 \r
1344         SendDlgItemMessage(hwndConsole, OPT_ConsoleInput,\r
1345           EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);\r
1346         SendDlgItemMessage(hwndConsole, OPT_ConsoleText,\r
1347           EM_SETBKGNDCOLOR, FALSE, background);\r
1348         SendDlgItemMessage(hwndConsole, OPT_ConsoleInput,\r
1349           EM_SETBKGNDCOLOR, FALSE, background);\r
1350       }\r
1351 \r
1352       if (cbc != consoleBackgroundColor) {\r
1353         consoleBackgroundColor = cbc;\r
1354         if (appData.colorize) {\r
1355           SendDlgItemMessage(hwndConsole, OPT_ConsoleText,\r
1356             EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor);\r
1357           SendDlgItemMessage(hwndConsole, OPT_ConsoleInput,\r
1358             EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor);\r
1359         }\r
1360       }\r
1361 \r
1362       for (i=0; i < NColorClasses - 1; i++) {\r
1363         textAttribs[i].color   = mca[i].color;\r
1364         textAttribs[i].effects = mca[i].effects;\r
1365       }\r
1366 \r
1367       EndDialog(hDlg, TRUE);\r
1368       return TRUE;\r
1369 \r
1370     case IDCANCEL:\r
1371       EndDialog(hDlg, FALSE);\r
1372       return TRUE;\r
1373 \r
1374     case OPT_ChooseShoutColor:\r
1375       ColorizeTextPopup(hDlg, ColorShout);\r
1376       UpdateSampleText(hDlg, OPT_SampleShout, &mca[ColorShout]);\r
1377       break;\r
1378 \r
1379     case OPT_ChooseSShoutColor:\r
1380       ColorizeTextPopup(hDlg, ColorSShout);\r
1381       UpdateSampleText(hDlg, OPT_SampleSShout, &mca[ColorSShout]);\r
1382       break;\r
1383 \r
1384     case OPT_ChooseChannel1Color:\r
1385       ColorizeTextPopup(hDlg, ColorChannel1);\r
1386       UpdateSampleText(hDlg, OPT_SampleChannel1,\r
1387                        &colorizeAttribs[ColorChannel1]);\r
1388       break;\r
1389 \r
1390     case OPT_ChooseChannelColor:\r
1391       ColorizeTextPopup(hDlg, ColorChannel);\r
1392       UpdateSampleText(hDlg, OPT_SampleChannel, &mca[ColorChannel]);\r
1393       break;\r
1394 \r
1395     case OPT_ChooseKibitzColor:\r
1396       ColorizeTextPopup(hDlg, ColorKibitz);\r
1397       UpdateSampleText(hDlg, OPT_SampleKibitz, &mca[ColorKibitz]);\r
1398       break;\r
1399 \r
1400     case OPT_ChooseTellColor:\r
1401       ColorizeTextPopup(hDlg, ColorTell);\r
1402       UpdateSampleText(hDlg, OPT_SampleTell, &mca[ColorTell]);\r
1403       break;\r
1404 \r
1405     case OPT_ChooseChallengeColor:\r
1406       ColorizeTextPopup(hDlg, ColorChallenge);\r
1407       UpdateSampleText(hDlg, OPT_SampleChallenge, &mca[ColorChallenge]);\r
1408       break;\r
1409 \r
1410     case OPT_ChooseRequestColor:\r
1411       ColorizeTextPopup(hDlg, ColorRequest);\r
1412       UpdateSampleText(hDlg, OPT_SampleRequest, &mca[ColorRequest]);\r
1413       break;\r
1414 \r
1415     case OPT_ChooseSeekColor:\r
1416       ColorizeTextPopup(hDlg, ColorSeek);\r
1417       UpdateSampleText(hDlg, OPT_SampleSeek, &mca[ColorSeek]);\r
1418       break;\r
1419 \r
1420 \r
1421     case OPT_ChooseNormalColor:\r
1422       ColorizeTextPopup(hDlg, ColorNormal);\r
1423       UpdateSampleText(hDlg, OPT_SampleNormal, &mca[ColorNormal]);\r
1424       break;\r
1425 \r
1426     case OPT_ChooseBackgroundColor:\r
1427       if (ChangeColor(hDlg, &cbc)) {\r
1428         SendDlgItemMessage(hDlg, OPT_SampleShout,     EM_SETBKGNDCOLOR, 0, cbc);\r
1429         SendDlgItemMessage(hDlg, OPT_SampleSShout,    EM_SETBKGNDCOLOR, 0, cbc);\r
1430         SendDlgItemMessage(hDlg, OPT_SampleChannel1,  EM_SETBKGNDCOLOR, 0, cbc);\r
1431         SendDlgItemMessage(hDlg, OPT_SampleChannel,   EM_SETBKGNDCOLOR, 0, cbc);\r
1432         SendDlgItemMessage(hDlg, OPT_SampleKibitz,    EM_SETBKGNDCOLOR, 0, cbc);\r
1433         SendDlgItemMessage(hDlg, OPT_SampleTell,      EM_SETBKGNDCOLOR, 0, cbc);\r
1434         SendDlgItemMessage(hDlg, OPT_SampleChallenge, EM_SETBKGNDCOLOR, 0, cbc);\r
1435         SendDlgItemMessage(hDlg, OPT_SampleRequest,   EM_SETBKGNDCOLOR, 0, cbc);\r
1436         SendDlgItemMessage(hDlg, OPT_SampleSeek,      EM_SETBKGNDCOLOR, 0, cbc);\r
1437         SendDlgItemMessage(hDlg, OPT_SampleNormal,    EM_SETBKGNDCOLOR, 0, cbc);\r
1438       }\r
1439       break;\r
1440 \r
1441     case OPT_DefaultColors:\r
1442       for (i=0; i < NColorClasses - 1; i++)\r
1443         ParseAttribs(&mca[i].color,\r
1444                      &mca[i].effects,\r
1445                      defaultTextAttribs[i]);\r
1446 \r
1447       cbc = ParseColorName(COLOR_BKGD);\r
1448       SendDlgItemMessage(hDlg, OPT_SampleShout,     EM_SETBKGNDCOLOR, 0, cbc);\r
1449       SendDlgItemMessage(hDlg, OPT_SampleSShout,    EM_SETBKGNDCOLOR, 0, cbc);\r
1450       SendDlgItemMessage(hDlg, OPT_SampleChannel1,  EM_SETBKGNDCOLOR, 0, cbc);\r
1451       SendDlgItemMessage(hDlg, OPT_SampleChannel,   EM_SETBKGNDCOLOR, 0, cbc);\r
1452       SendDlgItemMessage(hDlg, OPT_SampleKibitz,    EM_SETBKGNDCOLOR, 0, cbc);\r
1453       SendDlgItemMessage(hDlg, OPT_SampleTell,      EM_SETBKGNDCOLOR, 0, cbc);\r
1454       SendDlgItemMessage(hDlg, OPT_SampleChallenge, EM_SETBKGNDCOLOR, 0, cbc);\r
1455       SendDlgItemMessage(hDlg, OPT_SampleRequest,   EM_SETBKGNDCOLOR, 0, cbc);\r
1456       SendDlgItemMessage(hDlg, OPT_SampleSeek,      EM_SETBKGNDCOLOR, 0, cbc);\r
1457       SendDlgItemMessage(hDlg, OPT_SampleNormal,    EM_SETBKGNDCOLOR, 0, cbc);\r
1458 \r
1459       UpdateSampleText(hDlg, OPT_SampleShout,     &mca[ColorShout]);\r
1460       UpdateSampleText(hDlg, OPT_SampleSShout,    &mca[ColorSShout]);\r
1461       UpdateSampleText(hDlg, OPT_SampleChannel1,  &mca[ColorChannel1]);\r
1462       UpdateSampleText(hDlg, OPT_SampleChannel,   &mca[ColorChannel]);\r
1463       UpdateSampleText(hDlg, OPT_SampleKibitz,    &mca[ColorKibitz]);\r
1464       UpdateSampleText(hDlg, OPT_SampleTell,      &mca[ColorTell]);\r
1465       UpdateSampleText(hDlg, OPT_SampleChallenge, &mca[ColorChallenge]);\r
1466       UpdateSampleText(hDlg, OPT_SampleRequest,   &mca[ColorRequest]);\r
1467       UpdateSampleText(hDlg, OPT_SampleSeek,      &mca[ColorSeek]);\r
1468       UpdateSampleText(hDlg, OPT_SampleNormal,    &mca[ColorNormal]);\r
1469       break;\r
1470 \r
1471     default:\r
1472       SetIcsOptionEnables(hDlg);\r
1473       break;\r
1474     }\r
1475     break;\r
1476   }\r
1477   return FALSE;\r
1478 }\r
1479 \r
1480 VOID\r
1481 IcsOptionsPopup(HWND hwnd)\r
1482 {\r
1483   FARPROC lpProc = MakeProcInstance((FARPROC)IcsOptionsDialog, hInst);\r
1484   DialogBox(hInst, MAKEINTRESOURCE(DLG_IcsOptions), hwnd,\r
1485             (DLGPROC) lpProc);\r
1486   FreeProcInstance(lpProc);\r
1487 }\r
1488 \r
1489 /*---------------------------------------------------------------------------*\\r
1490  *\r
1491  * Fonts Dialog functions\r
1492  *\r
1493 \*---------------------------------------------------------------------------*/\r
1494 \r
1495 char *string; // sorry\r
1496 \r
1497 VOID\r
1498 SetSampleFontText(HWND hwnd, int id, const MyFont *mf)\r
1499 {\r
1500   char buf[MSG_SIZ];\r
1501   HWND hControl;\r
1502   HDC hdc;\r
1503   CHARFORMAT cf;\r
1504   SIZE size;\r
1505   RECT rectClient, rectFormat;\r
1506   HFONT oldFont;\r
1507   POINT center;\r
1508   int len;\r
1509 \r
1510   len = snprintf(buf, MSG_SIZ, "%.0f pt. %s%s%s\n",\r
1511                  mf->mfp.pointSize, mf->mfp.faceName,\r
1512                  mf->mfp.bold ? " bold" : "",\r
1513                  mf->mfp.italic ? " italic" : "");\r
1514  if(id != OPT_SamplePieceFont)\r
1515   SetDlgItemText(hwnd, id, buf);\r
1516  else SetDlgItemText(hwnd, id, string);\r
1517 \r
1518   hControl = GetDlgItem(hwnd, id);\r
1519   hdc = GetDC(hControl);\r
1520   SetMapMode(hdc, MM_TEXT);     /* 1 pixel == 1 logical unit */\r
1521   oldFont = SelectObject(hdc, mf->hf);\r
1522 \r
1523   /* get number of logical units necessary to display font name */\r
1524   GetTextExtentPoint32(hdc, buf, len, &size);\r
1525 \r
1526   /* calculate formatting rectangle in the rich edit control.\r
1527    * May be larger or smaller than the actual control.\r
1528    */\r
1529   GetClientRect(hControl, &rectClient);\r
1530   center.x = (rectClient.left + rectClient.right) / 2;\r
1531   center.y = (rectClient.top  + rectClient.bottom) / 2;\r
1532   rectFormat.top    = center.y - (size.cy / 2) - 1;\r
1533   rectFormat.bottom = center.y + (size.cy / 2) + 1;\r
1534   rectFormat.left   = center.x - (size.cx / 2) - 1;\r
1535   rectFormat.right  = center.x + (size.cx / 2) + 1;\r
1536 \r
1537   cf.cbSize = sizeof(CHARFORMAT);\r
1538   cf.dwMask = CFM_FACE|CFM_SIZE|CFM_CHARSET|CFM_BOLD|CFM_ITALIC;\r
1539   cf.dwEffects = 0;\r
1540   if (mf->lf.lfWeight == FW_BOLD) cf.dwEffects |= CFE_BOLD;\r
1541   if (mf->lf.lfItalic) cf.dwEffects |= CFE_ITALIC;\r
1542   safeStrCpy(cf.szFaceName, mf->mfp.faceName, sizeof(cf.szFaceName)/sizeof(cf.szFaceName[0]) );\r
1543   /*\r
1544    * yHeight is expressed in twips.  A twip is 1/20 of a font's point\r
1545    * size. See documentation of CHARFORMAT.  --msw\r
1546    */\r
1547   cf.yHeight = (int)(mf->mfp.pointSize * 20.0 + 0.5);\r
1548   cf.bCharSet = mf->lf.lfCharSet;\r
1549   cf.bPitchAndFamily = mf->lf.lfPitchAndFamily;\r
1550 \r
1551   /* format the text in the rich edit control */\r
1552   SendMessage(hControl, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &cf);\r
1553  if(id != OPT_SamplePieceFont)\r
1554   SendMessage(hControl, EM_SETRECT, (WPARAM)0, (LPARAM) &rectFormat);\r
1555 \r
1556   /* clean up */\r
1557   SelectObject(hdc, oldFont);\r
1558   ReleaseDC(hControl, hdc);\r
1559 }\r
1560 \r
1561 VOID\r
1562 CopyFont(MyFont *dest, const MyFont *src)\r
1563 {\r
1564   dest->mfp.pointSize = src->mfp.pointSize;\r
1565   dest->mfp.bold      = src->mfp.bold;\r
1566   dest->mfp.italic    = src->mfp.italic;\r
1567   dest->mfp.underline = src->mfp.underline;\r
1568   dest->mfp.strikeout = src->mfp.strikeout;\r
1569   dest->mfp.charset   = src->mfp.charset;\r
1570   safeStrCpy(dest->mfp.faceName, src->mfp.faceName, sizeof(dest->mfp.faceName)/sizeof(dest->mfp.faceName[0]) );\r
1571   CreateFontInMF(dest);\r
1572 }\r
1573 \r
1574 \r
1575 LRESULT CALLBACK\r
1576 FontOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
1577 {\r
1578   static MyFont workFont[NUM_FONTS+1];\r
1579   static BOOL firstPaint;\r
1580   static char pieceText[] = "ABCDEFGHIJKLMNOPQRSTUVWXZabcdefghijklmnopqrstuvwxyz";\r
1581   int i;\r
1582   RECT rect;\r
1583 \r
1584   switch (message) {\r
1585   case WM_INITDIALOG:\r
1586 \r
1587     /* copy the current font settings into a working copy */\r
1588     for (i=0; i < NUM_FONTS; i++)\r
1589       CopyFont(&workFont[i], font[boardSize][i]);\r
1590     strncpy(workFont[NUM_FONTS].mfp.faceName, appData.renderPiecesWithFont, sizeof(workFont[NUM_FONTS].mfp.faceName));\r
1591     workFont[NUM_FONTS].mfp.pointSize = 16.;\r
1592     workFont[NUM_FONTS].mfp.charset = DEFAULT_CHARSET;\r
1593 \r
1594     Translate(hDlg, DLG_Fonts);\r
1595     if (!appData.icsActive)\r
1596       EnableWindow(GetDlgItem(hDlg, OPT_ChooseConsoleFont), FALSE);\r
1597 \r
1598     firstPaint = TRUE;  /* see rant below */\r
1599 \r
1600     /* If I don't call SetFocus(), the dialog won't respond to the keyboard\r
1601      * when first drawn. Why is this the only dialog that behaves this way? Is\r
1602      * is the WM_PAINT stuff below?? Sigh...\r
1603      */\r
1604     SetFocus(GetDlgItem(hDlg, IDOK));\r
1605     break;\r
1606 \r
1607   case WM_PAINT:\r
1608     /* This should not be necessary. However, if SetSampleFontText() is called\r
1609      * in response to WM_INITDIALOG, the strings are not properly centered in\r
1610      * the controls when the dialog first appears. I can't figure out why, so\r
1611      * this is the workaround.  --msw\r
1612      */\r
1613     if (firstPaint) {\r
1614       SetSampleFontText(hDlg, OPT_SampleClockFont, &workFont[CLOCK_FONT]);\r
1615       SetSampleFontText(hDlg, OPT_SampleMessageFont, &workFont[MESSAGE_FONT]);\r
1616       SetSampleFontText(hDlg, OPT_SampleCoordFont, &workFont[COORD_FONT]);\r
1617       SetSampleFontText(hDlg, OPT_SampleTagFont, &workFont[EDITTAGS_FONT]);\r
1618       SetSampleFontText(hDlg, OPT_SampleCommentsFont, &workFont[COMMENT_FONT]);\r
1619       SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]);\r
1620       SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]);\r
1621       SetSampleFontText(hDlg, OPT_SampleGameListFont, &workFont[GAMELIST_FONT]);\r
1622       string = appData.fontToPieceTable;\r
1623       SetSampleFontText(hDlg, OPT_SamplePieceFont, &workFont[NUM_FONTS]);\r
1624       firstPaint = FALSE;\r
1625     }\r
1626     break;\r
1627 \r
1628   case WM_COMMAND: /* message: received a command */\r
1629     switch (LOWORD(wParam)) {\r
1630 \r
1631     case IDOK:\r
1632       /* again, it seems to avoid redraw problems if we call EndDialog first */\r
1633       EndDialog(hDlg, FALSE);\r
1634 \r
1635       /* copy modified settings back to the fonts array */\r
1636       for (i=0; i < NUM_FONTS; i++)\r
1637         CopyFont(font[boardSize][i], &workFont[i]);\r
1638 \r
1639       { // Make new piece-to-char table\r
1640         char buf[MSG_SIZ];\r
1641         GetDlgItemText(hDlg, OPT_SamplePieceFont, buf, MSG_SIZ);\r
1642         ASSIGN(appData.fontToPieceTable, buf);\r
1643       }\r
1644       ASSIGN(appData.renderPiecesWithFont, workFont[NUM_FONTS].mfp.faceName); // piece font\r
1645 \r
1646       /* a sad necessity due to the original design of having a separate\r
1647        * console font, tags font, and comment font for each board size.  IMHO\r
1648        * these fonts should not be dependent on the current board size.  I'm\r
1649        * running out of time, so I am doing this hack rather than redesign the\r
1650        * data structure. Besides, I think if I redesigned the data structure, I\r
1651        * might break backwards compatibility with old winboard.ini files.\r
1652        * --msw\r
1653        */\r
1654       for (i=0; i < NUM_SIZES; i++) {\r
1655         CopyFont(font[i][EDITTAGS_FONT], &workFont[EDITTAGS_FONT]);\r
1656         CopyFont(font[i][CONSOLE_FONT],  &workFont[CONSOLE_FONT]);\r
1657         CopyFont(font[i][COMMENT_FONT],  &workFont[COMMENT_FONT]);\r
1658         CopyFont(font[i][MOVEHISTORY_FONT],  &workFont[MOVEHISTORY_FONT]);\r
1659         CopyFont(font[i][GAMELIST_FONT],  &workFont[GAMELIST_FONT]);\r
1660       }\r
1661       /* end sad necessity */\r
1662 \r
1663       InitDrawingSizes(boardSize, 0);\r
1664       InvalidateRect(hwndMain, NULL, TRUE);\r
1665 \r
1666       if (commentDialog) {\r
1667         SendDlgItemMessage(commentDialog, OPT_CommentText,\r
1668           WM_SETFONT, (WPARAM)font[boardSize][COMMENT_FONT]->hf,\r
1669           MAKELPARAM(TRUE, 0));\r
1670         GetClientRect(GetDlgItem(commentDialog, OPT_CommentText), &rect);\r
1671         InvalidateRect(commentDialog, &rect, TRUE);\r
1672       }\r
1673 \r
1674       if (editTagsDialog) {\r
1675         SendDlgItemMessage(editTagsDialog, OPT_TagsText,\r
1676           WM_SETFONT, (WPARAM)font[boardSize][EDITTAGS_FONT]->hf,\r
1677           MAKELPARAM(TRUE, 0));\r
1678         GetClientRect(GetDlgItem(editTagsDialog, OPT_TagsText), &rect);\r
1679         InvalidateRect(editTagsDialog, &rect, TRUE);\r
1680       }\r
1681 \r
1682       if( moveHistoryDialog != NULL ) {\r
1683         SendDlgItemMessage(moveHistoryDialog, IDC_MoveHistory,\r
1684           WM_SETFONT, (WPARAM)font[boardSize][MOVEHISTORY_FONT]->hf,\r
1685           MAKELPARAM(TRUE, 0));\r
1686         SendMessage( moveHistoryDialog, WM_INITDIALOG, 0, 0 );\r
1687 //      InvalidateRect(editTagsDialog, NULL, TRUE); // [HGM] this ws improperly cloned?\r
1688       }\r
1689 \r
1690       if( engineOutputDialog != NULL ) {\r
1691         SendDlgItemMessage(engineOutputDialog, IDC_EngineMemo1,\r
1692           WM_SETFONT, (WPARAM)font[boardSize][MOVEHISTORY_FONT]->hf,\r
1693           MAKELPARAM(TRUE, 0));\r
1694         SendDlgItemMessage(engineOutputDialog, IDC_EngineMemo2,\r
1695           WM_SETFONT, (WPARAM)font[boardSize][MOVEHISTORY_FONT]->hf,\r
1696           MAKELPARAM(TRUE, 0));\r
1697       }\r
1698 \r
1699       if (hwndConsole) {\r
1700         ChangedConsoleFont();\r
1701       }\r
1702 \r
1703       for (i=0; i<NUM_FONTS; i++)\r
1704         DeleteObject(&workFont[i].hf);\r
1705 \r
1706       return TRUE;\r
1707 \r
1708     case IDCANCEL:\r
1709       for (i=0; i<NUM_FONTS; i++)\r
1710         DeleteObject(&workFont[i].hf);\r
1711       EndDialog(hDlg, FALSE);\r
1712       return TRUE;\r
1713 \r
1714     case OPT_ChooseClockFont:\r
1715       MyCreateFont(hDlg, &workFont[CLOCK_FONT]);\r
1716       SetSampleFontText(hDlg, OPT_SampleClockFont, &workFont[CLOCK_FONT]);\r
1717       break;\r
1718 \r
1719     case OPT_ChooseMessageFont:\r
1720       MyCreateFont(hDlg, &workFont[MESSAGE_FONT]);\r
1721       SetSampleFontText(hDlg, OPT_SampleMessageFont, &workFont[MESSAGE_FONT]);\r
1722       break;\r
1723 \r
1724     case OPT_ChooseCoordFont:\r
1725       MyCreateFont(hDlg, &workFont[COORD_FONT]);\r
1726       SetSampleFontText(hDlg, OPT_SampleCoordFont, &workFont[COORD_FONT]);\r
1727       break;\r
1728 \r
1729     case OPT_ChooseTagFont:\r
1730       MyCreateFont(hDlg, &workFont[EDITTAGS_FONT]);\r
1731       SetSampleFontText(hDlg, OPT_SampleTagFont, &workFont[EDITTAGS_FONT]);\r
1732       break;\r
1733 \r
1734     case OPT_ChooseCommentsFont:\r
1735       MyCreateFont(hDlg, &workFont[COMMENT_FONT]);\r
1736       SetSampleFontText(hDlg, OPT_SampleCommentsFont, &workFont[COMMENT_FONT]);\r
1737       break;\r
1738 \r
1739     case OPT_ChooseConsoleFont:\r
1740       MyCreateFont(hDlg, &workFont[CONSOLE_FONT]);\r
1741       SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]);\r
1742       break;\r
1743 \r
1744     case OPT_ChooseMoveHistoryFont:\r
1745       MyCreateFont(hDlg, &workFont[MOVEHISTORY_FONT]);\r
1746       SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]);\r
1747       break;\r
1748 \r
1749     case OPT_ChooseGameListFont:\r
1750       MyCreateFont(hDlg, &workFont[GAMELIST_FONT]);\r
1751       SetSampleFontText(hDlg, OPT_SampleGameListFont, &workFont[GAMELIST_FONT]);\r
1752       break;\r
1753 \r
1754     case OPT_ChoosePieceFont:\r
1755       MyCreateFont(hDlg, &workFont[NUM_FONTS]);\r
1756       string = pieceText;\r
1757       SetSampleFontText(hDlg, OPT_SamplePieceFont, &workFont[NUM_FONTS]);\r
1758       break;\r
1759 \r
1760     case OPT_DefaultFonts:\r
1761       for (i=0; i<NUM_FONTS; i++) {\r
1762         DeleteObject(&workFont[i].hf);\r
1763         ParseFontName(font[boardSize][i]->def, &workFont[i].mfp);\r
1764         CreateFontInMF(&workFont[i]);\r
1765       }\r
1766       SetSampleFontText(hDlg, OPT_SampleClockFont, &workFont[CLOCK_FONT]);\r
1767       SetSampleFontText(hDlg, OPT_SampleMessageFont, &workFont[MESSAGE_FONT]);\r
1768       SetSampleFontText(hDlg, OPT_SampleCoordFont, &workFont[COORD_FONT]);\r
1769       SetSampleFontText(hDlg, OPT_SampleTagFont, &workFont[EDITTAGS_FONT]);\r
1770       SetSampleFontText(hDlg, OPT_SampleCommentsFont, &workFont[COMMENT_FONT]);\r
1771       SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]);\r
1772       SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]);\r
1773       SetSampleFontText(hDlg, OPT_SampleGameListFont, &workFont[GAMELIST_FONT]);\r
1774       break;\r
1775     }\r
1776   }\r
1777   return FALSE;\r
1778 }\r
1779 \r
1780 VOID\r
1781 FontsOptionsPopup(HWND hwnd)\r
1782 {\r
1783   FARPROC lpProc = MakeProcInstance((FARPROC)FontOptionsDialog, hInst);\r
1784   DialogBox(hInst, MAKEINTRESOURCE(DLG_Fonts), hwnd,\r
1785           (DLGPROC) lpProc);\r
1786   FreeProcInstance(lpProc);\r
1787 }\r
1788 \r
1789 /*---------------------------------------------------------------------------*\\r
1790  *\r
1791  * Sounds Dialog functions\r
1792  *\r
1793 \*---------------------------------------------------------------------------*/\r
1794 \r
1795 \r
1796 SoundComboData soundComboData[] = {\r
1797   {N_("Move"), NULL},\r
1798   {N_("Bell"), NULL},\r
1799   {N_("ICS Alarm"), NULL},\r
1800   {N_("ICS Win"), NULL},\r
1801   {N_("ICS Loss"), NULL},\r
1802   {N_("ICS Draw"), NULL},\r
1803   {N_("ICS Unfinished"), NULL},\r
1804   {N_("Shout"), NULL},\r
1805   {N_("SShout/CShout"), NULL},\r
1806   {N_("Channel 1"), NULL},\r
1807   {N_("Channel"), NULL},\r
1808   {N_("Kibitz"), NULL},\r
1809   {N_("Tell"), NULL},\r
1810   {N_("Challenge"), NULL},\r
1811   {N_("Request"), NULL},\r
1812   {N_("Seek"), NULL},\r
1813   {NULL, NULL},\r
1814 };\r
1815 \r
1816 \r
1817 void\r
1818 InitSoundComboData(SoundComboData *scd)\r
1819 {\r
1820   SoundClass sc;\r
1821   ColorClass cc;\r
1822   int index;\r
1823 \r
1824   /* copy current sound settings to combo array */\r
1825 \r
1826   for ( sc = (SoundClass)0; sc < NSoundClasses; sc++) {\r
1827     scd[sc].name = strdup(sounds[sc].name);\r
1828   }\r
1829   for ( cc = (ColorClass)0; cc < NColorClasses - 2; cc++) {\r
1830     index = (int)cc + (int)NSoundClasses;\r
1831     scd[index].name = strdup(textAttribs[cc].sound.name);\r
1832   }\r
1833 }\r
1834 \r
1835 \r
1836 void\r
1837 ResetSoundComboData(SoundComboData *scd)\r
1838 {\r
1839   while (scd->label) {\r
1840     if (scd->name != NULL) {\r
1841       free (scd->name);\r
1842       scd->name = NULL;\r
1843     }\r
1844     scd++;\r
1845   }\r
1846 }\r
1847 \r
1848 void\r
1849 InitSoundCombo(HWND hwndCombo, SoundComboData *scd)\r
1850 {\r
1851   char buf[255];\r
1852   DWORD err;\r
1853   DWORD cnt = 0;\r
1854   SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0);\r
1855 \r
1856   /* send the labels to the combo box */\r
1857   while (scd->label) {\r
1858     err = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) T_(scd->label));\r
1859     if (err != cnt++) {\r
1860       snprintf(buf, MSG_SIZ,  "InitSoundCombo(): err '%d', cnt '%d'\n",\r
1861           (int)err, (int)cnt);\r
1862       MessageBox(NULL, buf, NULL, MB_OK);\r
1863     }\r
1864     scd++;\r
1865   }\r
1866   SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
1867 }\r
1868 \r
1869 int\r
1870 SoundDialogWhichRadio(HWND hDlg)\r
1871 {\r
1872   if (IsDlgButtonChecked(hDlg, OPT_NoSound)) return OPT_NoSound;\r
1873   if (IsDlgButtonChecked(hDlg, OPT_DefaultBeep)) return OPT_DefaultBeep;\r
1874   if (IsDlgButtonChecked(hDlg, OPT_BuiltInSound)) return OPT_BuiltInSound;\r
1875   if (IsDlgButtonChecked(hDlg, OPT_WavFile)) return OPT_WavFile;\r
1876   return -1;\r
1877 }\r
1878 \r
1879 VOID\r
1880 SoundDialogSetEnables(HWND hDlg, int radio)\r
1881 {\r
1882   EnableWindow(GetDlgItem(hDlg, OPT_BuiltInSoundName),\r
1883                radio == OPT_BuiltInSound);\r
1884   EnableWindow(GetDlgItem(hDlg, OPT_WavFileName), radio == OPT_WavFile);\r
1885   EnableWindow(GetDlgItem(hDlg, OPT_BrowseSound), radio == OPT_WavFile);\r
1886 }\r
1887 \r
1888 char *\r
1889 SoundDialogGetName(HWND hDlg, int radio)\r
1890 {\r
1891   static char buf[MSG_SIZ], buf2[MSG_SIZ], buf3[MSG_SIZ];\r
1892   char *dummy, *ret;\r
1893   switch (radio) {\r
1894   case OPT_NoSound:\r
1895   default:\r
1896     return "";\r
1897   case OPT_DefaultBeep:\r
1898     return "$";\r
1899   case OPT_BuiltInSound:\r
1900     buf[0] = '!';\r
1901     GetDlgItemText(hDlg, OPT_BuiltInSoundName, buf + 1, sizeof(buf) - 1);\r
1902     return buf;\r
1903   case OPT_WavFile:\r
1904     GetDlgItemText(hDlg, OPT_WavFileName, buf, sizeof(buf));\r
1905     GetCurrentDirectory(MSG_SIZ, buf3);\r
1906     SetCurrentDirectory(installDir);\r
1907     if (GetFullPathName(buf, MSG_SIZ, buf2, &dummy)) {\r
1908       ret = buf2;\r
1909     } else {\r
1910       ret = buf;\r
1911     }\r
1912     SetCurrentDirectory(buf3);\r
1913     return ret;\r
1914   }\r
1915 }\r
1916 \r
1917 void\r
1918 DisplaySelectedSound(HWND hDlg, HWND hCombo, const char *name)\r
1919 {\r
1920   int radio;\r
1921   /*\r
1922    * I think it's best to clear the combo and edit boxes. It looks stupid\r
1923    * to have a value from another sound event sitting there grayed out.\r
1924    */\r
1925   SetDlgItemText(hDlg, OPT_WavFileName, "");\r
1926   SendMessage(hCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);\r
1927 \r
1928   if (appData.debugMode)\r
1929       fprintf(debugFP, "DisplaySelectedSound(,,'%s'):\n", name);\r
1930   switch (name[0]) {\r
1931   case NULLCHAR:\r
1932     radio = OPT_NoSound;\r
1933     break;\r
1934   case '$':\r
1935     if (name[1] == NULLCHAR) {\r
1936       radio = OPT_DefaultBeep;\r
1937     } else {\r
1938       radio = OPT_WavFile;\r
1939       SetDlgItemText(hDlg, OPT_WavFileName, name);\r
1940     }\r
1941     break;\r
1942   case '!':\r
1943     if (name[1] == NULLCHAR) {\r
1944       radio = OPT_NoSound;\r
1945     } else {\r
1946       radio = OPT_BuiltInSound;\r
1947       if (SendMessage(hCombo, CB_SELECTSTRING, (WPARAM) -1,\r
1948                       (LPARAM) (name + 1)) == CB_ERR) {\r
1949         SendMessage(hCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);\r
1950         SendMessage(hCombo, WM_SETTEXT, (WPARAM) 0, (LPARAM) (name + 1));\r
1951       }\r
1952     }\r
1953     break;\r
1954   default:\r
1955     radio = OPT_WavFile;\r
1956     SetDlgItemText(hDlg, OPT_WavFileName, name);\r
1957     break;\r
1958   }\r
1959   SoundDialogSetEnables(hDlg, radio);\r
1960   CheckRadioButton(hDlg, OPT_NoSound, OPT_WavFile, radio);\r
1961 }\r
1962 \r
1963 \r
1964 char *builtInSoundNames[] = BUILT_IN_SOUND_NAMES;\r
1965 \r
1966 LRESULT CALLBACK\r
1967 SoundOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
1968 {\r
1969   static HWND hSoundCombo;\r
1970   static DWORD index;\r
1971   static HWND hBISN;\r
1972   int radio;\r
1973   MySound tmp;\r
1974   FILE *f;\r
1975   char buf[MSG_SIZ];\r
1976   char *newName;\r
1977   SoundClass sc;\r
1978   ColorClass cc;\r
1979   SoundComboData *scd;\r
1980   int oldMute;\r
1981 \r
1982   switch (message) {\r
1983   case WM_INITDIALOG:\r
1984     /* Center the dialog over the application window */\r
1985     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
1986     Translate(hDlg, DLG_Sound);\r
1987 \r
1988     /* Initialize the built-in sounds combo */\r
1989     hBISN = GetDlgItem(hDlg, OPT_BuiltInSoundName);\r
1990      InitComboStrings(hBISN, builtInSoundNames);\r
1991 \r
1992     /* Initialize the  sound events combo */\r
1993     index = 0;\r
1994     InitSoundComboData(soundComboData);\r
1995     hSoundCombo = GetDlgItem(hDlg, CBO_Sounds);\r
1996     InitSoundCombo(hSoundCombo, soundComboData);\r
1997 \r
1998     /* update the dialog */\r
1999     DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name);\r
2000     return TRUE;\r
2001 \r
2002   case WM_COMMAND: /* message: received a command */\r
2003 \r
2004     if (((HWND)lParam == hSoundCombo) &&\r
2005         (HIWORD(wParam) == CBN_SELCHANGE)) {\r
2006       /*\r
2007        * the user has selected a new sound event. We must store the name for\r
2008        * the previously selected event, then retrieve the name for the\r
2009        * newly selected event and update the dialog.\r
2010        */\r
2011       radio = SoundDialogWhichRadio(hDlg);\r
2012       newName = strdup(SoundDialogGetName(hDlg, radio));\r
2013 \r
2014       if (strcmp(newName, soundComboData[index].name) != 0) {\r
2015         free(soundComboData[index].name);\r
2016         soundComboData[index].name = newName;\r
2017       } else {\r
2018         free(newName);\r
2019         newName = NULL;\r
2020       }\r
2021       /* now get the settings for the newly selected event */\r
2022       index = SendMessage(hSoundCombo, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);\r
2023       DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name);\r
2024 \r
2025       return TRUE;\r
2026     }\r
2027     switch (LOWORD(wParam)) {\r
2028     case IDOK:\r
2029       /*\r
2030        * save the name for the currently selected sound event\r
2031        */\r
2032       radio = SoundDialogWhichRadio(hDlg);\r
2033       newName = strdup(SoundDialogGetName(hDlg, radio));\r
2034 \r
2035       if (strcmp(soundComboData[index].name, newName) != 0) {\r
2036         free(soundComboData[index].name);\r
2037         soundComboData[index].name = newName;\r
2038       } else {\r
2039         free(newName);\r
2040         newName = NULL;\r
2041       }\r
2042 \r
2043       /* save all the sound names that changed and load the sounds */\r
2044 \r
2045       for ( sc = (SoundClass)0; sc < NSoundClasses; sc++) {\r
2046         if (strcmp(soundComboData[sc].name, sounds[sc].name) != 0) {\r
2047           free(sounds[sc].name);\r
2048           sounds[sc].name = strdup(soundComboData[sc].name);\r
2049           MyLoadSound(&sounds[sc]);\r
2050         }\r
2051       }\r
2052       for ( cc = (ColorClass)0; cc < NColorClasses - 2; cc++) {\r
2053         index = (int)cc + (int)NSoundClasses;\r
2054         if (strcmp(soundComboData[index].name,\r
2055                    textAttribs[cc].sound.name) != 0) {\r
2056           free(textAttribs[cc].sound.name);\r
2057           textAttribs[cc].sound.name = strdup(soundComboData[index].name);\r
2058           MyLoadSound(&textAttribs[cc].sound);\r
2059         }\r
2060       }\r
2061 \r
2062         mute = FALSE; // [HGM] mute: switch sounds automatically on if we select one\r
2063       CheckMenuItem(GetMenu(hwndMain),IDM_MuteSounds,MF_BYCOMMAND|MF_UNCHECKED);\r
2064       ResetSoundComboData(soundComboData);\r
2065       EndDialog(hDlg, TRUE);\r
2066       return TRUE;\r
2067 \r
2068     case IDCANCEL:\r
2069       ResetSoundComboData(soundComboData);\r
2070       EndDialog(hDlg, FALSE);\r
2071       return TRUE;\r
2072 \r
2073     case OPT_DefaultSounds:\r
2074       /* can't use SetDefaultSounds() because we need to be able to "undo" if\r
2075        * user selects "Cancel" later on. So we do it the hard way here.\r
2076        */\r
2077       scd = &soundComboData[0];\r
2078       while (scd->label != NULL) {\r
2079         if (scd->name != NULL) free(scd->name);\r
2080         scd->name = strdup("");\r
2081         scd++;\r
2082       }\r
2083       free(soundComboData[(int)SoundBell].name);\r
2084       soundComboData[(int)SoundBell].name = strdup(SOUND_BELL);\r
2085       DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name);\r
2086       break;\r
2087 \r
2088     case OPT_PlaySound:\r
2089       radio = SoundDialogWhichRadio(hDlg);\r
2090       tmp.name = strdup(SoundDialogGetName(hDlg, radio));\r
2091       tmp.data = NULL;\r
2092       MyLoadSound(&tmp);\r
2093         oldMute = mute; mute = FALSE; // [HGM] mute: always sound when user presses play, ignorig mute setting\r
2094       MyPlaySound(&tmp);\r
2095         mute = oldMute;\r
2096       if (tmp.data  != NULL) FreeResource(tmp.data); // technically obsolete fn, but tmp.data is NOT malloc'd mem\r
2097       if (tmp.name != NULL) free(tmp.name);\r
2098       return TRUE;\r
2099 \r
2100     case OPT_BrowseSound:\r
2101       f = OpenFileDialog(hDlg, "rb", NULL, "wav", SOUND_FILT,\r
2102         _("Browse for Sound File"), NULL, NULL, buf);\r
2103       if (f != NULL) {\r
2104         fclose(f);\r
2105         SetDlgItemText(hDlg, OPT_WavFileName, buf);\r
2106       }\r
2107       return TRUE;\r
2108 \r
2109     default:\r
2110       radio = SoundDialogWhichRadio(hDlg);\r
2111       SoundDialogSetEnables(hDlg, radio);\r
2112       break;\r
2113     }\r
2114     break;\r
2115   }\r
2116   return FALSE;\r
2117 }\r
2118 \r
2119 \r
2120 VOID SoundOptionsPopup(HWND hwnd)\r
2121 {\r
2122   FARPROC lpProc;\r
2123 \r
2124   lpProc = MakeProcInstance((FARPROC)SoundOptionsDialog, hInst);\r
2125   DialogBox(hInst, MAKEINTRESOURCE(DLG_Sound), hwnd, (DLGPROC)lpProc);\r
2126   FreeProcInstance(lpProc);\r
2127 }\r
2128 \r
2129 \r
2130 /*---------------------------------------------------------------------------*\\r
2131  *\r
2132  * Comm Port dialog functions\r
2133  *\r
2134 \*---------------------------------------------------------------------------*/\r
2135 \r
2136 \r
2137 #define FLOW_NONE   0\r
2138 #define FLOW_XOFF   1\r
2139 #define FLOW_CTS    2\r
2140 #define FLOW_DSR    3\r
2141 \r
2142 #define PORT_NONE\r
2143 \r
2144 ComboData cdPort[]     = { {"None", PORT_NONE}, {"COM1", 1}, {"COM2", 2},\r
2145                            {"COM3", 3}, {"COM4", 4}, {NULL, 0} };\r
2146 ComboData cdDataRate[] = { {"110", 110}, {"300", 300}, {"600", 600}, {"1200", 1200},\r
2147                            {"2400", 2400}, {"4800", 4800}, {"9600", 9600}, {"19200", 19200},\r
2148                            {"38400", 38400}, {NULL, 0} };\r
2149 ComboData cdDataBits[] = { {"5", 5}, {"6", 6}, {"7", 7}, {"8", 8}, {NULL, 0} };\r
2150 ComboData cdParity[]   = { {"None", NOPARITY}, {"Odd", ODDPARITY}, {"Even", EVENPARITY},\r
2151                            {"Mark", MARKPARITY}, {"Space", SPACEPARITY}, {NULL, 0} };\r
2152 ComboData cdStopBits[] = { {"1", ONESTOPBIT}, {"1.5", ONE5STOPBITS},\r
2153                            {"2", TWOSTOPBITS}, {NULL, 0} };\r
2154 ComboData cdFlow[]     = { {"None", FLOW_NONE}, {"Xoff/Xon", FLOW_XOFF}, {"CTS", FLOW_CTS},\r
2155                            {"DSR", FLOW_DSR}, {NULL, 0} };\r
2156 \r
2157 \r
2158 VOID\r
2159 ParseCommSettings(char *arg, DCB *dcb)\r
2160 {\r
2161   int dataRate, count;\r
2162   char bits[MSG_SIZ], parity[MSG_SIZ], stopBits[MSG_SIZ], flow[MSG_SIZ];\r
2163   ComboData *cd;\r
2164   count = sscanf(arg, "%d%*[, ]%[^, ]%*[, ]%[^, ]%*[, ]%[^, ]%*[, ]%[^, ]",\r
2165     &dataRate, bits, parity, stopBits, flow);\r
2166   if (count != 5) goto cant_parse;\r
2167   dcb->BaudRate = dataRate;\r
2168   cd = cdDataBits;\r
2169   while (cd->label != NULL) {\r
2170     if (StrCaseCmp(cd->label, bits) == 0) {\r
2171       dcb->ByteSize = cd->value;\r
2172       break;\r
2173     }\r
2174     cd++;\r
2175   }\r
2176   if (cd->label == NULL) goto cant_parse;\r
2177   cd = cdParity;\r
2178   while (cd->label != NULL) {\r
2179     if (StrCaseCmp(cd->label, parity) == 0) {\r
2180       dcb->Parity = cd->value;\r
2181       break;\r
2182     }\r
2183     cd++;\r
2184   }\r
2185   if (cd->label == NULL) goto cant_parse;\r
2186   cd = cdStopBits;\r
2187   while (cd->label != NULL) {\r
2188     if (StrCaseCmp(cd->label, stopBits) == 0) {\r
2189       dcb->StopBits = cd->value;\r
2190       break;\r
2191     }\r
2192     cd++;\r
2193   }\r
2194   cd = cdFlow;\r
2195   if (cd->label == NULL) goto cant_parse;\r
2196   while (cd->label != NULL) {\r
2197     if (StrCaseCmp(cd->label, flow) == 0) {\r
2198       switch (cd->value) {\r
2199       case FLOW_NONE:\r
2200         dcb->fOutX = FALSE;\r
2201         dcb->fOutxCtsFlow = FALSE;\r
2202         dcb->fOutxDsrFlow = FALSE;\r
2203         break;\r
2204       case FLOW_CTS:\r
2205         dcb->fOutX = FALSE;\r
2206         dcb->fOutxCtsFlow = TRUE;\r
2207         dcb->fOutxDsrFlow = FALSE;\r
2208         break;\r
2209       case FLOW_DSR:\r
2210         dcb->fOutX = FALSE;\r
2211         dcb->fOutxCtsFlow = FALSE;\r
2212         dcb->fOutxDsrFlow = TRUE;\r
2213         break;\r
2214       case FLOW_XOFF:\r
2215         dcb->fOutX = TRUE;\r
2216         dcb->fOutxCtsFlow = FALSE;\r
2217         dcb->fOutxDsrFlow = FALSE;\r
2218         break;\r
2219       }\r
2220       break;\r
2221     }\r
2222     cd++;\r
2223   }\r
2224   if (cd->label == NULL) goto cant_parse;\r
2225   return;\r
2226 cant_parse:\r
2227     ExitArgError(_("Can't parse com port settings"), arg, TRUE);\r
2228 }\r
2229 \r
2230 \r
2231 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb)\r
2232 {\r
2233   char *flow = "??", *parity = "??", *stopBits = "??";\r
2234   ComboData *cd;\r
2235 \r
2236   cd = cdParity;\r
2237   while (cd->label != NULL) {\r
2238     if (dcb->Parity == cd->value) {\r
2239       parity = cd->label;\r
2240       break;\r
2241     }\r
2242     cd++;\r
2243   }\r
2244   cd = cdStopBits;\r
2245   while (cd->label != NULL) {\r
2246     if (dcb->StopBits == cd->value) {\r
2247       stopBits = cd->label;\r
2248       break;\r
2249     }\r
2250     cd++;\r
2251   }\r
2252   if (dcb->fOutX) {\r
2253     flow = cdFlow[FLOW_XOFF].label;\r
2254   } else if (dcb->fOutxCtsFlow) {\r
2255     flow = cdFlow[FLOW_CTS].label;\r
2256   } else if (dcb->fOutxDsrFlow) {\r
2257     flow = cdFlow[FLOW_DSR].label;\r
2258   } else {\r
2259     flow = cdFlow[FLOW_NONE].label;\r
2260   }\r
2261   fprintf(f, "/%s=%d,%d,%s,%s,%s\n", name,\r
2262     (int)dcb->BaudRate, dcb->ByteSize, parity, stopBits, flow);\r
2263 }\r
2264 \r
2265 \r
2266 void\r
2267 InitCombo(HANDLE hwndCombo, ComboData *cd)\r
2268 {\r
2269   SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0);\r
2270 \r
2271   while (cd->label != NULL) {\r
2272     SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) cd->label);\r
2273     cd++;\r
2274   }\r
2275 }\r
2276 \r
2277 void\r
2278 SelectComboValue(HANDLE hwndCombo, ComboData *cd, unsigned value)\r
2279 {\r
2280   int i;\r
2281 \r
2282   i = 0;\r
2283   while (cd->label != NULL) {\r
2284     if (cd->value == value) {\r
2285       SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) i, (LPARAM) 0);\r
2286       return;\r
2287     }\r
2288     cd++;\r
2289     i++;\r
2290   }\r
2291 }\r
2292 \r
2293 LRESULT CALLBACK\r
2294 CommPortOptionsDialog(HWND hDlg, UINT message, WPARAM wParam,   LPARAM lParam)\r
2295 {\r
2296   char buf[MSG_SIZ];\r
2297   HANDLE hwndCombo;\r
2298   char *p;\r
2299   LRESULT index;\r
2300   unsigned value;\r
2301   int err;\r
2302 \r
2303   switch (message) {\r
2304   case WM_INITDIALOG: /* message: initialize dialog box */\r
2305     /* Center the dialog over the application window */\r
2306     CenterWindow (hDlg, GetWindow(hDlg, GW_OWNER));\r
2307     Translate(hDlg, DLG_CommPort);\r
2308     /* Initialize the dialog items */\r
2309     /* !! There should probably be some synchronization\r
2310        in accessing hCommPort and dcb.  Or does modal nature\r
2311        of this dialog box do it for us?\r
2312        */\r
2313     hwndCombo = GetDlgItem(hDlg, OPT_Port);\r
2314     InitCombo(hwndCombo, cdPort);\r
2315     p = strrchr(appData.icsCommPort, '\\');\r
2316     if (p++ == NULL) p = appData.icsCommPort;\r
2317     if ((*p == '\0') ||\r
2318         (SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) p) == CB_ERR)) {\r
2319       SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) "None");\r
2320     }\r
2321     EnableWindow(hwndCombo, hCommPort == NULL); /*!! don't allow change for now*/\r
2322 \r
2323     hwndCombo = GetDlgItem(hDlg, OPT_DataRate);\r
2324     InitCombo(hwndCombo, cdDataRate);\r
2325     snprintf(buf, MSG_SIZ, "%u", (int)dcb.BaudRate);\r
2326     if (SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) buf) == CB_ERR) {\r
2327       SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);\r
2328       SendMessage(hwndCombo, WM_SETTEXT, (WPARAM) 0, (LPARAM) buf);\r
2329     }\r
2330 \r
2331     hwndCombo = GetDlgItem(hDlg, OPT_Bits);\r
2332     InitCombo(hwndCombo, cdDataBits);\r
2333     SelectComboValue(hwndCombo, cdDataBits, dcb.ByteSize);\r
2334 \r
2335     hwndCombo = GetDlgItem(hDlg, OPT_Parity);\r
2336     InitCombo(hwndCombo, cdParity);\r
2337     SelectComboValue(hwndCombo, cdParity, dcb.Parity);\r
2338 \r
2339     hwndCombo = GetDlgItem(hDlg, OPT_StopBits);\r
2340     InitCombo(hwndCombo, cdStopBits);\r
2341     SelectComboValue(hwndCombo, cdStopBits, dcb.StopBits);\r
2342 \r
2343     hwndCombo = GetDlgItem(hDlg, OPT_Flow);\r
2344     InitCombo(hwndCombo, cdFlow);\r
2345     if (dcb.fOutX) {\r
2346       SelectComboValue(hwndCombo, cdFlow, FLOW_XOFF);\r
2347     } else if (dcb.fOutxCtsFlow) {\r
2348       SelectComboValue(hwndCombo, cdFlow, FLOW_CTS);\r
2349     } else if (dcb.fOutxDsrFlow) {\r
2350       SelectComboValue(hwndCombo, cdFlow, FLOW_DSR);\r
2351     } else {\r
2352       SelectComboValue(hwndCombo, cdFlow, FLOW_NONE);\r
2353     }\r
2354     return TRUE;\r
2355 \r
2356   case WM_COMMAND: /* message: received a command */\r
2357     switch (LOWORD(wParam)) {\r
2358     case IDOK:\r
2359       /* Read changed options from the dialog box */\r
2360 #ifdef NOTDEF\r
2361       /* !! Currently we can't change comm ports in midstream */\r
2362       hwndCombo = GetDlgItem(hDlg, OPT_Port);\r
2363       index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
2364       if (index == PORT_NONE) {\r
2365         appData.icsCommPort = "";\r
2366         if (hCommPort != NULL) {\r
2367           CloseHandle(hCommPort);\r
2368           hCommPort = NULL;\r
2369         }\r
2370         EndDialog(hDlg, TRUE);\r
2371         return TRUE;\r
2372       }\r
2373       SendMessage(hwndCombo, WM_GETTEXT, (WPARAM) MSG_SIZ, (LPARAM) buf);\r
2374       appData.icsCommPort = strdup(buf);\r
2375       if (hCommPort != NULL) {\r
2376         CloseHandle(hCommPort);\r
2377         hCommPort = NULL;\r
2378       }\r
2379       /* now what?? can't really do this; have to fix up the ChildProc\r
2380          and InputSource records for the comm port that we gave to the\r
2381          back end. */\r
2382 #endif /*NOTDEF*/\r
2383 \r
2384       hwndCombo = GetDlgItem(hDlg, OPT_DataRate);\r
2385       SendMessage(hwndCombo, WM_GETTEXT, (WPARAM) MSG_SIZ, (LPARAM) buf);\r
2386       if (sscanf(buf, "%u", &value) != 1) {\r
2387         MessageBox(hDlg, _("Invalid data rate"),\r
2388                    _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2389         return TRUE;\r
2390       }\r
2391       dcb.BaudRate = value;\r
2392 \r
2393       hwndCombo = GetDlgItem(hDlg, OPT_Bits);\r
2394       index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
2395       dcb.ByteSize = cdDataBits[index].value;\r
2396 \r
2397       hwndCombo = GetDlgItem(hDlg, OPT_Parity);\r
2398       index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
2399       dcb.Parity = cdParity[index].value;\r
2400 \r
2401       hwndCombo = GetDlgItem(hDlg, OPT_StopBits);\r
2402       index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
2403       dcb.StopBits = cdStopBits[index].value;\r
2404 \r
2405       hwndCombo = GetDlgItem(hDlg, OPT_Flow);\r
2406       index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
2407       switch (cdFlow[index].value) {\r
2408       case FLOW_NONE:\r
2409         dcb.fOutX = FALSE;\r
2410         dcb.fOutxCtsFlow = FALSE;\r
2411         dcb.fOutxDsrFlow = FALSE;\r
2412         break;\r
2413       case FLOW_CTS:\r
2414         dcb.fOutX = FALSE;\r
2415         dcb.fOutxCtsFlow = TRUE;\r
2416         dcb.fOutxDsrFlow = FALSE;\r
2417         break;\r
2418       case FLOW_DSR:\r
2419         dcb.fOutX = FALSE;\r
2420         dcb.fOutxCtsFlow = FALSE;\r
2421         dcb.fOutxDsrFlow = TRUE;\r
2422         break;\r
2423       case FLOW_XOFF:\r
2424         dcb.fOutX = TRUE;\r
2425         dcb.fOutxCtsFlow = FALSE;\r
2426         dcb.fOutxDsrFlow = FALSE;\r
2427         break;\r
2428       }\r
2429       if (!SetCommState(hCommPort, (LPDCB) &dcb)) {\r
2430         err = GetLastError();\r
2431         switch(MessageBox(hDlg,\r
2432                          "Failed to set comm port state;\r\ninvalid options?",\r
2433                          _("Option Error"), MB_ABORTRETRYIGNORE|MB_ICONQUESTION)) {\r
2434         case IDABORT:\r
2435           DisplayFatalError(_("Failed to set comm port state"), err, 1);\r
2436           exit(1);  /*is it ok to do this from here?*/\r
2437 \r
2438         case IDRETRY:\r
2439           return TRUE;\r
2440 \r
2441         case IDIGNORE:\r
2442           EndDialog(hDlg, TRUE);\r
2443           return TRUE;\r
2444         }\r
2445       }\r
2446 \r
2447       EndDialog(hDlg, TRUE);\r
2448       return TRUE;\r
2449 \r
2450     case IDCANCEL:\r
2451       EndDialog(hDlg, FALSE);\r
2452       return TRUE;\r
2453 \r
2454     default:\r
2455       break;\r
2456     }\r
2457     break;\r
2458   }\r
2459   return FALSE;\r
2460 }\r
2461 \r
2462 VOID\r
2463 CommPortOptionsPopup(HWND hwnd)\r
2464 {\r
2465   FARPROC lpProc = MakeProcInstance((FARPROC)CommPortOptionsDialog, hInst);\r
2466   DialogBox(hInst, MAKEINTRESOURCE(DLG_CommPort), hwnd, (DLGPROC) lpProc);\r
2467   FreeProcInstance(lpProc);\r
2468 }\r
2469 \r
2470 /*---------------------------------------------------------------------------*\\r
2471  *\r
2472  * Load Options dialog functions\r
2473  *\r
2474 \*---------------------------------------------------------------------------*/\r
2475 \r
2476 int\r
2477 LoadOptionsWhichRadio(HWND hDlg)\r
2478 {\r
2479   return (IsDlgButtonChecked(hDlg, OPT_Exact) ? 1 :\r
2480          (IsDlgButtonChecked(hDlg, OPT_Subset) ? 2 :\r
2481          (IsDlgButtonChecked(hDlg, OPT_Struct) ? 3 :\r
2482          (IsDlgButtonChecked(hDlg, OPT_Material) ? 4 :\r
2483          (IsDlgButtonChecked(hDlg, OPT_Range) ? 5 :\r
2484          (IsDlgButtonChecked(hDlg, OPT_Difference) ? 6 : -1))))));\r
2485 }\r
2486 \r
2487 VOID\r
2488 SetLoadOptionEnables(HWND hDlg)\r
2489 {\r
2490   UINT state;\r
2491 \r
2492   state = IsDlgButtonChecked(hDlg, OPT_Autostep);\r
2493   EnableWindow(GetDlgItem(hDlg, OPT_ASTimeDelay), state);\r
2494   EnableWindow(GetDlgItem(hDlg, OPT_AStext1), state);\r
2495 }\r
2496 \r
2497 LRESULT CALLBACK\r
2498 LoadOptions(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
2499 {\r
2500   char buf[MSG_SIZ];\r
2501   float fnumber;\r
2502   int ok;\r
2503 \r
2504   switch (message) {\r
2505   case WM_INITDIALOG: /* message: initialize dialog box */\r
2506     /* Center the dialog over the application window */\r
2507     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
2508     Translate(hDlg, DLG_LoadOptions);\r
2509     /* Initialize the dialog items */\r
2510     if (appData.timeDelay >= 0.0) {\r
2511       CheckDlgButton(hDlg, OPT_Autostep, TRUE);\r
2512       snprintf(buf, MSG_SIZ, "%.2g", appData.timeDelay);\r
2513       SetDlgItemText(hDlg, OPT_ASTimeDelay, buf);\r
2514     } else {\r
2515       CheckDlgButton(hDlg, OPT_Autostep, FALSE);\r
2516     }\r
2517     SetLoadOptionEnables(hDlg);\r
2518     SetDlgItemInt(hDlg, OPT_elo1, appData.eloThreshold1, FALSE);\r
2519     SetDlgItemInt(hDlg, OPT_elo2, appData.eloThreshold2, FALSE);\r
2520     SetDlgItemInt(hDlg, OPT_date, appData.dateThreshold, FALSE);\r
2521     SetDlgItemInt(hDlg, OPT_Stretch, appData.stretch, FALSE);\r
2522     CheckDlgButton(hDlg, OPT_Reversed, appData.ignoreColors);\r
2523     CheckDlgButton(hDlg, OPT_Mirror, appData.findMirror);\r
2524     switch (appData.searchMode) {\r
2525     case 1:\r
2526       CheckDlgButton(hDlg, OPT_Exact, TRUE);\r
2527       break;\r
2528     case 2:\r
2529       CheckDlgButton(hDlg, OPT_Subset, TRUE);\r
2530       break;\r
2531     case 3:\r
2532       CheckDlgButton(hDlg, OPT_Struct, TRUE);\r
2533       break;\r
2534     case 4:\r
2535       CheckDlgButton(hDlg, OPT_Material, TRUE);\r
2536       break;\r
2537     case 5:\r
2538       CheckDlgButton(hDlg, OPT_Range, TRUE);\r
2539       break;\r
2540     case 6:\r
2541       CheckDlgButton(hDlg, OPT_Difference, TRUE);\r
2542       break;\r
2543     }\r
2544     return TRUE;\r
2545 \r
2546   case WM_COMMAND: /* message: received a command */\r
2547     switch (LOWORD(wParam)) {\r
2548     case IDOK:\r
2549       /* Read changed options from the dialog box */\r
2550       if (IsDlgButtonChecked(hDlg, OPT_Autostep)) {\r
2551         GetDlgItemText(hDlg, OPT_ASTimeDelay, buf, MSG_SIZ);\r
2552         if (sscanf(buf, "%f", &fnumber) != 1) {\r
2553           MessageBox(hDlg, _("Invalid load game step rate"),\r
2554                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2555           return FALSE;\r
2556         }\r
2557         appData.timeDelay = fnumber;\r
2558       } else {\r
2559         appData.timeDelay = (float) -1.0;\r
2560       }\r
2561       appData.eloThreshold1 = GetDlgItemInt(hDlg, OPT_elo1, &ok, FALSE);\r
2562       appData.eloThreshold2 = GetDlgItemInt(hDlg, OPT_elo2, &ok, FALSE);\r
2563       appData.dateThreshold = GetDlgItemInt(hDlg, OPT_date, &ok, FALSE);\r
2564       appData.stretch = GetDlgItemInt(hDlg, OPT_Stretch, &ok, FALSE);\r
2565       appData.searchMode = LoadOptionsWhichRadio(hDlg);\r
2566       appData.ignoreColors = IsDlgButtonChecked(hDlg, OPT_Reversed);\r
2567       appData.findMirror   = IsDlgButtonChecked(hDlg, OPT_Mirror);\r
2568       EndDialog(hDlg, TRUE);\r
2569       return TRUE;\r
2570 \r
2571     case IDCANCEL:\r
2572       EndDialog(hDlg, FALSE);\r
2573       return TRUE;\r
2574 \r
2575     default:\r
2576       SetLoadOptionEnables(hDlg);\r
2577       break;\r
2578     }\r
2579     break;\r
2580   }\r
2581   return FALSE;\r
2582 }\r
2583 \r
2584 \r
2585 VOID\r
2586 LoadOptionsPopup(HWND hwnd)\r
2587 {\r
2588   FARPROC lpProc = MakeProcInstance((FARPROC)LoadOptions, hInst);\r
2589   DialogBox(hInst, MAKEINTRESOURCE(DLG_LoadOptions), hwnd, (DLGPROC) lpProc);\r
2590   FreeProcInstance(lpProc);\r
2591 }\r
2592 \r
2593 /*---------------------------------------------------------------------------*\\r
2594  *\r
2595  * Save Options dialog functions\r
2596  *\r
2597 \*---------------------------------------------------------------------------*/\r
2598 \r
2599 VOID\r
2600 SetSaveOptionEnables(HWND hDlg)\r
2601 {\r
2602   UINT state;\r
2603 \r
2604   state = IsDlgButtonChecked(hDlg, OPT_Autosave);\r
2605   EnableWindow(GetDlgItem(hDlg, OPT_AVPrompt), state);\r
2606   EnableWindow(GetDlgItem(hDlg, OPT_AVToFile), state);\r
2607   if (state && !IsDlgButtonChecked(hDlg, OPT_AVPrompt) &&\r
2608       !IsDlgButtonChecked(hDlg, OPT_AVToFile)) {\r
2609     CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVPrompt);\r
2610   }\r
2611 \r
2612   state = state && IsDlgButtonChecked(hDlg, OPT_AVToFile);\r
2613   EnableWindow(GetDlgItem(hDlg, OPT_AVFilename), state);\r
2614   EnableWindow(GetDlgItem(hDlg, OPT_AVBrowse), state);\r
2615 }\r
2616 \r
2617 LRESULT CALLBACK\r
2618 SaveOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
2619 {\r
2620   char buf[MSG_SIZ];\r
2621   FILE *f;\r
2622 \r
2623   switch (message) {\r
2624   case WM_INITDIALOG: /* message: initialize dialog box */\r
2625     /* Center the dialog over the application window */\r
2626     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
2627     Translate(hDlg, DLG_SaveOptions);\r
2628     /* Initialize the dialog items */\r
2629     if (*appData.saveGameFile != NULLCHAR) {\r
2630       CheckDlgButton(hDlg, OPT_Autosave, (UINT) TRUE);\r
2631       CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVToFile);\r
2632       SetDlgItemText(hDlg, OPT_AVFilename, appData.saveGameFile);\r
2633     } else if (appData.autoSaveGames) {\r
2634       CheckDlgButton(hDlg, OPT_Autosave, (UINT) TRUE);\r
2635       CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVPrompt);\r
2636     } else {\r
2637       CheckDlgButton(hDlg, OPT_Autosave, (UINT) FALSE);\r
2638     }\r
2639     if (appData.oldSaveStyle) {\r
2640       CheckRadioButton(hDlg, OPT_PGN, OPT_Old, OPT_Old);\r
2641     } else {\r
2642       CheckRadioButton(hDlg, OPT_PGN, OPT_Old, OPT_PGN);\r
2643     }\r
2644     CheckDlgButton( hDlg, OPT_OutOfBookInfo, appData.saveOutOfBookInfo );\r
2645     SetSaveOptionEnables(hDlg);\r
2646     return TRUE;\r
2647 \r
2648   case WM_COMMAND: /* message: received a command */\r
2649     switch (LOWORD(wParam)) {\r
2650     case IDOK:\r
2651       /* Read changed options from the dialog box */\r
2652       if (IsDlgButtonChecked(hDlg, OPT_Autosave)) {\r
2653         appData.autoSaveGames = TRUE;\r
2654         if (IsDlgButtonChecked(hDlg, OPT_AVPrompt)) {\r
2655           ASSIGN(appData.saveGameFile, ""); // [HGM] make sure value is ALWAYS in allocated memory\r
2656         } else /*if (IsDlgButtonChecked(hDlg, OPT_AVToFile))*/ {\r
2657           GetDlgItemText(hDlg, OPT_AVFilename, buf, MSG_SIZ);\r
2658           if (*buf == NULLCHAR) {\r
2659             MessageBox(hDlg, _("Invalid save game file name"),\r
2660                        _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2661             return FALSE;\r
2662           }\r
2663           FREE(appData.saveGameFile);\r
2664           appData.saveGameFile = InterpretFileName(buf, homeDir);\r
2665         }\r
2666       } else {\r
2667         appData.autoSaveGames = FALSE;\r
2668         ASSIGN(appData.saveGameFile, "");\r
2669       }\r
2670       appData.oldSaveStyle = IsDlgButtonChecked(hDlg, OPT_Old);\r
2671       appData.saveOutOfBookInfo = IsDlgButtonChecked( hDlg, OPT_OutOfBookInfo );\r
2672       EndDialog(hDlg, TRUE);\r
2673       return TRUE;\r
2674 \r
2675     case IDCANCEL:\r
2676       EndDialog(hDlg, FALSE);\r
2677       return TRUE;\r
2678 \r
2679     case OPT_AVBrowse:\r
2680       f = OpenFileDialog(hDlg, "a", NULL,\r
2681                          appData.oldSaveStyle ? "gam" : "pgn",\r
2682                          GAME_FILT, _("Browse for Auto Save File"),\r
2683                          NULL, NULL, buf);\r
2684       if (f != NULL) {\r
2685         fclose(f);\r
2686         SetDlgItemText(hDlg, OPT_AVFilename, buf);\r
2687       }\r
2688       break;\r
2689 \r
2690     default:\r
2691       SetSaveOptionEnables(hDlg);\r
2692       break;\r
2693     }\r
2694     break;\r
2695   }\r
2696   return FALSE;\r
2697 }\r
2698 \r
2699 VOID\r
2700 SaveOptionsPopup(HWND hwnd)\r
2701 {\r
2702   FARPROC lpProc = MakeProcInstance((FARPROC)SaveOptionsDialog, hInst);\r
2703   DialogBox(hInst, MAKEINTRESOURCE(DLG_SaveOptions), hwnd, (DLGPROC) lpProc);\r
2704   FreeProcInstance(lpProc);\r
2705 }\r
2706 \r
2707 /*---------------------------------------------------------------------------*\\r
2708  *\r
2709  * Time Control Options dialog functions\r
2710  *\r
2711 \*---------------------------------------------------------------------------*/\r
2712 \r
2713 VOID\r
2714 SetTimeControlEnables(HWND hDlg)\r
2715 {\r
2716   UINT state;\r
2717 \r
2718   state = IsDlgButtonChecked(hDlg, OPT_TCUseMoves)\r
2719         + 2*IsDlgButtonChecked(hDlg, OPT_TCUseFixed);\r
2720   EnableWindow(GetDlgItem(hDlg, OPT_TCTime), state == 1);\r
2721   EnableWindow(GetDlgItem(hDlg, OPT_TCMoves), state == 1);\r
2722   EnableWindow(GetDlgItem(hDlg, OPT_TCtext1), state == 1);\r
2723   EnableWindow(GetDlgItem(hDlg, OPT_TCtext2), state == 1);\r
2724   EnableWindow(GetDlgItem(hDlg, OPT_TCTime2), !state);\r
2725   EnableWindow(GetDlgItem(hDlg, OPT_TCInc), !state);\r
2726   EnableWindow(GetDlgItem(hDlg, OPT_TCitext1), !state);\r
2727   EnableWindow(GetDlgItem(hDlg, OPT_TCitext2), !state);\r
2728   EnableWindow(GetDlgItem(hDlg, OPT_TCitext3), !state);\r
2729   EnableWindow(GetDlgItem(hDlg, OPT_TCFixed), state == 2);\r
2730   EnableWindow(GetDlgItem(hDlg, OPT_TCftext), state == 2);\r
2731 }\r
2732 \r
2733 \r
2734 LRESULT CALLBACK\r
2735 TimeControl(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
2736 {\r
2737   char buf[MSG_SIZ], *tc;\r
2738   int mps, odds1, odds2, st;\r
2739   float increment;\r
2740   BOOL ok, ok2;\r
2741 \r
2742   switch (message) {\r
2743   case WM_INITDIALOG: /* message: initialize dialog box */\r
2744     /* Center the dialog over the application window */\r
2745     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
2746     Translate(hDlg, DLG_TimeControl);\r
2747     /* Initialize the dialog items */\r
2748     if (/*appData.clockMode &&*/ !appData.icsActive) { // [HGM] even if !clockMode, we could want to set it in tournament dialog\r
2749       if (searchTime) {\r
2750         CheckRadioButton(hDlg, OPT_TCUseMoves, OPT_TCUseFixed,\r
2751                          OPT_TCUseFixed);\r
2752         SetDlgItemInt(hDlg, OPT_TCFixed, searchTime, FALSE);\r
2753       } else\r
2754       if (appData.timeIncrement == -1) {\r
2755         CheckRadioButton(hDlg, OPT_TCUseMoves, OPT_TCUseFixed,\r
2756                          OPT_TCUseMoves);\r
2757         SetDlgItemText(hDlg, OPT_TCTime, appData.timeControl);\r
2758         SetDlgItemInt(hDlg, OPT_TCMoves, appData.movesPerSession,\r
2759                       FALSE);\r
2760         SetDlgItemText(hDlg, OPT_TCTime2, "");\r
2761         SetDlgItemText(hDlg, OPT_TCInc, "");\r
2762       } else {\r
2763         int i = appData.timeIncrement;\r
2764         if(i == appData.timeIncrement) snprintf(buf, MSG_SIZ, "%d", i);\r
2765         else snprintf(buf, MSG_SIZ, "%4.2f", appData.timeIncrement);\r
2766         CheckRadioButton(hDlg, OPT_TCUseMoves, OPT_TCUseFixed,\r
2767                          OPT_TCUseInc);\r
2768         SetDlgItemText(hDlg, OPT_TCTime, "");\r
2769         SetDlgItemText(hDlg, OPT_TCMoves, "");\r
2770         SetDlgItemText(hDlg, OPT_TCTime2, appData.timeControl);\r
2771         SetDlgItemText(hDlg, OPT_TCInc, buf);\r
2772       }\r
2773       SetDlgItemInt(hDlg, OPT_TCOdds1, 1, FALSE);\r
2774       SetDlgItemInt(hDlg, OPT_TCOdds2, 1, FALSE);\r
2775       SetTimeControlEnables(hDlg);\r
2776     }\r
2777     return TRUE;\r
2778 \r
2779   case WM_COMMAND: /* message: received a command */\r
2780     switch (LOWORD(wParam)) {\r
2781     case IDOK:\r
2782       mps = appData.movesPerSession;\r
2783       increment = appData.timeIncrement;\r
2784       tc = appData.timeControl;\r
2785       st = 0;\r
2786       /* Read changed options from the dialog box */\r
2787       if (IsDlgButtonChecked(hDlg, OPT_TCUseFixed)) {\r
2788         st = GetDlgItemInt(hDlg, OPT_TCFixed, &ok, FALSE);\r
2789         if (!ok || st <= 0) {\r
2790           MessageBox(hDlg, _("Invalid max time per move"),\r
2791                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2792           return FALSE;\r
2793         }\r
2794       } else\r
2795       if (IsDlgButtonChecked(hDlg, OPT_TCUseMoves)) {\r
2796         increment = -1;\r
2797         mps = GetDlgItemInt(hDlg, OPT_TCMoves, &ok, FALSE);\r
2798         if (!ok || mps <= 0) {\r
2799           MessageBox(hDlg, _("Invalid moves per time control"),\r
2800                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2801           return FALSE;\r
2802         }\r
2803         GetDlgItemText(hDlg, OPT_TCTime, buf, MSG_SIZ);\r
2804         if (!ParseTimeControl(buf, increment, mps)) {\r
2805           MessageBox(hDlg, _("Invalid minutes per time control"),\r
2806                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2807           return FALSE;\r
2808         }\r
2809       tc = buf;\r
2810       } else {\r
2811         GetDlgItemText(hDlg, OPT_TCInc, buf, MSG_SIZ);\r
2812         ok = (sscanf(buf, "%f%c", &increment, buf) == 1);\r
2813         if (!ok || increment < 0) {\r
2814           MessageBox(hDlg, _("Invalid increment"),\r
2815                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2816           return FALSE;\r
2817         }\r
2818         GetDlgItemText(hDlg, OPT_TCTime2, buf, MSG_SIZ);\r
2819         if (!ParseTimeControl(buf, increment, mps)) {\r
2820           MessageBox(hDlg, _("Invalid initial time"),\r
2821                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2822           return FALSE;\r
2823         }\r
2824       tc = buf;\r
2825       }\r
2826       odds1 = GetDlgItemInt(hDlg, OPT_TCOdds1, &ok, FALSE);\r
2827       odds2 = GetDlgItemInt(hDlg, OPT_TCOdds2, &ok2, FALSE);\r
2828       if (!ok || !ok2 || odds1 <= 0 || odds2 <= 0) {\r
2829           MessageBox(hDlg, _("Invalid time-odds factor"),\r
2830                      _("Option Error"), MB_OK|MB_ICONEXCLAMATION);\r
2831           return FALSE;\r
2832       }\r
2833       searchTime = st;\r
2834       appData.timeControl = strdup(tc);\r
2835       appData.movesPerSession = mps;\r
2836       appData.timeIncrement = increment;\r
2837       appData.firstTimeOdds  = first.timeOdds  = odds1;\r
2838       appData.secondTimeOdds = second.timeOdds = odds2;\r
2839       Reset(TRUE, TRUE);\r
2840       EndDialog(hDlg, TRUE);\r
2841       return TRUE;\r
2842 \r
2843     case IDCANCEL:\r
2844       EndDialog(hDlg, FALSE);\r
2845       return TRUE;\r
2846 \r
2847     default:\r
2848       SetTimeControlEnables(hDlg);\r
2849       break;\r
2850     }\r
2851     break;\r
2852   }\r
2853   return FALSE;\r
2854 }\r
2855 \r
2856 VOID\r
2857 TimeControlOptionsPopup(HWND hwnd)\r
2858 {\r
2859   if (gameMode != BeginningOfGame) {\r
2860     DisplayError(_("Changing time control during a game is not implemented"), 0);\r
2861   } else {\r
2862     FARPROC lpProc = MakeProcInstance((FARPROC)TimeControl, hInst);\r
2863     DialogBox(hInst, MAKEINTRESOURCE(DLG_TimeControl), hwnd, (DLGPROC) lpProc);\r
2864     FreeProcInstance(lpProc);\r
2865   }\r
2866 }\r
2867 \r
2868 /*---------------------------------------------------------------------------*\\r
2869  *\r
2870  * Engine Options Dialog functions\r
2871  *\r
2872 \*---------------------------------------------------------------------------*/\r
2873 #define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y))\r
2874 #define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x))\r
2875 \r
2876 #define INT_ABS( n )    ((n) >= 0 ? (n) : -(n))\r
2877 \r
2878 LRESULT CALLBACK EnginePlayOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
2879 {\r
2880   switch (message) {\r
2881   case WM_INITDIALOG: /* message: initialize dialog box */\r
2882 \r
2883     /* Center the dialog over the application window */\r
2884     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
2885     Translate(hDlg, DLG_EnginePlayOptions);\r
2886 \r
2887     /* Initialize the dialog items */\r
2888     CHECK_BOX(IDC_EpPeriodicUpdates, appData.periodicUpdates);\r
2889     CHECK_BOX(IDC_EpPonder, appData.ponderNextMove);\r
2890     CHECK_BOX(IDC_EpShowThinking, appData.showThinking);\r
2891     CHECK_BOX(IDC_EpHideThinkingHuman, appData.hideThinkingFromHuman);\r
2892 \r
2893     CHECK_BOX(IDC_TestClaims, appData.testClaims);\r
2894     CHECK_BOX(IDC_DetectMates, appData.checkMates);\r
2895     CHECK_BOX(IDC_MaterialDraws, appData.materialDraws);\r
2896     CHECK_BOX(IDC_TrivialDraws, appData.trivialDraws);\r
2897 \r
2898     CHECK_BOX(IDC_ScoreAbs1, appData.firstScoreIsAbsolute);\r
2899     CHECK_BOX(IDC_ScoreAbs2, appData.secondScoreIsAbsolute);\r
2900 \r
2901     SetDlgItemInt( hDlg, IDC_EpDrawMoveCount, appData.adjudicateDrawMoves, TRUE );\r
2902     SendDlgItemMessage( hDlg, IDC_EpDrawMoveCount, EM_SETSEL, 0, -1 );\r
2903 \r
2904     SetDlgItemInt( hDlg, IDC_EpAdjudicationThreshold, INT_ABS(appData.adjudicateLossThreshold), TRUE );\r
2905     SendDlgItemMessage( hDlg, IDC_EpAdjudicationThreshold, EM_SETSEL, 0, -1 );\r
2906 \r
2907     SetDlgItemInt( hDlg, IDC_RuleMoves, appData.ruleMoves, TRUE );\r
2908     SendDlgItemMessage( hDlg, IDC_RuleMoves, EM_SETSEL, 0, -1 );\r
2909 \r
2910     SetDlgItemInt( hDlg, IDC_DrawRepeats, INT_ABS(appData.drawRepeats), TRUE );\r
2911     SendDlgItemMessage( hDlg, IDC_DrawRepeats, EM_SETSEL, 0, -1 );\r
2912 \r
2913     return TRUE;\r
2914 \r
2915   case WM_COMMAND: /* message: received a command */\r
2916     switch (LOWORD(wParam)) {\r
2917     case IDOK:\r
2918       /* Read changed options from the dialog box */\r
2919       PeriodicUpdatesEvent(          IS_CHECKED(IDC_EpPeriodicUpdates));\r
2920       PonderNextMoveEvent(           IS_CHECKED(IDC_EpPonder));\r
2921       appData.hideThinkingFromHuman= IS_CHECKED(IDC_EpHideThinkingHuman); // [HGM] thinking: moved up\r
2922       appData.showThinking   = IS_CHECKED(IDC_EpShowThinking);\r
2923       ShowThinkingEvent(); // [HGM] thinking: tests all options that need thinking output\r
2924       appData.testClaims    = IS_CHECKED(IDC_TestClaims);\r
2925       appData.checkMates    = IS_CHECKED(IDC_DetectMates);\r
2926       appData.materialDraws = IS_CHECKED(IDC_MaterialDraws);\r
2927       appData.trivialDraws  = IS_CHECKED(IDC_TrivialDraws);\r
2928 \r
2929       appData.adjudicateDrawMoves = GetDlgItemInt(hDlg, IDC_EpDrawMoveCount, NULL, FALSE );\r
2930       appData.adjudicateLossThreshold = - (int) GetDlgItemInt(hDlg, IDC_EpAdjudicationThreshold, NULL, FALSE );\r
2931       appData.ruleMoves = GetDlgItemInt(hDlg, IDC_RuleMoves, NULL, FALSE );\r
2932       appData.drawRepeats = (int) GetDlgItemInt(hDlg, IDC_DrawRepeats, NULL, FALSE );\r
2933 \r
2934       first.scoreIsAbsolute  = appData.firstScoreIsAbsolute  = IS_CHECKED(IDC_ScoreAbs1);\r
2935       second.scoreIsAbsolute = appData.secondScoreIsAbsolute = IS_CHECKED(IDC_ScoreAbs2);\r
2936 \r
2937       EndDialog(hDlg, TRUE);\r
2938       return TRUE;\r
2939 \r
2940     case IDCANCEL:\r
2941       EndDialog(hDlg, FALSE);\r
2942       return TRUE;\r
2943 \r
2944     case IDC_EpDrawMoveCount:\r
2945     case IDC_EpAdjudicationThreshold:\r
2946     case IDC_DrawRepeats:\r
2947     case IDC_RuleMoves:\r
2948         if( HIWORD(wParam) == EN_CHANGE ) {\r
2949             int n1_ok;\r
2950             int n2_ok;\r
2951             int n3_ok;\r
2952             int n4_ok;\r
2953 \r
2954             GetDlgItemInt(hDlg, IDC_EpDrawMoveCount, &n1_ok, FALSE );\r
2955             GetDlgItemInt(hDlg, IDC_EpAdjudicationThreshold, &n2_ok, FALSE );\r
2956             GetDlgItemInt(hDlg, IDC_RuleMoves, &n3_ok, FALSE );\r
2957             GetDlgItemInt(hDlg, IDC_DrawRepeats, &n4_ok, FALSE );\r
2958 \r
2959             EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok && n3_ok && n4_ok ? TRUE : FALSE );\r
2960         }\r
2961         return TRUE;\r
2962     }\r
2963     break;\r
2964   }\r
2965   return FALSE;\r
2966 }\r
2967 \r
2968 VOID EnginePlayOptionsPopup(HWND hwnd)\r
2969 {\r
2970   FARPROC lpProc;\r
2971 \r
2972   lpProc = MakeProcInstance((FARPROC)EnginePlayOptionsDialog, hInst);\r
2973   DialogBox(hInst, MAKEINTRESOURCE(DLG_EnginePlayOptions), hwnd, (DLGPROC) lpProc);\r
2974   FreeProcInstance(lpProc);\r
2975 }\r
2976 \r
2977 /*---------------------------------------------------------------------------*\\r
2978  *\r
2979  * UCI Options Dialog functions\r
2980  *\r
2981 \*---------------------------------------------------------------------------*/\r
2982 INT CALLBACK BrowseCallbackProc(HWND hwnd, \r
2983                                 UINT uMsg,\r
2984                                 LPARAM lp, \r
2985                                 LPARAM pData) \r
2986 {\r
2987     switch(uMsg) \r
2988     {\r
2989       case BFFM_INITIALIZED: \r
2990         SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)pData);\r
2991         break;\r
2992     }\r
2993     return 0;\r
2994 }\r
2995 \r
2996 BOOL BrowseForFolder( const char * title, char * path )\r
2997 {\r
2998     BOOL result = FALSE;\r
2999     BROWSEINFO bi;\r
3000     LPITEMIDLIST pidl;\r
3001 \r
3002     ZeroMemory( &bi, sizeof(bi) );\r
3003 \r
3004     bi.lpszTitle = title == 0 ? _("Choose Folder") : title;\r
3005     bi.ulFlags = BIF_RETURNONLYFSDIRS;\r
3006     bi.lpfn = BrowseCallbackProc;\r
3007     bi.lParam = (LPARAM) path;\r
3008 \r
3009     pidl = SHBrowseForFolder( &bi );\r
3010 \r
3011     if( pidl != 0 ) {\r
3012         IMalloc * imalloc = 0;\r
3013 \r
3014         if( SHGetPathFromIDList( pidl, path ) ) {\r
3015             result = TRUE;\r
3016         }\r
3017 \r
3018         if( SUCCEEDED( SHGetMalloc ( &imalloc ) ) ) {\r
3019             imalloc->lpVtbl->Free(imalloc,pidl);\r
3020             imalloc->lpVtbl->Release(imalloc);\r
3021         }\r
3022     }\r
3023 \r
3024     return result;\r
3025 }\r
3026 \r
3027 int\r
3028 IsMultiFormat(char *s)\r
3029 {\r
3030   char *p = strchr(s, ':');\r
3031   return p && p != s+1;\r
3032 }\r
3033 \r
3034 LRESULT CALLBACK UciOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
3035 {\r
3036   char buf[MAX_PATH];\r
3037   int oldCores;\r
3038 \r
3039   switch (message) {\r
3040   case WM_INITDIALOG: /* message: initialize dialog box */\r
3041 \r
3042     /* Center the dialog over the application window */\r
3043     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
3044     Translate(hDlg, DLG_OptionsUCI);\r
3045 \r
3046     /* Initialize the dialog items */\r
3047     SetDlgItemText( hDlg, IDC_PolyglotDir, appData.polyglotDir );\r
3048     SetDlgItemInt( hDlg, IDC_HashSize, appData.defaultHashSize, TRUE );\r
3049     if(appData.defaultPathEGTB[0])\r
3050     SetDlgItemText( hDlg, IDC_PathToEGTB, appData.defaultPathEGTB );\r
3051     else\r
3052     SetDlgItemText( hDlg, IDC_PathToEGTB, appData.egtFormats );\r
3053     SetDlgItemInt( hDlg, IDC_SizeOfEGTB, appData.defaultCacheSizeEGTB, TRUE );\r
3054     CheckDlgButton( hDlg, IDC_UseBook, (BOOL) appData.usePolyglotBook );\r
3055     SetDlgItemText( hDlg, IDC_BookFile, appData.polyglotBook );\r
3056     // [HGM] smp: input field for nr of cores:\r
3057     SetDlgItemInt( hDlg, IDC_Cores, appData.smpCores, TRUE );\r
3058     // [HGM] book: tick boxes for own book use\r
3059     CheckDlgButton( hDlg, IDC_OwnBook1, (BOOL) appData.firstHasOwnBookUCI );\r
3060     CheckDlgButton( hDlg, IDC_OwnBook2, (BOOL) appData.secondHasOwnBookUCI );\r
3061     SetDlgItemInt( hDlg, IDC_BookDep, appData.bookDepth, TRUE );\r
3062     SetDlgItemInt( hDlg, IDC_BookStr, appData.bookStrength, TRUE );\r
3063     SetDlgItemInt( hDlg, IDC_Games, appData.defaultMatchGames, TRUE );\r
3064 \r
3065     SendDlgItemMessage( hDlg, IDC_PolyglotDir, EM_SETSEL, 0, -1 );\r
3066 \r
3067     return TRUE;\r
3068 \r
3069   case WM_COMMAND: /* message: received a command */\r
3070     switch (LOWORD(wParam)) {\r
3071     case IDOK:\r
3072       GetDlgItemText( hDlg, IDC_PolyglotDir, buf, sizeof(buf) );\r
3073       appData.polyglotDir = strdup(buf);\r
3074       appData.defaultHashSize = GetDlgItemInt(hDlg, IDC_HashSize, NULL, FALSE );\r
3075       appData.defaultCacheSizeEGTB = GetDlgItemInt(hDlg, IDC_SizeOfEGTB, NULL, FALSE );\r
3076       GetDlgItemText( hDlg, IDC_PathToEGTB, buf, sizeof(buf) );\r
3077       if(IsMultiFormat(buf)) {\r
3078         ASSIGN(appData.egtFormats, buf);\r
3079       } else {\r
3080         ASSIGN(appData.defaultPathEGTB, buf);\r
3081       }\r
3082       GetDlgItemText( hDlg, IDC_BookFile, buf, sizeof(buf) );\r
3083       appData.polyglotBook = strdup(buf);\r
3084       appData.usePolyglotBook = (Boolean) IsDlgButtonChecked( hDlg, IDC_UseBook );\r
3085       // [HGM] smp: get nr of cores:\r
3086       oldCores = appData.smpCores;\r
3087       appData.smpCores = GetDlgItemInt(hDlg, IDC_Cores, NULL, FALSE );\r
3088       if(appData.smpCores != oldCores) NewSettingEvent(FALSE, &(first.maxCores), "cores", appData.smpCores);\r
3089       // [HGM] book: read tick boxes for own book use\r
3090       appData.firstHasOwnBookUCI  = (Boolean) IsDlgButtonChecked( hDlg, IDC_OwnBook1 );\r
3091       appData.secondHasOwnBookUCI = (Boolean) IsDlgButtonChecked( hDlg, IDC_OwnBook2 );\r
3092       appData.bookDepth = GetDlgItemInt(hDlg, IDC_BookDep, NULL, FALSE );\r
3093       appData.bookStrength = GetDlgItemInt(hDlg, IDC_BookStr, NULL, FALSE );\r
3094       appData.defaultMatchGames = GetDlgItemInt(hDlg, IDC_Games, NULL, FALSE );\r
3095 \r
3096       if(gameMode == BeginningOfGame) Reset(TRUE, TRUE);\r
3097       EndDialog(hDlg, TRUE);\r
3098       return TRUE;\r
3099 \r
3100     case IDCANCEL:\r
3101       EndDialog(hDlg, FALSE);\r
3102       return TRUE;\r
3103 \r
3104     case IDC_BrowseForBook:\r
3105       {\r
3106           char filter[] = {\r
3107               'A','l','l',' ','F','i','l','e','s', 0,\r
3108               '*','.','*', 0,\r
3109               'B','I','N',' ','F','i','l','e','s', 0,\r
3110               '*','.','b','i','n', 0,\r
3111               0 };\r
3112 \r
3113           OPENFILENAME ofn;\r
3114 \r
3115           safeStrCpy( buf, "" , sizeof( buf)/sizeof( buf[0]) );\r
3116 \r
3117           ZeroMemory( &ofn, sizeof(ofn) );\r
3118 \r
3119           ofn.lStructSize = sizeof(ofn);\r
3120           ofn.hwndOwner = hDlg;\r
3121           ofn.hInstance = hInst;\r
3122           ofn.lpstrFilter = filter;\r
3123           ofn.lpstrFile = buf;\r
3124           ofn.nMaxFile = sizeof(buf);\r
3125           ofn.lpstrTitle = _("Choose Book");\r
3126           ofn.Flags = OFN_FILEMUSTEXIST | OFN_LONGNAMES | OFN_HIDEREADONLY;\r
3127 \r
3128           if( GetOpenFileName( &ofn ) ) {\r
3129               SetDlgItemText( hDlg, IDC_BookFile, buf );\r
3130           }\r
3131       }\r
3132       return TRUE;\r
3133 \r
3134     case IDC_BrowseForPolyglotDir:\r
3135       if( BrowseForFolder( _("Choose Polyglot Directory"), buf ) ) {\r
3136         SetDlgItemText( hDlg, IDC_PolyglotDir, buf );\r
3137 \r
3138         strcat( buf, "\\polyglot.exe" );\r
3139 \r
3140         if( GetFileAttributes(buf) == 0xFFFFFFFF ) {\r
3141             MessageBox( hDlg, _("Polyglot was not found in the specified folder!"), "Warning", MB_OK | MB_ICONWARNING );\r
3142         }\r
3143       }\r
3144       return TRUE;\r
3145 \r
3146     case IDC_BrowseForEGTB:\r
3147       if( BrowseForFolder( _("Choose EGTB Directory:"), buf ) ) {\r
3148         SetDlgItemText( hDlg, IDC_PathToEGTB, buf );\r
3149       }\r
3150       return TRUE;\r
3151 \r
3152     case IDC_HashSize:\r
3153     case IDC_SizeOfEGTB:\r
3154         if( HIWORD(wParam) == EN_CHANGE ) {\r
3155             int n1_ok;\r
3156             int n2_ok;\r
3157 \r
3158             GetDlgItemInt(hDlg, IDC_HashSize, &n1_ok, FALSE );\r
3159             GetDlgItemInt(hDlg, IDC_SizeOfEGTB, &n2_ok, FALSE );\r
3160 \r
3161             EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok ? TRUE : FALSE );\r
3162         }\r
3163         return TRUE;\r
3164     }\r
3165     break;\r
3166   }\r
3167   return FALSE;\r
3168 }\r
3169 \r
3170 VOID UciOptionsPopup(HWND hwnd)\r
3171 {\r
3172   FARPROC lpProc;\r
3173 \r
3174   lpProc = MakeProcInstance((FARPROC)UciOptionsDialog, hInst);\r
3175   DialogBox(hInst, MAKEINTRESOURCE(DLG_OptionsUCI), hwnd, (DLGPROC) lpProc);\r
3176   FreeProcInstance(lpProc);\r
3177 }\r