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