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