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