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