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