cleaned up old CVS left overs
[xboard.git] / winboard / woptions.c
1 /*
2  * woptions.c -- Options dialog box routines for WinBoard
3  *
4  * Copyright 2000,2009 Free Software Foundation, Inc.
5  *
6  * ------------------------------------------------------------------------
7  *
8  * GNU XBoard is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or (at
11  * your option) any later version.
12  *
13  * GNU XBoard is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see http://www.gnu.org/licenses/.  *
20  *
21  *------------------------------------------------------------------------
22  ** See the file ChangeLog for a revision history.  */
23
24 #include "config.h"
25
26 #include <windows.h>   /* required for all Windows applications */
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <shlobj.h>    /* [AS] Requires NT 4.0 or Win95 */
30 #include <ctype.h>
31
32 #include "common.h"
33 #include "winboard.h"
34 #include "backend.h"
35 #include "woptions.h"
36 #include "defaults.h"
37 #include "wedittags.h"
38 #include <richedit.h>
39
40 #if __GNUC__
41 #include <errno.h>
42 #include <string.h>
43 #endif
44
45 /* Imports from winboard.c */
46
47 extern MyFont *font[NUM_SIZES][NUM_FONTS];
48 extern HINSTANCE hInst;          /* current instance */
49 extern HWND hwndMain;            /* root window*/
50 extern BOOLEAN alwaysOnTop;
51 extern RECT boardRect;
52 extern COLORREF lightSquareColor, darkSquareColor, whitePieceColor, 
53   blackPieceColor, highlightSquareColor, premoveHighlightColor;
54 extern HPALETTE hPal;
55 extern BoardSize boardSize;
56 extern COLORREF consoleBackgroundColor;
57 extern MyColorizeAttribs colorizeAttribs[]; /* do I need the size? */
58 extern MyTextAttribs textAttribs[];
59 extern MySound sounds[];
60 extern ColorClass currentColorClass;
61 extern HWND hwndConsole;
62 extern char *defaultTextAttribs[];
63 extern HWND commentDialog;
64 extern HWND moveHistoryDialog;
65 extern HWND engineOutputDialog;
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         SendMessage( moveHistoryDialog, WM_INITDIALOG, 0, 0 );
1638 //      InvalidateRect(editTagsDialog, NULL, TRUE); // [HGM] this ws improperly cloned?
1639       }
1640
1641       if( engineOutputDialog != NULL ) {
1642         SendDlgItemMessage(engineOutputDialog, IDC_EngineMemo1,
1643           WM_SETFONT, (WPARAM)font[boardSize][MOVEHISTORY_FONT]->hf, 
1644           MAKELPARAM(TRUE, 0));
1645         SendDlgItemMessage(engineOutputDialog, IDC_EngineMemo2,
1646           WM_SETFONT, (WPARAM)font[boardSize][MOVEHISTORY_FONT]->hf, 
1647           MAKELPARAM(TRUE, 0));
1648       }
1649
1650       if (hwndConsole) {
1651         ChangedConsoleFont();
1652       }
1653
1654       for (i=0; i<NUM_FONTS; i++)
1655         DeleteObject(&workFont[i].hf);
1656
1657       return TRUE;
1658
1659     case IDCANCEL:
1660       for (i=0; i<NUM_FONTS; i++)
1661         DeleteObject(&workFont[i].hf);
1662       EndDialog(hDlg, FALSE);
1663       return TRUE;
1664
1665     case OPT_ChooseClockFont:
1666       MyCreateFont(hDlg, &workFont[CLOCK_FONT]);
1667       SetSampleFontText(hDlg, OPT_SampleClockFont, &workFont[CLOCK_FONT]);
1668       break;
1669
1670     case OPT_ChooseMessageFont:
1671       MyCreateFont(hDlg, &workFont[MESSAGE_FONT]);
1672       SetSampleFontText(hDlg, OPT_SampleMessageFont, &workFont[MESSAGE_FONT]);
1673       break;
1674
1675     case OPT_ChooseCoordFont:
1676       MyCreateFont(hDlg, &workFont[COORD_FONT]);
1677       SetSampleFontText(hDlg, OPT_SampleCoordFont, &workFont[COORD_FONT]);
1678       break;
1679
1680     case OPT_ChooseTagFont:
1681       MyCreateFont(hDlg, &workFont[EDITTAGS_FONT]);
1682       SetSampleFontText(hDlg, OPT_SampleTagFont, &workFont[EDITTAGS_FONT]);
1683       break;
1684
1685     case OPT_ChooseCommentsFont:
1686       MyCreateFont(hDlg, &workFont[COMMENT_FONT]);
1687       SetSampleFontText(hDlg, OPT_SampleCommentsFont, &workFont[COMMENT_FONT]);
1688       break;
1689
1690     case OPT_ChooseConsoleFont:
1691       MyCreateFont(hDlg, &workFont[CONSOLE_FONT]);
1692       SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]);
1693       break;
1694
1695     case OPT_ChooseMoveHistoryFont:
1696       MyCreateFont(hDlg, &workFont[MOVEHISTORY_FONT]);
1697       SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]);
1698       break;
1699
1700     case OPT_DefaultFonts:
1701       for (i=0; i<NUM_FONTS; i++) {
1702         DeleteObject(&workFont[i].hf);
1703         ParseFontName(font[boardSize][i]->def, &workFont[i].mfp);
1704         CreateFontInMF(&workFont[i]);
1705       }
1706       SetSampleFontText(hDlg, OPT_SampleClockFont, &workFont[CLOCK_FONT]);
1707       SetSampleFontText(hDlg, OPT_SampleMessageFont, &workFont[MESSAGE_FONT]);
1708       SetSampleFontText(hDlg, OPT_SampleCoordFont, &workFont[COORD_FONT]);
1709       SetSampleFontText(hDlg, OPT_SampleTagFont, &workFont[EDITTAGS_FONT]);
1710       SetSampleFontText(hDlg, OPT_SampleCommentsFont, &workFont[COMMENT_FONT]);
1711       SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]);
1712       SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]);
1713       break;
1714     }
1715   }
1716   return FALSE;
1717 }
1718
1719 VOID
1720 FontsOptionsPopup(HWND hwnd)
1721 {
1722   FARPROC lpProc = MakeProcInstance((FARPROC)FontOptionsDialog, hInst);
1723   DialogBox(hInst, MAKEINTRESOURCE(DLG_Fonts), hwnd,
1724           (DLGPROC) lpProc);
1725   FreeProcInstance(lpProc);
1726 }
1727
1728 /*---------------------------------------------------------------------------*\
1729  *
1730  * Sounds Dialog functions
1731  *
1732 \*---------------------------------------------------------------------------*/
1733
1734
1735 SoundComboData soundComboData[] = {
1736   {"Move", NULL},
1737   {"Bell", NULL},
1738   {"ICS Alarm", NULL},
1739   {"ICS Win", NULL},
1740   {"ICS Loss", NULL},
1741   {"ICS Draw", NULL},
1742   {"ICS Unfinished", NULL},
1743   {"Shout", NULL},
1744   {"SShout/CShout", NULL},
1745   {"Channel 1", NULL},
1746   {"Channel", NULL},
1747   {"Kibitz", NULL},
1748   {"Tell", NULL},
1749   {"Challenge", NULL},
1750   {"Request", NULL},
1751   {"Seek", NULL},
1752   {NULL, NULL},
1753 };
1754
1755
1756 void
1757 InitSoundComboData(SoundComboData *scd)
1758 {
1759   SoundClass sc;
1760   ColorClass cc;
1761   int index;
1762
1763   /* copy current sound settings to combo array */
1764
1765   for ( sc = (SoundClass)0; sc < NSoundClasses; sc++) {
1766     scd[sc].name = strdup(sounds[sc].name);
1767   }
1768   for ( cc = (ColorClass)0; cc < NColorClasses - 2; cc++) {
1769     index = (int)cc + (int)NSoundClasses;
1770     scd[index].name = strdup(textAttribs[cc].sound.name);
1771   }
1772 }
1773
1774
1775 void
1776 ResetSoundComboData(SoundComboData *scd)
1777 {
1778   while (scd->label) {
1779     if (scd->name != NULL) {
1780       free (scd->name);
1781       scd->name = NULL;
1782     }
1783     scd++;
1784   }
1785 }
1786
1787 void
1788 InitSoundCombo(HWND hwndCombo, SoundComboData *scd)
1789 {
1790   char buf[255];
1791   DWORD err;
1792   DWORD cnt = 0;
1793   SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0);
1794
1795   /* send the labels to the combo box */
1796   while (scd->label) {
1797     err = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) scd->label);
1798     if (err != cnt++) {
1799       sprintf(buf, "InitSoundCombo(): err '%d', cnt '%d'\n",
1800           (int)err, (int)cnt);
1801       MessageBox(NULL, buf, NULL, MB_OK);
1802     }
1803     scd++;
1804   }
1805   SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) 0, (LPARAM) 0);
1806 }
1807
1808 int
1809 SoundDialogWhichRadio(HWND hDlg)
1810 {
1811   if (IsDlgButtonChecked(hDlg, OPT_NoSound)) return OPT_NoSound;
1812   if (IsDlgButtonChecked(hDlg, OPT_DefaultBeep)) return OPT_DefaultBeep;
1813   if (IsDlgButtonChecked(hDlg, OPT_BuiltInSound)) return OPT_BuiltInSound;
1814   if (IsDlgButtonChecked(hDlg, OPT_WavFile)) return OPT_WavFile;
1815   return -1;
1816 }
1817
1818 VOID
1819 SoundDialogSetEnables(HWND hDlg, int radio)
1820 {
1821   EnableWindow(GetDlgItem(hDlg, OPT_BuiltInSoundName),
1822                radio == OPT_BuiltInSound);
1823   EnableWindow(GetDlgItem(hDlg, OPT_WavFileName), radio == OPT_WavFile);
1824   EnableWindow(GetDlgItem(hDlg, OPT_BrowseSound), radio == OPT_WavFile);
1825 }
1826
1827 char *
1828 SoundDialogGetName(HWND hDlg, int radio)
1829 {
1830   static char buf[MSG_SIZ], buf2[MSG_SIZ], buf3[MSG_SIZ];
1831   char *dummy, *ret;
1832   switch (radio) {
1833   case OPT_NoSound:
1834   default:
1835     return "";
1836   case OPT_DefaultBeep:
1837     return "$";
1838   case OPT_BuiltInSound:
1839     buf[0] = '!';
1840     GetDlgItemText(hDlg, OPT_BuiltInSoundName, buf + 1, sizeof(buf) - 1);
1841     return buf;
1842   case OPT_WavFile:
1843     GetDlgItemText(hDlg, OPT_WavFileName, buf, sizeof(buf));
1844     GetCurrentDirectory(MSG_SIZ, buf3);
1845     SetCurrentDirectory(installDir);
1846     if (GetFullPathName(buf, MSG_SIZ, buf2, &dummy)) {
1847       ret = buf2;
1848     } else {
1849       ret = buf;
1850     }
1851     SetCurrentDirectory(buf3);
1852     return ret;
1853   }
1854 }
1855
1856 void
1857 DisplaySelectedSound(HWND hDlg, HWND hCombo, const char *name)
1858 {
1859   int radio;
1860   /* 
1861    * I think it's best to clear the combo and edit boxes. It looks stupid
1862    * to have a value from another sound event sitting there grayed out.
1863    */
1864   SetDlgItemText(hDlg, OPT_WavFileName, "");
1865   SendMessage(hCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);
1866
1867   if (appData.debugMode)
1868       fprintf(debugFP, "DisplaySelectedSound(,,'%s'):\n", name);
1869   switch (name[0]) {
1870   case NULLCHAR:
1871     radio = OPT_NoSound;
1872     break;
1873   case '$':
1874     if (name[1] == NULLCHAR) {
1875       radio = OPT_DefaultBeep;
1876     } else {
1877       radio = OPT_WavFile;
1878       SetDlgItemText(hDlg, OPT_WavFileName, name);
1879     }
1880     break;
1881   case '!':
1882     if (name[1] == NULLCHAR) {
1883       radio = OPT_NoSound;
1884     } else {
1885       radio = OPT_BuiltInSound;
1886       if (SendMessage(hCombo, CB_SELECTSTRING, (WPARAM) -1, 
1887                       (LPARAM) (name + 1)) == CB_ERR) {
1888         SendMessage(hCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);
1889         SendMessage(hCombo, WM_SETTEXT, (WPARAM) 0, (LPARAM) (name + 1));
1890       }
1891     }
1892     break;
1893   default:
1894     radio = OPT_WavFile;
1895     SetDlgItemText(hDlg, OPT_WavFileName, name);
1896     break;
1897   }
1898   SoundDialogSetEnables(hDlg, radio);
1899   CheckRadioButton(hDlg, OPT_NoSound, OPT_WavFile, radio);
1900 }
1901     
1902
1903 char *builtInSoundNames[] = BUILT_IN_SOUND_NAMES;
1904
1905 LRESULT CALLBACK
1906 SoundOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1907 {
1908   static HWND hSoundCombo;
1909   static DWORD index;
1910   static HWND hBISN;
1911   int radio;
1912   MySound tmp;
1913   FILE *f;
1914   char buf[MSG_SIZ];
1915   char *newName;
1916   SoundClass sc;
1917   ColorClass cc;
1918   SoundComboData *scd;
1919
1920   switch (message) {
1921   case WM_INITDIALOG:
1922     /* Center the dialog over the application window */
1923     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
1924
1925     /* Initialize the built-in sounds combo */
1926     hBISN = GetDlgItem(hDlg, OPT_BuiltInSoundName);
1927      InitComboStrings(hBISN, builtInSoundNames);
1928
1929     /* Initialize the  sound events combo */
1930     index = 0;
1931     InitSoundComboData(soundComboData);
1932     hSoundCombo = GetDlgItem(hDlg, CBO_Sounds);
1933     InitSoundCombo(hSoundCombo, soundComboData);
1934
1935     /* update the dialog */
1936     DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name);
1937     return TRUE;
1938
1939   case WM_COMMAND: /* message: received a command */
1940
1941     if (((HWND)lParam == hSoundCombo) && 
1942         (HIWORD(wParam) == CBN_SELCHANGE)) {
1943       /* 
1944        * the user has selected a new sound event. We must store the name for
1945        * the previously selected event, then retrieve the name for the
1946        * newly selected event and update the dialog. 
1947        */
1948       radio = SoundDialogWhichRadio(hDlg);
1949       newName = strdup(SoundDialogGetName(hDlg, radio));
1950       
1951       if (strcmp(newName, soundComboData[index].name) != 0) {
1952         free(soundComboData[index].name);
1953         soundComboData[index].name = newName;
1954       } else {
1955         free(newName);
1956         newName = NULL;
1957       }
1958       /* now get the settings for the newly selected event */
1959       index = SendMessage(hSoundCombo, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
1960       DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name);
1961       
1962       return TRUE;
1963     }
1964     switch (LOWORD(wParam)) {
1965     case IDOK:
1966       /* 
1967        * save the name for the currently selected sound event 
1968        */
1969       radio = SoundDialogWhichRadio(hDlg);
1970       newName = strdup(SoundDialogGetName(hDlg, radio));
1971
1972       if (strcmp(soundComboData[index].name, newName) != 0) {
1973         free(soundComboData[index].name);
1974         soundComboData[index].name = newName;
1975       } else {
1976         free(newName);
1977         newName = NULL;
1978       }
1979
1980       /* save all the sound names that changed and load the sounds */
1981
1982       for ( sc = (SoundClass)0; sc < NSoundClasses; sc++) {
1983         if (strcmp(soundComboData[sc].name, sounds[sc].name) != 0) {
1984           free(sounds[sc].name);
1985           sounds[sc].name = strdup(soundComboData[sc].name);
1986           MyLoadSound(&sounds[sc]);
1987         }
1988       }
1989       for ( cc = (ColorClass)0; cc < NColorClasses - 2; cc++) {
1990         index = (int)cc + (int)NSoundClasses;
1991         if (strcmp(soundComboData[index].name, 
1992                    textAttribs[cc].sound.name) != 0) {
1993           free(textAttribs[cc].sound.name);
1994           textAttribs[cc].sound.name = strdup(soundComboData[index].name);
1995           MyLoadSound(&textAttribs[cc].sound);
1996         }
1997       }
1998
1999       ResetSoundComboData(soundComboData);
2000       EndDialog(hDlg, TRUE);
2001       return TRUE;
2002
2003     case IDCANCEL:
2004       ResetSoundComboData(soundComboData);
2005       EndDialog(hDlg, FALSE);
2006       return TRUE;
2007
2008     case OPT_DefaultSounds:
2009       /* can't use SetDefaultSounds() because we need to be able to "undo" if
2010        * user selects "Cancel" later on. So we do it the hard way here.
2011        */
2012       scd = &soundComboData[0];
2013       while (scd->label != NULL) {
2014         if (scd->name != NULL) free(scd->name);
2015         scd->name = strdup("");
2016         scd++;
2017       }
2018       free(soundComboData[(int)SoundBell].name);
2019       soundComboData[(int)SoundBell].name = strdup(SOUND_BELL);
2020       DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name);
2021       break;
2022
2023     case OPT_PlaySound:
2024       radio = SoundDialogWhichRadio(hDlg);
2025       tmp.name = strdup(SoundDialogGetName(hDlg, radio));
2026       tmp.data = NULL;
2027       MyLoadSound(&tmp);
2028       MyPlaySound(&tmp);
2029       if (tmp.data  != NULL) FreeResource(tmp.data); // technically obsolete fn, but tmp.data is NOT malloc'd mem
2030       if (tmp.name != NULL) free(tmp.name);
2031       return TRUE;
2032
2033     case OPT_BrowseSound:
2034       f = OpenFileDialog(hDlg, "rb", NULL, "wav", SOUND_FILT,
2035         "Browse for Sound File", NULL, NULL, buf);
2036       if (f != NULL) {
2037         fclose(f);
2038         SetDlgItemText(hDlg, OPT_WavFileName, buf);
2039       }
2040       return TRUE;
2041
2042     default:
2043       radio = SoundDialogWhichRadio(hDlg);
2044       SoundDialogSetEnables(hDlg, radio);
2045       break;
2046     }
2047     break;
2048   }
2049   return FALSE;
2050 }
2051
2052
2053 VOID SoundOptionsPopup(HWND hwnd)
2054 {
2055   FARPROC lpProc;
2056
2057   lpProc = MakeProcInstance((FARPROC)SoundOptionsDialog, hInst);
2058   DialogBox(hInst, MAKEINTRESOURCE(DLG_Sound), hwnd, (DLGPROC)lpProc);
2059   FreeProcInstance(lpProc);
2060 }
2061
2062
2063 /*---------------------------------------------------------------------------*\
2064  *
2065  * Comm Port dialog functions
2066  *
2067 \*---------------------------------------------------------------------------*/
2068
2069
2070 #define FLOW_NONE   0
2071 #define FLOW_XOFF   1
2072 #define FLOW_CTS    2
2073 #define FLOW_DSR    3
2074
2075 #define PORT_NONE
2076
2077 ComboData cdPort[]     = { {"None", PORT_NONE}, {"COM1", 1}, {"COM2", 2},
2078                            {"COM3", 3}, {"COM4", 4}, {NULL, 0} };
2079 ComboData cdDataRate[] = { {"110", 110}, {"300", 300}, {"600", 600}, {"1200", 1200},
2080                            {"2400", 2400}, {"4800", 4800}, {"9600", 9600}, {"19200", 19200},
2081                            {"38400", 38400}, {NULL, 0} };
2082 ComboData cdDataBits[] = { {"5", 5}, {"6", 6}, {"7", 7}, {"8", 8}, {NULL, 0} };
2083 ComboData cdParity[]   = { {"None", NOPARITY}, {"Odd", ODDPARITY}, {"Even", EVENPARITY},
2084                            {"Mark", MARKPARITY}, {"Space", SPACEPARITY}, {NULL, 0} };
2085 ComboData cdStopBits[] = { {"1", ONESTOPBIT}, {"1.5", ONE5STOPBITS},
2086                            {"2", TWOSTOPBITS}, {NULL, 0} };
2087 ComboData cdFlow[]     = { {"None", FLOW_NONE}, {"Xoff/Xon", FLOW_XOFF}, {"CTS", FLOW_CTS},
2088                            {"DSR", FLOW_DSR}, {NULL, 0} };
2089
2090
2091 VOID
2092 ParseCommSettings(char *arg, DCB *dcb)
2093 {
2094   int dataRate, count;
2095   char bits[MSG_SIZ], parity[MSG_SIZ], stopBits[MSG_SIZ], flow[MSG_SIZ];
2096   ComboData *cd;
2097   count = sscanf(arg, "%d%*[, ]%[^, ]%*[, ]%[^, ]%*[, ]%[^, ]%*[, ]%[^, ]",
2098     &dataRate, bits, parity, stopBits, flow);
2099   if (count != 5) goto cant_parse;
2100   dcb->BaudRate = dataRate;
2101   cd = cdDataBits;
2102   while (cd->label != NULL) {
2103     if (StrCaseCmp(cd->label, bits) == 0) {
2104       dcb->ByteSize = cd->value;
2105       break;
2106     }
2107     cd++;
2108   }
2109   if (cd->label == NULL) goto cant_parse;
2110   cd = cdParity;
2111   while (cd->label != NULL) {
2112     if (StrCaseCmp(cd->label, parity) == 0) {
2113       dcb->Parity = cd->value;
2114       break;
2115     }
2116     cd++;
2117   }
2118   if (cd->label == NULL) goto cant_parse;
2119   cd = cdStopBits;
2120   while (cd->label != NULL) {
2121     if (StrCaseCmp(cd->label, stopBits) == 0) {
2122       dcb->StopBits = cd->value;
2123       break;
2124     }
2125     cd++;
2126   }
2127   cd = cdFlow;
2128   if (cd->label == NULL) goto cant_parse;
2129   while (cd->label != NULL) {
2130     if (StrCaseCmp(cd->label, flow) == 0) {
2131       switch (cd->value) {
2132       case FLOW_NONE:
2133         dcb->fOutX = FALSE;
2134         dcb->fOutxCtsFlow = FALSE;
2135         dcb->fOutxDsrFlow = FALSE;
2136         break;
2137       case FLOW_CTS:
2138         dcb->fOutX = FALSE;
2139         dcb->fOutxCtsFlow = TRUE;
2140         dcb->fOutxDsrFlow = FALSE;
2141         break;
2142       case FLOW_DSR:
2143         dcb->fOutX = FALSE;
2144         dcb->fOutxCtsFlow = FALSE;
2145         dcb->fOutxDsrFlow = TRUE;
2146         break;
2147       case FLOW_XOFF:
2148         dcb->fOutX = TRUE;
2149         dcb->fOutxCtsFlow = FALSE;
2150         dcb->fOutxDsrFlow = FALSE;
2151         break;
2152       }
2153       break;
2154     }
2155     cd++;
2156   }
2157   if (cd->label == NULL) goto cant_parse;
2158   return;
2159 cant_parse:
2160     ExitArgError("Can't parse com port settings", arg);
2161 }
2162
2163
2164 VOID PrintCommSettings(FILE *f, char *name, DCB *dcb)
2165 {
2166   char *flow = "??", *parity = "??", *stopBits = "??";
2167   ComboData *cd;
2168   
2169   cd = cdParity;
2170   while (cd->label != NULL) {
2171     if (dcb->Parity == cd->value) {
2172       parity = cd->label;
2173       break;
2174     }
2175     cd++;
2176   }
2177   cd = cdStopBits;
2178   while (cd->label != NULL) {
2179     if (dcb->StopBits == cd->value) {
2180       stopBits = cd->label;
2181       break;
2182     }
2183     cd++;
2184   }
2185   if (dcb->fOutX) {
2186     flow = cdFlow[FLOW_XOFF].label;
2187   } else if (dcb->fOutxCtsFlow) {
2188     flow = cdFlow[FLOW_CTS].label;
2189   } else if (dcb->fOutxDsrFlow) {
2190     flow = cdFlow[FLOW_DSR].label;
2191   } else {
2192     flow = cdFlow[FLOW_NONE].label;
2193   }
2194   fprintf(f, "/%s=%d,%d,%s,%s,%s\n", name,
2195     (int)dcb->BaudRate, dcb->ByteSize, parity, stopBits, flow);
2196 }
2197
2198
2199 void
2200 InitCombo(HANDLE hwndCombo, ComboData *cd)
2201 {
2202   SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0);
2203
2204   while (cd->label != NULL) {
2205     SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) cd->label);
2206     cd++;
2207   }
2208 }
2209
2210 void
2211 SelectComboValue(HANDLE hwndCombo, ComboData *cd, unsigned value)
2212 {
2213   int i;
2214
2215   i = 0;
2216   while (cd->label != NULL) {
2217     if (cd->value == value) {
2218       SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) i, (LPARAM) 0);
2219       return;
2220     }
2221     cd++;
2222     i++;
2223   }
2224 }
2225
2226 LRESULT CALLBACK
2227 CommPortOptionsDialog(HWND hDlg, UINT message, WPARAM wParam,   LPARAM lParam)
2228 {
2229   char buf[MSG_SIZ];
2230   HANDLE hwndCombo;
2231   char *p;
2232   LRESULT index;
2233   unsigned value;
2234   int err;
2235
2236   switch (message) {
2237   case WM_INITDIALOG: /* message: initialize dialog box */
2238     /* Center the dialog over the application window */
2239     CenterWindow (hDlg, GetWindow(hDlg, GW_OWNER));
2240     /* Initialize the dialog items */
2241     /* !! There should probably be some synchronization
2242        in accessing hCommPort and dcb.  Or does modal nature
2243        of this dialog box do it for us?
2244        */
2245     hwndCombo = GetDlgItem(hDlg, OPT_Port);
2246     InitCombo(hwndCombo, cdPort);
2247     p = strrchr(appData.icsCommPort, '\\');
2248     if (p++ == NULL) p = appData.icsCommPort;
2249     if ((*p == '\0') ||
2250         (SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) p) == CB_ERR)) {
2251       SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) "None");
2252     }
2253     EnableWindow(hwndCombo, hCommPort == NULL); /*!! don't allow change for now*/
2254
2255     hwndCombo = GetDlgItem(hDlg, OPT_DataRate);
2256     InitCombo(hwndCombo, cdDataRate);
2257     sprintf(buf, "%u", (int)dcb.BaudRate);
2258     if (SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) buf) == CB_ERR) {
2259       SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);
2260       SendMessage(hwndCombo, WM_SETTEXT, (WPARAM) 0, (LPARAM) buf);
2261     }
2262
2263     hwndCombo = GetDlgItem(hDlg, OPT_Bits);
2264     InitCombo(hwndCombo, cdDataBits);
2265     SelectComboValue(hwndCombo, cdDataBits, dcb.ByteSize);
2266
2267     hwndCombo = GetDlgItem(hDlg, OPT_Parity);
2268     InitCombo(hwndCombo, cdParity);
2269     SelectComboValue(hwndCombo, cdParity, dcb.Parity);
2270
2271     hwndCombo = GetDlgItem(hDlg, OPT_StopBits);
2272     InitCombo(hwndCombo, cdStopBits);
2273     SelectComboValue(hwndCombo, cdStopBits, dcb.StopBits);
2274
2275     hwndCombo = GetDlgItem(hDlg, OPT_Flow);
2276     InitCombo(hwndCombo, cdFlow);
2277     if (dcb.fOutX) {
2278       SelectComboValue(hwndCombo, cdFlow, FLOW_XOFF);
2279     } else if (dcb.fOutxCtsFlow) {
2280       SelectComboValue(hwndCombo, cdFlow, FLOW_CTS);
2281     } else if (dcb.fOutxDsrFlow) {
2282       SelectComboValue(hwndCombo, cdFlow, FLOW_DSR);
2283     } else {
2284       SelectComboValue(hwndCombo, cdFlow, FLOW_NONE);
2285     }
2286     return TRUE;
2287
2288   case WM_COMMAND: /* message: received a command */
2289     switch (LOWORD(wParam)) {
2290     case IDOK:
2291       /* Read changed options from the dialog box */
2292 #ifdef NOTDEF
2293       /* !! Currently we can't change comm ports in midstream */
2294       hwndCombo = GetDlgItem(hDlg, OPT_Port);
2295       index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
2296       if (index == PORT_NONE) {
2297         appData.icsCommPort = "";
2298         if (hCommPort != NULL) {
2299           CloseHandle(hCommPort);
2300           hCommPort = NULL;
2301         }
2302         EndDialog(hDlg, TRUE);
2303         return TRUE;
2304       }
2305       SendMessage(hwndCombo, WM_GETTEXT, (WPARAM) MSG_SIZ, (LPARAM) buf);
2306       appData.icsCommPort = strdup(buf);
2307       if (hCommPort != NULL) {
2308         CloseHandle(hCommPort);
2309         hCommPort = NULL;
2310       }
2311       /* now what?? can't really do this; have to fix up the ChildProc
2312          and InputSource records for the comm port that we gave to the
2313          back end. */
2314 #endif /*NOTDEF*/
2315
2316       hwndCombo = GetDlgItem(hDlg, OPT_DataRate);
2317       SendMessage(hwndCombo, WM_GETTEXT, (WPARAM) MSG_SIZ, (LPARAM) buf);
2318       if (sscanf(buf, "%u", &value) != 1) {
2319         MessageBox(hDlg, "Invalid data rate",
2320                    "Option Error", MB_OK|MB_ICONEXCLAMATION);
2321         return TRUE;
2322       }
2323       dcb.BaudRate = value;
2324
2325       hwndCombo = GetDlgItem(hDlg, OPT_Bits);
2326       index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
2327       dcb.ByteSize = cdDataBits[index].value;
2328
2329       hwndCombo = GetDlgItem(hDlg, OPT_Parity);
2330       index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
2331       dcb.Parity = cdParity[index].value;
2332
2333       hwndCombo = GetDlgItem(hDlg, OPT_StopBits);
2334       index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
2335       dcb.StopBits = cdStopBits[index].value;
2336
2337       hwndCombo = GetDlgItem(hDlg, OPT_Flow);
2338       index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
2339       switch (cdFlow[index].value) {
2340       case FLOW_NONE:
2341         dcb.fOutX = FALSE;
2342         dcb.fOutxCtsFlow = FALSE;
2343         dcb.fOutxDsrFlow = FALSE;
2344         break;
2345       case FLOW_CTS:
2346         dcb.fOutX = FALSE;
2347         dcb.fOutxCtsFlow = TRUE;
2348         dcb.fOutxDsrFlow = FALSE;
2349         break;
2350       case FLOW_DSR:
2351         dcb.fOutX = FALSE;
2352         dcb.fOutxCtsFlow = FALSE;
2353         dcb.fOutxDsrFlow = TRUE;
2354         break;
2355       case FLOW_XOFF:
2356         dcb.fOutX = TRUE;
2357         dcb.fOutxCtsFlow = FALSE;
2358         dcb.fOutxDsrFlow = FALSE;
2359         break;
2360       }
2361       if (!SetCommState(hCommPort, (LPDCB) &dcb)) {
2362         err = GetLastError();
2363         switch(MessageBox(hDlg, 
2364                          "Failed to set comm port state;\r\ninvalid options?",
2365                          "Option Error", MB_ABORTRETRYIGNORE|MB_ICONQUESTION)) {
2366         case IDABORT:
2367           DisplayFatalError("Failed to set comm port state", err, 1);
2368           exit(1);  /*is it ok to do this from here?*/
2369
2370         case IDRETRY:
2371           return TRUE;
2372
2373         case IDIGNORE:
2374           EndDialog(hDlg, TRUE);
2375           return TRUE;
2376         }
2377       }
2378
2379       EndDialog(hDlg, TRUE);
2380       return TRUE;
2381
2382     case IDCANCEL:
2383       EndDialog(hDlg, FALSE);
2384       return TRUE;
2385
2386     default:
2387       break;
2388     }
2389     break;
2390   }
2391   return FALSE;
2392 }
2393
2394 VOID
2395 CommPortOptionsPopup(HWND hwnd)
2396 {
2397   FARPROC lpProc = MakeProcInstance((FARPROC)CommPortOptionsDialog, hInst);
2398   DialogBox(hInst, MAKEINTRESOURCE(DLG_CommPort), hwnd, (DLGPROC) lpProc);
2399   FreeProcInstance(lpProc);
2400 }
2401
2402 /*---------------------------------------------------------------------------*\
2403  *
2404  * Load Options dialog functions
2405  *
2406 \*---------------------------------------------------------------------------*/
2407
2408 VOID
2409 SetLoadOptionEnables(HWND hDlg)
2410 {
2411   UINT state;
2412
2413   state = IsDlgButtonChecked(hDlg, OPT_Autostep);
2414   EnableWindow(GetDlgItem(hDlg, OPT_ASTimeDelay), state);
2415   EnableWindow(GetDlgItem(hDlg, OPT_AStext1), state);
2416 }
2417
2418 LRESULT CALLBACK
2419 LoadOptions(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
2420 {
2421   char buf[MSG_SIZ];
2422   float fnumber;
2423
2424   switch (message) {
2425   case WM_INITDIALOG: /* message: initialize dialog box */
2426     /* Center the dialog over the application window */
2427     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
2428     /* Initialize the dialog items */
2429     if (appData.timeDelay >= 0.0) {
2430       CheckDlgButton(hDlg, OPT_Autostep, TRUE);
2431       sprintf(buf, "%.2g", appData.timeDelay);
2432       SetDlgItemText(hDlg, OPT_ASTimeDelay, buf);
2433     } else {
2434       CheckDlgButton(hDlg, OPT_Autostep, FALSE);
2435     }
2436     SetLoadOptionEnables(hDlg);
2437     return TRUE;
2438
2439   case WM_COMMAND: /* message: received a command */
2440     switch (LOWORD(wParam)) {
2441     case IDOK:
2442       /* Read changed options from the dialog box */
2443       if (IsDlgButtonChecked(hDlg, OPT_Autostep)) {
2444         GetDlgItemText(hDlg, OPT_ASTimeDelay, buf, MSG_SIZ);
2445         if (sscanf(buf, "%f", &fnumber) != 1) {
2446           MessageBox(hDlg, "Invalid load game step rate",
2447                      "Option Error", MB_OK|MB_ICONEXCLAMATION);
2448           return FALSE;
2449         }
2450         appData.timeDelay = fnumber;
2451       } else {
2452         appData.timeDelay = (float) -1.0;
2453       }
2454       EndDialog(hDlg, TRUE);
2455       return TRUE;
2456
2457     case IDCANCEL:
2458       EndDialog(hDlg, FALSE);
2459       return TRUE;
2460
2461     default:
2462       SetLoadOptionEnables(hDlg);
2463       break;
2464     }
2465     break;
2466   }
2467   return FALSE;
2468 }
2469
2470
2471 VOID 
2472 LoadOptionsPopup(HWND hwnd)
2473 {
2474   FARPROC lpProc = MakeProcInstance((FARPROC)LoadOptions, hInst);
2475   DialogBox(hInst, MAKEINTRESOURCE(DLG_LoadOptions), hwnd, (DLGPROC) lpProc);
2476   FreeProcInstance(lpProc);
2477 }
2478
2479 /*---------------------------------------------------------------------------*\
2480  *
2481  * Save Options dialog functions
2482  *
2483 \*---------------------------------------------------------------------------*/
2484
2485 VOID
2486 SetSaveOptionEnables(HWND hDlg)
2487 {
2488   UINT state;
2489
2490   state = IsDlgButtonChecked(hDlg, OPT_Autosave);
2491   EnableWindow(GetDlgItem(hDlg, OPT_AVPrompt), state);
2492   EnableWindow(GetDlgItem(hDlg, OPT_AVToFile), state);
2493   if (state && !IsDlgButtonChecked(hDlg, OPT_AVPrompt) &&
2494       !IsDlgButtonChecked(hDlg, OPT_AVToFile)) {
2495     CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVPrompt);
2496   }
2497
2498   state = state && IsDlgButtonChecked(hDlg, OPT_AVToFile);
2499   EnableWindow(GetDlgItem(hDlg, OPT_AVFilename), state);
2500   EnableWindow(GetDlgItem(hDlg, OPT_AVBrowse), state);
2501 }
2502
2503 LRESULT CALLBACK
2504 SaveOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
2505 {
2506   char buf[MSG_SIZ];
2507   FILE *f;
2508
2509   switch (message) {
2510   case WM_INITDIALOG: /* message: initialize dialog box */
2511     /* Center the dialog over the application window */
2512     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
2513     /* Initialize the dialog items */
2514     if (*appData.saveGameFile != NULLCHAR) {
2515       CheckDlgButton(hDlg, OPT_Autosave, (UINT) TRUE);
2516       CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVToFile);
2517       SetDlgItemText(hDlg, OPT_AVFilename, appData.saveGameFile);
2518     } else if (appData.autoSaveGames) {
2519       CheckDlgButton(hDlg, OPT_Autosave, (UINT) TRUE);
2520       CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVPrompt);
2521     } else {
2522       CheckDlgButton(hDlg, OPT_Autosave, (UINT) FALSE);
2523     }
2524     if (appData.oldSaveStyle) {
2525       CheckRadioButton(hDlg, OPT_PGN, OPT_Old, OPT_Old);
2526     } else {
2527       CheckRadioButton(hDlg, OPT_PGN, OPT_Old, OPT_PGN);
2528     }
2529     CheckDlgButton( hDlg, OPT_OutOfBookInfo, appData.saveOutOfBookInfo );
2530     SetSaveOptionEnables(hDlg);
2531     return TRUE;
2532
2533   case WM_COMMAND: /* message: received a command */
2534     switch (LOWORD(wParam)) {
2535     case IDOK:
2536       /* Read changed options from the dialog box */
2537       if (IsDlgButtonChecked(hDlg, OPT_Autosave)) {
2538         appData.autoSaveGames = TRUE;
2539         if (IsDlgButtonChecked(hDlg, OPT_AVPrompt)) {
2540           appData.saveGameFile = "";
2541         } else /*if (IsDlgButtonChecked(hDlg, OPT_AVToFile))*/ {
2542           GetDlgItemText(hDlg, OPT_AVFilename, buf, MSG_SIZ);
2543           if (*buf == NULLCHAR) {
2544             MessageBox(hDlg, "Invalid save game file name",
2545                        "Option Error", MB_OK|MB_ICONEXCLAMATION);
2546             return FALSE;
2547           }
2548           if ((isalpha(buf[0]) && buf[1] == ':') ||
2549             (buf[0] == '\\' && buf[1] == '\\')) {
2550             appData.saveGameFile = strdup(buf);
2551           } else {
2552             char buf2[MSG_SIZ], buf3[MSG_SIZ];
2553             char *dummy;
2554             GetCurrentDirectory(MSG_SIZ, buf3);
2555             SetCurrentDirectory(installDir);
2556             if (GetFullPathName(buf, MSG_SIZ, buf2, &dummy)) {
2557               appData.saveGameFile = strdup(buf2);
2558             } else {
2559               appData.saveGameFile = strdup(buf);
2560             }
2561             SetCurrentDirectory(buf3);
2562           }
2563         }
2564       } else {
2565         appData.autoSaveGames = FALSE;
2566         appData.saveGameFile = "";
2567       }
2568       appData.oldSaveStyle = IsDlgButtonChecked(hDlg, OPT_Old);
2569       appData.saveOutOfBookInfo = IsDlgButtonChecked( hDlg, OPT_OutOfBookInfo );
2570       EndDialog(hDlg, TRUE);
2571       return TRUE;
2572
2573     case IDCANCEL:
2574       EndDialog(hDlg, FALSE);
2575       return TRUE;
2576
2577     case OPT_AVBrowse:
2578       f = OpenFileDialog(hDlg, "a", NULL, 
2579                          appData.oldSaveStyle ? "gam" : "pgn", 
2580                          GAME_FILT, "Browse for Auto Save File", 
2581                          NULL, NULL, buf);
2582       if (f != NULL) {
2583         fclose(f);
2584         SetDlgItemText(hDlg, OPT_AVFilename, buf);
2585       }
2586       break;
2587
2588     default:
2589       SetSaveOptionEnables(hDlg);
2590       break;
2591     }
2592     break;
2593   }
2594   return FALSE;
2595 }
2596
2597 VOID
2598 SaveOptionsPopup(HWND hwnd)
2599 {
2600   FARPROC lpProc = MakeProcInstance((FARPROC)SaveOptionsDialog, hInst);
2601   DialogBox(hInst, MAKEINTRESOURCE(DLG_SaveOptions), hwnd, (DLGPROC) lpProc);
2602   FreeProcInstance(lpProc);
2603 }
2604
2605 /*---------------------------------------------------------------------------*\
2606  *
2607  * Time Control Options dialog functions
2608  *
2609 \*---------------------------------------------------------------------------*/
2610
2611 VOID
2612 SetTimeControlEnables(HWND hDlg)
2613 {
2614   UINT state;
2615
2616   state = IsDlgButtonChecked(hDlg, OPT_TCUseMoves);
2617   EnableWindow(GetDlgItem(hDlg, OPT_TCTime), state);
2618   EnableWindow(GetDlgItem(hDlg, OPT_TCMoves), state);
2619   EnableWindow(GetDlgItem(hDlg, OPT_TCtext1), state);
2620   EnableWindow(GetDlgItem(hDlg, OPT_TCtext2), state);
2621   EnableWindow(GetDlgItem(hDlg, OPT_TCTime2), !state);
2622   EnableWindow(GetDlgItem(hDlg, OPT_TCInc), !state);
2623   EnableWindow(GetDlgItem(hDlg, OPT_TCitext1), !state);
2624   EnableWindow(GetDlgItem(hDlg, OPT_TCitext2), !state);
2625   EnableWindow(GetDlgItem(hDlg, OPT_TCitext3), !state);
2626 }
2627
2628
2629 LRESULT CALLBACK
2630 TimeControl(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
2631 {
2632   char buf[MSG_SIZ];
2633   int mps, increment, odds1, odds2;
2634   BOOL ok, ok2;
2635
2636   switch (message) {
2637   case WM_INITDIALOG: /* message: initialize dialog box */
2638     /* Center the dialog over the application window */
2639     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
2640     /* Initialize the dialog items */
2641     if (appData.clockMode && !appData.icsActive) {
2642       if (appData.timeIncrement == -1) {
2643         CheckRadioButton(hDlg, OPT_TCUseMoves, OPT_TCUseInc,
2644                          OPT_TCUseMoves);
2645         SetDlgItemText(hDlg, OPT_TCTime, appData.timeControl);
2646         SetDlgItemInt(hDlg, OPT_TCMoves, appData.movesPerSession,
2647                       FALSE);
2648         SetDlgItemText(hDlg, OPT_TCTime2, "");
2649         SetDlgItemText(hDlg, OPT_TCInc, "");
2650       } else {
2651         CheckRadioButton(hDlg, OPT_TCUseMoves, OPT_TCUseInc,
2652                          OPT_TCUseInc);
2653         SetDlgItemText(hDlg, OPT_TCTime, "");
2654         SetDlgItemText(hDlg, OPT_TCMoves, "");
2655         SetDlgItemText(hDlg, OPT_TCTime2, appData.timeControl);
2656         SetDlgItemInt(hDlg, OPT_TCInc, appData.timeIncrement, FALSE);
2657       }
2658       SetDlgItemInt(hDlg, OPT_TCOdds1, 1, FALSE);
2659       SetDlgItemInt(hDlg, OPT_TCOdds2, 1, FALSE);
2660       SetTimeControlEnables(hDlg);
2661     }
2662     return TRUE;
2663
2664   case WM_COMMAND: /* message: received a command */
2665     switch (LOWORD(wParam)) {
2666     case IDOK:
2667       /* Read changed options from the dialog box */
2668       if (IsDlgButtonChecked(hDlg, OPT_TCUseMoves)) {
2669         increment = -1;
2670         mps = GetDlgItemInt(hDlg, OPT_TCMoves, &ok, FALSE);
2671         if (!ok || mps <= 0) {
2672           MessageBox(hDlg, "Invalid moves per time control",
2673                      "Option Error", MB_OK|MB_ICONEXCLAMATION);
2674           return FALSE;
2675         }
2676         GetDlgItemText(hDlg, OPT_TCTime, buf, MSG_SIZ);
2677         if (!ParseTimeControl(buf, increment, mps)) {
2678           MessageBox(hDlg, "Invalid minutes per time control",
2679                      "Option Error", MB_OK|MB_ICONEXCLAMATION);
2680           return FALSE;
2681         }
2682       } else {
2683         increment = GetDlgItemInt(hDlg, OPT_TCInc, &ok, FALSE);
2684         mps = appData.movesPerSession;
2685         if (!ok || increment < 0) {
2686           MessageBox(hDlg, "Invalid increment",
2687                      "Option Error", MB_OK|MB_ICONEXCLAMATION);
2688           return FALSE;
2689         }
2690         GetDlgItemText(hDlg, OPT_TCTime2, buf, MSG_SIZ);
2691         if (!ParseTimeControl(buf, increment, mps)) {
2692           MessageBox(hDlg, "Invalid initial time",
2693                      "Option Error", MB_OK|MB_ICONEXCLAMATION);
2694           return FALSE;
2695         }
2696       }
2697       odds1 = GetDlgItemInt(hDlg, OPT_TCOdds1, &ok, FALSE);
2698       odds2 = GetDlgItemInt(hDlg, OPT_TCOdds2, &ok2, FALSE);
2699       if (!ok || !ok2 || odds1 <= 0 || odds2 <= 0) {
2700           MessageBox(hDlg, "Invalid time-odds factor",
2701                      "Option Error", MB_OK|MB_ICONEXCLAMATION);
2702           return FALSE;
2703       }
2704       appData.timeControl = strdup(buf);
2705       appData.movesPerSession = mps;
2706       appData.timeIncrement = increment;
2707       appData.firstTimeOdds  = first.timeOdds  = odds1;
2708       appData.secondTimeOdds = second.timeOdds = odds2;
2709       Reset(TRUE, TRUE);
2710       EndDialog(hDlg, TRUE);
2711       return TRUE;
2712
2713     case IDCANCEL:
2714       EndDialog(hDlg, FALSE);
2715       return TRUE;
2716
2717     default:
2718       SetTimeControlEnables(hDlg);
2719       break;
2720     }
2721     break;
2722   }
2723   return FALSE;
2724 }
2725
2726 VOID
2727 TimeControlOptionsPopup(HWND hwnd)
2728 {
2729   if (gameMode != BeginningOfGame) {
2730     DisplayError("Changing time control during a game is not implemented", 0);
2731   } else {
2732     FARPROC lpProc = MakeProcInstance((FARPROC)TimeControl, hInst);
2733     DialogBox(hInst, MAKEINTRESOURCE(DLG_TimeControl), hwnd, (DLGPROC) lpProc);
2734     FreeProcInstance(lpProc);
2735   }
2736 }
2737
2738 /*---------------------------------------------------------------------------*\
2739  *
2740  * Engine Options Dialog functions
2741  *
2742 \*---------------------------------------------------------------------------*/
2743 #define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y))
2744 #define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x))
2745
2746 #define INT_ABS( n )    ((n) >= 0 ? (n) : -(n))
2747
2748 LRESULT CALLBACK EnginePlayOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
2749 {
2750   switch (message) {
2751   case WM_INITDIALOG: /* message: initialize dialog box */
2752
2753     /* Center the dialog over the application window */
2754     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
2755
2756     /* Initialize the dialog items */
2757     CHECK_BOX(IDC_EpPeriodicUpdates, appData.periodicUpdates);
2758     CHECK_BOX(IDC_EpPonder, appData.ponderNextMove);
2759     CHECK_BOX(IDC_EpShowThinking, appData.showThinking);
2760     CHECK_BOX(IDC_EpHideThinkingHuman, appData.hideThinkingFromHuman);
2761
2762     CHECK_BOX(IDC_TestClaims, appData.testClaims);
2763     CHECK_BOX(IDC_DetectMates, appData.checkMates);
2764     CHECK_BOX(IDC_MaterialDraws, appData.materialDraws);
2765     CHECK_BOX(IDC_TrivialDraws, appData.trivialDraws);
2766
2767     CHECK_BOX(IDC_ScoreAbs1, appData.firstScoreIsAbsolute);
2768     CHECK_BOX(IDC_ScoreAbs2, appData.secondScoreIsAbsolute);
2769
2770     SetDlgItemInt( hDlg, IDC_EpDrawMoveCount, appData.adjudicateDrawMoves, TRUE );
2771     SendDlgItemMessage( hDlg, IDC_EpDrawMoveCount, EM_SETSEL, 0, -1 );
2772
2773     SetDlgItemInt( hDlg, IDC_EpAdjudicationThreshold, INT_ABS(appData.adjudicateLossThreshold), TRUE );
2774     SendDlgItemMessage( hDlg, IDC_EpAdjudicationThreshold, EM_SETSEL, 0, -1 );
2775
2776     SetDlgItemInt( hDlg, IDC_RuleMoves, appData.ruleMoves, TRUE );
2777     SendDlgItemMessage( hDlg, IDC_RuleMoves, EM_SETSEL, 0, -1 );
2778
2779     SetDlgItemInt( hDlg, IDC_DrawRepeats, INT_ABS(appData.drawRepeats), TRUE );
2780     SendDlgItemMessage( hDlg, IDC_DrawRepeats, EM_SETSEL, 0, -1 );
2781
2782     return TRUE;
2783
2784   case WM_COMMAND: /* message: received a command */
2785     switch (LOWORD(wParam)) {
2786     case IDOK:
2787       /* Read changed options from the dialog box */
2788       PeriodicUpdatesEvent(          IS_CHECKED(IDC_EpPeriodicUpdates));
2789       PonderNextMoveEvent(           IS_CHECKED(IDC_EpPonder));
2790       appData.hideThinkingFromHuman= IS_CHECKED(IDC_EpHideThinkingHuman); // [HGM] thinking: moved up
2791 #if 0
2792       ShowThinkingEvent(             IS_CHECKED(IDC_EpShowThinking));
2793 #else
2794       appData.showThinking   = IS_CHECKED(IDC_EpShowThinking);
2795       ShowThinkingEvent(); // [HGM] thinking: tests all options that need thinking output
2796 #endif
2797       appData.testClaims    = IS_CHECKED(IDC_TestClaims);
2798       appData.checkMates    = IS_CHECKED(IDC_DetectMates);
2799       appData.materialDraws = IS_CHECKED(IDC_MaterialDraws);
2800       appData.trivialDraws  = IS_CHECKED(IDC_TrivialDraws);
2801
2802       appData.adjudicateDrawMoves = GetDlgItemInt(hDlg, IDC_EpDrawMoveCount, NULL, FALSE );
2803       appData.adjudicateLossThreshold = - (int) GetDlgItemInt(hDlg, IDC_EpAdjudicationThreshold, NULL, FALSE );
2804       appData.ruleMoves = GetDlgItemInt(hDlg, IDC_RuleMoves, NULL, FALSE );
2805       appData.drawRepeats = (int) GetDlgItemInt(hDlg, IDC_DrawRepeats, NULL, FALSE );
2806
2807       appData.firstScoreIsAbsolute  = IS_CHECKED(IDC_ScoreAbs1);
2808       appData.secondScoreIsAbsolute = IS_CHECKED(IDC_ScoreAbs2);
2809
2810       EndDialog(hDlg, TRUE);
2811       return TRUE;
2812
2813     case IDCANCEL:
2814       EndDialog(hDlg, FALSE);
2815       return TRUE;
2816
2817     case IDC_EpDrawMoveCount:
2818     case IDC_EpAdjudicationThreshold:
2819     case IDC_DrawRepeats:
2820     case IDC_RuleMoves:
2821         if( HIWORD(wParam) == EN_CHANGE ) {
2822             int n1_ok;
2823             int n2_ok;
2824             int n3_ok;
2825             int n4_ok;
2826
2827             GetDlgItemInt(hDlg, IDC_EpDrawMoveCount, &n1_ok, FALSE );
2828             GetDlgItemInt(hDlg, IDC_EpAdjudicationThreshold, &n2_ok, FALSE );
2829             GetDlgItemInt(hDlg, IDC_RuleMoves, &n3_ok, FALSE );
2830             GetDlgItemInt(hDlg, IDC_DrawRepeats, &n4_ok, FALSE );
2831
2832             EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok && n3_ok && n4_ok ? TRUE : FALSE );
2833         }
2834         return TRUE;
2835     }
2836     break;
2837   }
2838   return FALSE;
2839 }
2840
2841 VOID EnginePlayOptionsPopup(HWND hwnd)
2842 {
2843   FARPROC lpProc;
2844
2845   lpProc = MakeProcInstance((FARPROC)EnginePlayOptionsDialog, hInst);
2846   DialogBox(hInst, MAKEINTRESOURCE(DLG_EnginePlayOptions), hwnd, (DLGPROC) lpProc);
2847   FreeProcInstance(lpProc);
2848 }
2849
2850 /*---------------------------------------------------------------------------*\
2851  *
2852  * UCI Options Dialog functions
2853  *
2854 \*---------------------------------------------------------------------------*/
2855 static BOOL BrowseForFolder( const char * title, char * path )
2856 {
2857     BOOL result = FALSE;
2858     BROWSEINFO bi;
2859     LPITEMIDLIST pidl;
2860
2861     ZeroMemory( &bi, sizeof(bi) );
2862
2863     bi.lpszTitle = title == 0 ? "Choose Folder" : title;
2864     bi.ulFlags = BIF_RETURNONLYFSDIRS;
2865
2866     pidl = SHBrowseForFolder( &bi );
2867
2868     if( pidl != 0 ) {
2869         IMalloc * imalloc = 0;
2870
2871         if( SHGetPathFromIDList( pidl, path ) ) {
2872             result = TRUE;
2873         }
2874
2875         if( SUCCEEDED( SHGetMalloc ( &imalloc ) ) ) {
2876             imalloc->lpVtbl->Free(imalloc,pidl);
2877             imalloc->lpVtbl->Release(imalloc);
2878         }
2879     }
2880
2881     return result;
2882 }
2883
2884 LRESULT CALLBACK UciOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
2885 {
2886   char buf[MAX_PATH];
2887   int oldCores;
2888
2889   switch (message) {
2890   case WM_INITDIALOG: /* message: initialize dialog box */
2891
2892     /* Center the dialog over the application window */
2893     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
2894
2895     /* Initialize the dialog items */
2896     SetDlgItemText( hDlg, IDC_PolyglotDir, appData.polyglotDir );
2897     SetDlgItemInt( hDlg, IDC_HashSize, appData.defaultHashSize, TRUE );
2898     SetDlgItemText( hDlg, IDC_PathToEGTB, appData.defaultPathEGTB );
2899     SetDlgItemInt( hDlg, IDC_SizeOfEGTB, appData.defaultCacheSizeEGTB, TRUE );
2900     CheckDlgButton( hDlg, IDC_UseBook, (BOOL) appData.usePolyglotBook );
2901     SetDlgItemText( hDlg, IDC_BookFile, appData.polyglotBook );
2902     // [HGM] smp: input field for nr of cores:
2903     SetDlgItemInt( hDlg, IDC_Cores, appData.smpCores, TRUE );
2904     // [HGM] book: tick boxes for own book use
2905     CheckDlgButton( hDlg, IDC_OwnBook1, (BOOL) appData.firstHasOwnBookUCI );
2906     CheckDlgButton( hDlg, IDC_OwnBook2, (BOOL) appData.secondHasOwnBookUCI );
2907
2908     SendDlgItemMessage( hDlg, IDC_PolyglotDir, EM_SETSEL, 0, -1 );
2909
2910     return TRUE;
2911
2912   case WM_COMMAND: /* message: received a command */
2913     switch (LOWORD(wParam)) {
2914     case IDOK:
2915       GetDlgItemText( hDlg, IDC_PolyglotDir, buf, sizeof(buf) );
2916       appData.polyglotDir = strdup(buf);
2917       appData.defaultHashSize = GetDlgItemInt(hDlg, IDC_HashSize, NULL, FALSE );
2918       appData.defaultCacheSizeEGTB = GetDlgItemInt(hDlg, IDC_SizeOfEGTB, NULL, FALSE );
2919       GetDlgItemText( hDlg, IDC_PathToEGTB, buf, sizeof(buf) );
2920       appData.defaultPathEGTB = strdup(buf);
2921       GetDlgItemText( hDlg, IDC_BookFile, buf, sizeof(buf) );
2922       appData.polyglotBook = strdup(buf);
2923       appData.usePolyglotBook = (Boolean) IsDlgButtonChecked( hDlg, IDC_UseBook );
2924       // [HGM] smp: get nr of cores:
2925       oldCores = appData.smpCores;
2926       appData.smpCores = GetDlgItemInt(hDlg, IDC_Cores, NULL, FALSE );
2927       if(appData.smpCores != oldCores) NewSettingEvent(FALSE, "cores", appData.smpCores);
2928       // [HGM] book: read tick boxes for own book use
2929       appData.firstHasOwnBookUCI  = (Boolean) IsDlgButtonChecked( hDlg, IDC_OwnBook1 );
2930       appData.secondHasOwnBookUCI = (Boolean) IsDlgButtonChecked( hDlg, IDC_OwnBook2 );
2931
2932       if(gameMode == BeginningOfGame) Reset(TRUE, TRUE);
2933       EndDialog(hDlg, TRUE);
2934       return TRUE;
2935
2936     case IDCANCEL:
2937       EndDialog(hDlg, FALSE);
2938       return TRUE;
2939
2940     case IDC_BrowseForBook:
2941       {
2942           char filter[] = { 
2943               'A','l','l',' ','F','i','l','e','s', 0,
2944               '*','.','*', 0,
2945               'B','I','N',' ','F','i','l','e','s', 0,
2946               '*','.','b','i','n', 0,
2947               0 };
2948
2949           OPENFILENAME ofn;
2950
2951           strcpy( buf, "" );
2952
2953           ZeroMemory( &ofn, sizeof(ofn) );
2954
2955           ofn.lStructSize = sizeof(ofn);
2956           ofn.hwndOwner = hDlg;
2957           ofn.hInstance = hInst;
2958           ofn.lpstrFilter = filter;
2959           ofn.lpstrFile = buf;
2960           ofn.nMaxFile = sizeof(buf);
2961           ofn.lpstrTitle = "Choose Book";
2962           ofn.Flags = OFN_FILEMUSTEXIST | OFN_LONGNAMES | OFN_HIDEREADONLY;
2963
2964           if( GetOpenFileName( &ofn ) ) {
2965               SetDlgItemText( hDlg, IDC_BookFile, buf );
2966           }
2967       }
2968       return TRUE;
2969
2970     case IDC_BrowseForPolyglotDir:
2971       if( BrowseForFolder( "Choose Polyglot Directory", buf ) ) {
2972         SetDlgItemText( hDlg, IDC_PolyglotDir, buf );
2973
2974         strcat( buf, "\\polyglot.exe" );
2975
2976         if( GetFileAttributes(buf) == 0xFFFFFFFF ) {
2977             MessageBox( hDlg, "Polyglot was not found in the specified folder!", "Warning", MB_OK | MB_ICONWARNING );
2978         }
2979       }
2980       return TRUE;
2981
2982     case IDC_BrowseForEGTB:
2983       if( BrowseForFolder( "Choose EGTB Directory:", buf ) ) {
2984         SetDlgItemText( hDlg, IDC_PathToEGTB, buf );
2985       }
2986       return TRUE;
2987
2988     case IDC_HashSize:
2989     case IDC_SizeOfEGTB:
2990         if( HIWORD(wParam) == EN_CHANGE ) {
2991             int n1_ok;
2992             int n2_ok;
2993
2994             GetDlgItemInt(hDlg, IDC_HashSize, &n1_ok, FALSE );
2995             GetDlgItemInt(hDlg, IDC_SizeOfEGTB, &n2_ok, FALSE );
2996
2997             EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok ? TRUE : FALSE );
2998         }
2999         return TRUE;
3000     }
3001     break;
3002   }
3003   return FALSE;
3004 }
3005
3006 VOID UciOptionsPopup(HWND hwnd)
3007 {
3008   FARPROC lpProc;
3009
3010   lpProc = MakeProcInstance((FARPROC)UciOptionsDialog, hInst);
3011   DialogBox(hInst, MAKEINTRESOURCE(DLG_OptionsUCI), hwnd, (DLGPROC) lpProc);
3012   FreeProcInstance(lpProc);
3013 }