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