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