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