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