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