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